diff options
-rw-r--r-- | drivers/base/bus.c | 15 | ||||
-rw-r--r-- | drivers/base/dd.c | 15 |
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 */ |
485 | static int bus_rescan_devices_helper(struct device *dev, void *data) | 493 | static 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 | */ |
70 | int driver_probe_device(struct device_driver * drv, struct device * dev) | 71 | int 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 | */ |
127 | int device_attach(struct device * dev) | 130 | int 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 | ||
186 | static void __device_release_driver(struct device * dev) | 195 | static 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 | } |