aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r--drivers/base/dd.c15
1 files changed, 14 insertions, 1 deletions
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}