Commit 151ef38f authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

[PATCH] driver core: Add the ability to unbind drivers to devices from userspace

This adds a single file, "unbind", to the sysfs directory of every
device that is currently bound to a driver.  To unbind the driver from
the device, write anything to this file and they will be disconnected
from each other.
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 0edb5860
...@@ -133,6 +133,34 @@ static struct kobj_type ktype_bus = { ...@@ -133,6 +133,34 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL); decl_subsys(bus, &ktype_bus, NULL);
/* Manually detach a device from it's associated driver. */
static int driver_helper(struct device *dev, void *data)
{
const char *name = data;
if (strcmp(name, dev->bus_id) == 0)
return 1;
return 0;
}
static ssize_t driver_unbind(struct device_driver *drv,
const char *buf, size_t count)
{
struct bus_type *bus = get_bus(drv->bus);
struct device *dev;
int err = -ENODEV;
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if ((dev) &&
(dev->driver == drv)) {
device_release_driver(dev);
err = count;
}
return err;
}
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
static struct device * next_device(struct klist_iter * i) static struct device * next_device(struct klist_iter * i)
{ {
struct klist_node * n = klist_next(i); struct klist_node * n = klist_next(i);
...@@ -396,6 +424,7 @@ int bus_add_driver(struct device_driver * drv) ...@@ -396,6 +424,7 @@ int bus_add_driver(struct device_driver * drv)
module_add_driver(drv->owner, drv); module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv); driver_add_attrs(bus, drv);
driver_create_file(drv, &driver_attr_unbind);
} }
return error; return error;
} }
...@@ -413,6 +442,7 @@ int bus_add_driver(struct device_driver * drv) ...@@ -413,6 +442,7 @@ int bus_add_driver(struct device_driver * drv)
void bus_remove_driver(struct device_driver * drv) void bus_remove_driver(struct device_driver * drv)
{ {
if (drv->bus) { if (drv->bus) {
driver_remove_file(drv, &driver_attr_unbind);
driver_remove_attrs(drv->bus, drv); driver_remove_attrs(drv->bus, drv);
klist_remove(&drv->knode_bus); klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment