aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r--drivers/base/bus.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index fa601b085eba..29f6af554e71 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -152,7 +152,11 @@ static ssize_t driver_unbind(struct device_driver *drv,
152 152
153 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); 153 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
154 if (dev && dev->driver == drv) { 154 if (dev && dev->driver == drv) {
155 if (dev->parent) /* Needed for USB */
156 down(&dev->parent->sem);
155 device_release_driver(dev); 157 device_release_driver(dev);
158 if (dev->parent)
159 up(&dev->parent->sem);
156 err = count; 160 err = count;
157 } 161 }
158 put_device(dev); 162 put_device(dev);
@@ -175,9 +179,13 @@ static ssize_t driver_bind(struct device_driver *drv,
175 179
176 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); 180 dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
177 if (dev && dev->driver == NULL) { 181 if (dev && dev->driver == NULL) {
182 if (dev->parent) /* Needed for USB */
183 down(&dev->parent->sem);
178 down(&dev->sem); 184 down(&dev->sem);
179 err = driver_probe_device(drv, dev); 185 err = driver_probe_device(drv, dev);
180 up(&dev->sem); 186 up(&dev->sem);
187 if (dev->parent)
188 up(&dev->parent->sem);
181 } 189 }
182 put_device(dev); 190 put_device(dev);
183 put_bus(bus); 191 put_bus(bus);
@@ -420,6 +428,26 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr
420 } 428 }
421} 429}
422 430
431#ifdef CONFIG_HOTPLUG
432/*
433 * Thanks to drivers making their tables __devinit, we can't allow manual
434 * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
435 */
436static void add_bind_files(struct device_driver *drv)
437{
438 driver_create_file(drv, &driver_attr_unbind);
439 driver_create_file(drv, &driver_attr_bind);
440}
441
442static void remove_bind_files(struct device_driver *drv)
443{
444 driver_remove_file(drv, &driver_attr_bind);
445 driver_remove_file(drv, &driver_attr_unbind);
446}
447#else
448static inline void add_bind_files(struct device_driver *drv) {}
449static inline void remove_bind_files(struct device_driver *drv) {}
450#endif
423 451
424/** 452/**
425 * bus_add_driver - Add a driver to the bus. 453 * bus_add_driver - Add a driver to the bus.
@@ -449,8 +477,7 @@ int bus_add_driver(struct device_driver * drv)
449 module_add_driver(drv->owner, drv); 477 module_add_driver(drv->owner, drv);
450 478
451 driver_add_attrs(bus, drv); 479 driver_add_attrs(bus, drv);
452 driver_create_file(drv, &driver_attr_unbind); 480 add_bind_files(drv);
453 driver_create_file(drv, &driver_attr_bind);
454 } 481 }
455 return error; 482 return error;
456} 483}
@@ -468,8 +495,7 @@ int bus_add_driver(struct device_driver * drv)
468void bus_remove_driver(struct device_driver * drv) 495void bus_remove_driver(struct device_driver * drv)
469{ 496{
470 if (drv->bus) { 497 if (drv->bus) {
471 driver_remove_file(drv, &driver_attr_bind); 498 remove_bind_files(drv);
472 driver_remove_file(drv, &driver_attr_unbind);
473 driver_remove_attrs(drv->bus, drv); 499 driver_remove_attrs(drv->bus, drv);
474 klist_remove(&drv->knode_bus); 500 klist_remove(&drv->knode_bus);
475 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); 501 pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
@@ -484,8 +510,13 @@ void bus_remove_driver(struct device_driver * drv)
484/* Helper for bus_rescan_devices's iter */ 510/* Helper for bus_rescan_devices's iter */
485static int bus_rescan_devices_helper(struct device *dev, void *data) 511static int bus_rescan_devices_helper(struct device *dev, void *data)
486{ 512{
487 if (!dev->driver) 513 if (!dev->driver) {
514 if (dev->parent) /* Needed for USB */
515 down(&dev->parent->sem);
488 device_attach(dev); 516 device_attach(dev);
517 if (dev->parent)
518 up(&dev->parent->sem);
519 }
489 return 0; 520 return 0;
490} 521}
491 522