dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if (dev && dev->driver == drv) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
device_release_driver(dev);
+ if (dev->parent)
+ up(&dev->parent->sem);
err = count;
}
put_device(dev);
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if (dev && dev->driver == NULL) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
err = driver_probe_device(drv, dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
}
put_device(dev);
put_bus(bus);
/* Helper for bus_rescan_devices's iter */
static int bus_rescan_devices_helper(struct device *dev, void *data)
{
- if (!dev->driver)
+ if (!dev->driver) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
device_attach(dev);
+ if (dev->parent)
+ up(&dev->parent->sem);
+ }
return 0;
}
* 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)
{
*
* 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)
{
* 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;
}
* 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)
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);
}
}