Index: lib/libdevctl/devctl.h =================================================================== --- lib/libdevctl/devctl.h +++ lib/libdevctl/devctl.h @@ -38,5 +38,6 @@ int devctl_suspend(const char *device); int devctl_resume(const char *device); int devctl_set_driver(const char *device, const char *driver, bool force); +int devctl_rescan(const char *device); #endif /* !__DEVCTL_H__ */ Index: lib/libdevctl/devctl.3 =================================================================== --- lib/libdevctl/devctl.3 +++ lib/libdevctl/devctl.3 @@ -34,6 +34,7 @@ .Nm devctl_detach , .Nm devctl_disable , .Nm devctl_enable , +.Nm devctl_rescan , .Nm devctl_resume , .Nm devctl_set_driver , .Nm devctl_suspend @@ -51,6 +52,8 @@ .Ft int .Fn devctl_enable "const char *device" .Ft int +.Fn devctl_rescan "const char *device" +.Ft int .Fn devctl_resume "const char *device" .Ft int .Fn devctl_set_driver "const char *device" "const char *driver" "bool force" @@ -149,9 +152,14 @@ is true, the device will be detached from its current device driver before it is attached to the new device driver. +.Pp +The +.Fn devctl_rescan +function rescans a bus device checking for devices that have been added or +removed. .Sh RETURN VALUES .Rv -std devctl_attach devctl_detach devctl_disable devctl_enable \ -devctl_suspend devctl_resume devctl_set_driver +devctl_suspend devctl_rescan devctl_resume devctl_set_driver .Sh ERRORS In addition to specific errors noted below, all of the @@ -280,6 +288,16 @@ .It Bq Er ENXIO The new device driver failed to attach. .El +.Pp +The +.Fn devctl_rescan +function may fail if: +.Bl -tag -width Er +.It Bq Er ENXIO +The device is not attached to a driver. +.It Bq Er ENXIO +The bus driver does not support rescanning. +.El .Sh SEE ALSO .Xr devinfo 3 , .Xr devstat 3 , Index: lib/libdevctl/devctl.c =================================================================== --- lib/libdevctl/devctl.c +++ lib/libdevctl/devctl.c @@ -122,3 +122,10 @@ req.dr_flags |= DEVF_SET_DRIVER_DETACH; return (devctl_request(DEV_SET_DRIVER, &req)); } + +int +devctl_rescan(const char *device) +{ + + return (devctl_simple_request(DEV_RESCAN, device, 0)); +} Index: share/man/man9/BUS_RESCAN.9 =================================================================== --- /dev/null +++ share/man/man9/BUS_RESCAN.9 @@ -0,0 +1,51 @@ +.\" -*- nroff -*- +.\" +.\" Copyright (c) 2016 John H. Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 19, 2016 +.Dt BUS_RESCAN 9 +.Os +.Sh NAME +.Nm BUS_RESCAN +.Nd "rescan a bus checking for devices that have been added or removed" +.Sh SYNOPSIS +.In sys/param.h +.In sys/bus.h +.Ft void +.Fn BUS_RESCAN "device_t dev" +.Sh DESCRIPTION +The +.Fn BUS_RESCAN +method is called to request a rescan of the child devices on a bus device. +The method should add any devices that have been added since the previous +scan and remove devices that have been removed. +This method is not required to re-examine existing devices to determine if +their properties have changed. +This method is also not required to propagate the rescan request to child +devices. +.Sh SEE ALSO +.Xr device 9 Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile +++ share/man/man9/Makefile @@ -44,6 +44,7 @@ BUS_NEW_PASS.9 \ BUS_PRINT_CHILD.9 \ BUS_READ_IVAR.9 \ + BUS_RESCAN.9 \ bus_release_resource.9 \ bus_set_pass.9 \ bus_set_resource.9 \ Index: sys/kern/bus_if.m =================================================================== --- sys/kern/bus_if.m +++ sys/kern/bus_if.m @@ -232,6 +232,19 @@ } DEFAULT null_add_child; /** + * @brief Rescan the bus + * + * This method is called by a parent bridge or devctl to trigger a bus + * rescan. The rescan should delete devices no longer present and + * enumerate devices that have newly arrived. + * + * @param _dev the bus device + */ +METHOD int rescan { + device_t _dev; +} + +/** * @brief Allocate a system resource * * This method is called by child devices of a bus to allocate resources. Index: sys/kern/subr_bus.c =================================================================== --- sys/kern/subr_bus.c +++ sys/kern/subr_bus.c @@ -5203,6 +5203,7 @@ case DEV_SUSPEND: case DEV_RESUME: case DEV_SET_DRIVER: + case DEV_RESCAN: error = priv_check(td, PRIV_DRIVER); if (error == 0) error = find_device(req, &dev); @@ -5366,6 +5367,13 @@ error = device_probe_and_attach(dev); break; } + case DEV_RESCAN: + if (!device_is_attached(dev)) { + error = ENXIO; + break; + } + error = BUS_RESCAN(dev); + break; } mtx_unlock(&Giant); return (error); Index: sys/sys/bus.h =================================================================== --- sys/sys/bus.h +++ sys/sys/bus.h @@ -117,6 +117,7 @@ #define DEV_SUSPEND _IOW('D', 5, struct devreq) #define DEV_RESUME _IOW('D', 6, struct devreq) #define DEV_SET_DRIVER _IOW('D', 7, struct devreq) +#define DEV_RESCAN _IOW('D', 9, struct devreq) /* Flags for DEV_DETACH and DEV_DISABLE. */ #define DEVF_FORCE_DETACH 0x0000001 Index: usr.sbin/devctl/devctl.8 =================================================================== --- usr.sbin/devctl/devctl.8 +++ usr.sbin/devctl/devctl.8 @@ -56,6 +56,9 @@ .Cm set driver .Op Fl f .Ar device driver +.Nm +.Cm rescan +.Ar device .Sh DESCRIPTION The .Nm @@ -126,6 +129,9 @@ .Fl f flag is not specified, the device will not be changed. +.It Cm rescan Ar device +Rescan a bus device checking for devices that have been added or +removed. .El .Sh SEE ALSO .Xr devctl 3 , Index: usr.sbin/devctl/devctl.c =================================================================== --- usr.sbin/devctl/devctl.c +++ usr.sbin/devctl/devctl.c @@ -259,6 +259,18 @@ } DEVCTL_COMMAND(set, driver, set_driver); +static int +rescan(int ac, char **av) +{ + + if (ac != 2) + usage(); + if (devctl_rescan(av[1]) < 0) + err(1, "Failed to rescan %s", av[1]); + return (0); +} +DEVCTL_COMMAND(top, rescan, rescan); + int main(int ac, char *av[]) {