}
static int generic_remove (struct device *dev)
{
+ struct usb_device *udev = to_usb_device(dev);
+
+ /* if this is only an unbind, not a physical disconnect, then
+ * unconfigure the device */
+ if (udev->state == USB_STATE_CONFIGURED)
+ usb_set_configuration(udev, 0);
+
+ /* in case the call failed or the device was suspended */
+ if (udev->state >= USB_STATE_CONFIGURED)
+ usb_disable_device(udev, 0);
return 0;
}
/* if interface was already added, bind now; else let
* the future device_add() bind it, bypassing probe()
*/
- if (!klist_node_attached (&dev->knode_bus))
+ if (device_is_registered(dev))
device_bind_driver(dev);
return 0;
if (!dev->driver || dev->driver != &driver->driver)
return;
- /* don't disconnect from disconnect(), or before dev_add() */
- if (!klist_node_attached(&dev->knode_driver) && !klist_node_attached(&dev->knode_bus))
+ /* don't release from within disconnect() */
+ if (iface->condition != USB_INTERFACE_BOUND)
+ return;
+
+ /* don't release if the interface hasn't been added yet */
+ if (device_is_registered(dev)) {
+ iface->condition = USB_INTERFACE_UNBINDING;
device_release_driver(dev);
+ }
dev->driver = NULL;
usb_set_intfdata(iface, NULL);
* is neither BINDING nor BOUND. Rather than sleeping to wait for the
* lock, the routine polls repeatedly. This is to prevent deadlock with
* disconnect; in some drivers (such as usb-storage) the disconnect()
- * callback will block waiting for a device reset to complete.
+ * or suspend() method will block waiting for a device reset to complete.
*
* Returns a negative error code for failure, otherwise 1 or 0 to indicate
* that the device will or will not have to be unlocked. (0 can be
int usb_lock_device_for_reset(struct usb_device *udev,
struct usb_interface *iface)
{
+ unsigned long jiffies_expire = jiffies + HZ;
+
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
if (udev->state == USB_STATE_SUSPENDED)
}
while (!usb_trylock_device(udev)) {
+
+ /* If we can't acquire the lock after waiting one second,
+ * we're probably deadlocked */
+ if (time_after(jiffies, jiffies_expire))
+ return -EBUSY;
+
msleep(15);
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
void *usb_buffer_alloc (
struct usb_device *dev,
size_t size,
- int mem_flags,
+ gfp_t mem_flags,
dma_addr_t *dma
)
{
driver = to_usb_driver(dev->driver);
/* there's only one USB suspend state */
- if (intf->dev.power.power_state)
+ if (intf->dev.power.power_state.event)
return 0;
if (driver->suspend)
retval = usb_major_init();
if (retval)
goto major_init_failed;
+ retval = usb_register(&usbfs_driver);
+ if (retval)
+ goto driver_register_failed;
+ retval = usbdev_init();
+ if (retval)
+ goto usbdevice_init_failed;
retval = usbfs_init();
if (retval)
goto fs_init_failed;
retval = usb_hub_init();
if (retval)
goto hub_init_failed;
-
retval = driver_register(&usb_generic_driver);
if (!retval)
goto out;
hub_init_failed:
usbfs_cleanup();
fs_init_failed:
- usb_major_cleanup();
+ usbdev_cleanup();
+usbdevice_init_failed:
+ usb_deregister(&usbfs_driver);
+driver_register_failed:
+ usb_major_cleanup();
major_init_failed:
usb_host_cleanup();
host_init_failed:
driver_unregister(&usb_generic_driver);
usb_major_cleanup();
usbfs_cleanup();
+ usb_deregister(&usbfs_driver);
+ usbdev_cleanup();
usb_hub_cleanup();
usb_host_cleanup();
bus_unregister(&usb_bus_type);
EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_disabled);
+EXPORT_SYMBOL_GPL(usb_get_intf);
+EXPORT_SYMBOL_GPL(usb_put_intf);
+
EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_put_dev);
EXPORT_SYMBOL(usb_get_dev);