summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/base.h1
-rw-r--r--drivers/base/bus.c26
-rw-r--r--drivers/base/dd.c2
3 files changed, 28 insertions, 1 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 645f62692920..783752b68a9a 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -5,6 +5,7 @@ extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
extern void driver_detach(struct device_driver * drv);
+extern int driver_probe_device(struct device_driver *, struct device *);
static inline struct class_device *to_class_dev(struct kobject *obj)
{
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index fa41ee90a53a..7e17488271a8 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -160,6 +160,30 @@ static ssize_t driver_unbind(struct device_driver *drv,
}
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
+/*
+ * Manually attach a device to a driver.
+ * Note: the driver must want to bind to the device,
+ * it is not possible to override the driver's id table.
+ */
+static ssize_t driver_bind(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 == NULL)) {
+ down(&dev->sem);
+ err = driver_probe_device(drv, dev);
+ up(&dev->sem);
+ put_device(dev);
+ }
+ return err;
+}
+static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+
static struct device * next_device(struct klist_iter * i)
{
@@ -425,6 +449,7 @@ int bus_add_driver(struct device_driver * drv)
driver_add_attrs(bus, drv);
driver_create_file(drv, &driver_attr_unbind);
+ driver_create_file(drv, &driver_attr_bind);
}
return error;
}
@@ -442,6 +467,7 @@ int bus_add_driver(struct device_driver * drv)
void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
+ driver_remove_file(drv, &driver_attr_bind);
driver_remove_file(drv, &driver_attr_unbind);
driver_remove_attrs(drv->bus, drv);
klist_remove(&drv->knode_bus);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6db3a789c54f..16323f9cbff0 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,7 @@ void device_bind_driver(struct device * dev)
*
* This function must be called with @dev->sem held.
*/
-static int driver_probe_device(struct device_driver * drv, struct device * dev)
+int driver_probe_device(struct device_driver * drv, struct device * dev)
{
int ret = 0;