summaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2006-01-05 08:52:11 -0800
committerTony Luck <tony.luck@intel.com>2006-01-05 08:52:11 -0800
commit5c3eee79128c372a81a83665be2332a000944280 (patch)
treee44331d36d63adc971003cc32540d0cb0c019525 /drivers/base/dd.c
parent408045afbdb46e109a1a44e67af688e9ddf7ad66 (diff)
parentdb9edfd7e339ca4113153d887e782dd05be5a9eb (diff)
Auto-update from upstream
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 3b419c9a1e7..2b905016664 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
* This function returns 1 if a match is found, an error if one
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
*
- * This function must be called with @dev->sem held.
+ * This function must be called with @dev->sem held. When called
+ * for a USB interface, @dev->parent->sem must be held as well.
*/
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
@@ -123,6 +124,8 @@ static int __device_attach(struct device_driver * drv, void * data)
*
* Returns 1 if the device was bound to a driver;
* 0 if no matching device was found; error code otherwise.
+ *
+ * When called for a USB interface, @dev->parent->sem must be held.
*/
int device_attach(struct device * dev)
{
@@ -152,10 +155,14 @@ static int __driver_attach(struct device * dev, void * data)
* is an error.
*/
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver)
driver_probe_device(drv, dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
return 0;
}
@@ -181,6 +188,8 @@ void driver_attach(struct device_driver * drv)
* Manually detach device from driver.
*
* __device_release_driver() must be called with @dev->sem held.
+ * When called for a USB interface, @dev->parent->sem must be held
+ * as well.
*/
static void __device_release_driver(struct device * dev)
@@ -233,10 +242,14 @@ void driver_detach(struct device_driver * drv)
get_device(dev);
spin_unlock(&drv->klist_devices.k_lock);
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
if (dev->driver == drv)
__device_release_driver(dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
put_device(dev);
}
}