aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/bus.c15
-rw-r--r--drivers/base/dd.c15
2 files changed, 28 insertions, 2 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index fa601b085eba..e3f915a24891 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);
@@ -484,8 +492,13 @@ void bus_remove_driver(struct device_driver * drv)
484/* Helper for bus_rescan_devices's iter */ 492/* Helper for bus_rescan_devices's iter */
485static int bus_rescan_devices_helper(struct device *dev, void *data) 493static int bus_rescan_devices_helper(struct device *dev, void *data)
486{ 494{
487 if (!dev->driver) 495 if (!dev->driver) {
496 if (dev->parent) /* Needed for USB */
497 down(&dev->parent->sem);
488 device_attach(dev); 498 device_attach(dev);
499 if (dev->parent)
500 up(&dev->parent->sem);
501 }
489 return 0; 502 return 0;
490} 503}
491 504
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3b419c9a1e7e..2b905016664d 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
65 * This function returns 1 if a match is found, an error if one 65 * This function returns 1 if a match is found, an error if one
66 * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise. 66 * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
67 * 67 *
68 * This function must be called with @dev->sem held. 68 * This function must be called with @dev->sem held. When called
69 * for a USB interface, @dev->parent->sem must be held as well.
69 */ 70 */
70int driver_probe_device(struct device_driver * drv, struct device * dev) 71int driver_probe_device(struct device_driver * drv, struct device * dev)
71{ 72{
@@ -123,6 +124,8 @@ static int __device_attach(struct device_driver * drv, void * data)
123 * 124 *
124 * Returns 1 if the device was bound to a driver; 125 * Returns 1 if the device was bound to a driver;
125 * 0 if no matching device was found; error code otherwise. 126 * 0 if no matching device was found; error code otherwise.
127 *
128 * When called for a USB interface, @dev->parent->sem must be held.
126 */ 129 */
127int device_attach(struct device * dev) 130int device_attach(struct device * dev)
128{ 131{
@@ -152,10 +155,14 @@ static int __driver_attach(struct device * dev, void * data)
152 * is an error. 155 * is an error.
153 */ 156 */
154 157
158 if (dev->parent) /* Needed for USB */
159 down(&dev->parent->sem);
155 down(&dev->sem); 160 down(&dev->sem);
156 if (!dev->driver) 161 if (!dev->driver)
157 driver_probe_device(drv, dev); 162 driver_probe_device(drv, dev);
158 up(&dev->sem); 163 up(&dev->sem);
164 if (dev->parent)
165 up(&dev->parent->sem);
159 166
160 return 0; 167 return 0;
161} 168}
@@ -181,6 +188,8 @@ void driver_attach(struct device_driver * drv)
181 * Manually detach device from driver. 188 * Manually detach device from driver.
182 * 189 *
183 * __device_release_driver() must be called with @dev->sem held. 190 * __device_release_driver() must be called with @dev->sem held.
191 * When called for a USB interface, @dev->parent->sem must be held
192 * as well.
184 */ 193 */
185 194
186static void __device_release_driver(struct device * dev) 195static void __device_release_driver(struct device * dev)
@@ -233,10 +242,14 @@ void driver_detach(struct device_driver * drv)
233 get_device(dev); 242 get_device(dev);
234 spin_unlock(&drv->klist_devices.k_lock); 243 spin_unlock(&drv->klist_devices.k_lock);
235 244
245 if (dev->parent) /* Needed for USB */
246 down(&dev->parent->sem);
236 down(&dev->sem); 247 down(&dev->sem);
237 if (dev->driver == drv) 248 if (dev->driver == drv)
238 __device_release_driver(dev); 249 __device_release_driver(dev);
239 up(&dev->sem); 250 up(&dev->sem);
251 if (dev->parent)
252 up(&dev->parent->sem);
240 put_device(dev); 253 put_device(dev);
241 } 254 }
242} 255}