diff options
author | jhb <jhb@FreeBSD.org> | 2016-09-30 22:05:47 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2016-09-30 22:05:47 +0000 |
commit | 0f41551ef9dde560d9d191d7190af02904dbf611 (patch) | |
tree | 00567e70252000c0a9f26250a859dfd20c8e1348 /sys/kern | |
parent | c03db820416e89f29bd1f5cb8f59a221d4d11463 (diff) | |
download | FreeBSD-src-0f41551ef9dde560d9d191d7190af02904dbf611.zip FreeBSD-src-0f41551ef9dde560d9d191d7190af02904dbf611.tar.gz |
MFC 305034: Implement 'devctl clear driver' to undo a previous 'set driver'.
Add a new 'clear driver' command for devctl along with the accompanying
ioctl and devctl_clear_driver() library routine to reset a device to
use a wildcard devclass instead of a fixed devclass. This can be used
to undo a previous 'set driver' command. After the device's name has
been reset to permit wildcard names, it is reprobed so that it can
attach to newly-available (to it) device drivers.
Sponsored by: Chelsio Communications
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_bus.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index aba4364..6ccda55 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -5069,6 +5069,7 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, case DEV_ENABLE: case DEV_DISABLE: case DEV_SET_DRIVER: + case DEV_CLEAR_DRIVER: error = priv_check(td, PRIV_DRIVER); if (error == 0) error = find_device(req, &dev); @@ -5210,6 +5211,25 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, error = device_probe_and_attach(dev); break; } + case DEV_CLEAR_DRIVER: + if (!(dev->flags & DF_FIXEDCLASS)) { + error = 0; + break; + } + if (device_is_attached(dev)) { + if (req->dr_flags & DEVF_CLEAR_DRIVER_DETACH) + error = device_detach(dev); + else + error = EBUSY; + if (error) + break; + } + + dev->flags &= ~DF_FIXEDCLASS; + dev->flags |= DF_WILDCARD; + devclass_delete_device(dev->devclass, dev); + error = device_probe_and_attach(dev); + break; } mtx_unlock(&Giant); return (error); |