X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fusb.c;h=02426d0b9a347f514f69b4c4f706bb9c5a48caef;hb=refs%2Fheads%2Fvserver;hp=de2edfb08582eebf24b8cc94f7e975a693c9e01a;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index de2edfb08..02426d0b9 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1,5 +1,5 @@ /* - * drivers/usb/usb.c + * drivers/usb/core/usb.c * * (C) Copyright Linus Torvalds 1999 * (C) Copyright Johannes Erdfelt 1999-2001 @@ -21,14 +21,6 @@ * are evil. */ -#include - -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - #include #include #include @@ -40,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -49,141 +43,13 @@ #include "hcd.h" #include "usb.h" -extern int usb_hub_init(void); -extern void usb_hub_cleanup(void); -extern int usb_major_init(void); -extern void usb_major_cleanup(void); -extern int usb_host_init(void); -extern void usb_host_cleanup(void); - const char *usbcore_name = "usbcore"; -int nousb; /* Disable USB when built into kernel image */ - /* Not honored on modular build */ - - -static int generic_probe (struct device *dev) -{ - return 0; -} -static int generic_remove (struct device *dev) -{ - return 0; -} - -static struct device_driver usb_generic_driver = { - .name = "usb", - .bus = &usb_bus_type, - .probe = generic_probe, - .remove = generic_remove, -}; - -static int usb_generic_driver_data; - -/* called from driver core with usb_bus_type.subsys writelock */ -int usb_probe_interface(struct device *dev) -{ - struct usb_interface * intf = to_usb_interface(dev); - struct usb_driver * driver = to_usb_driver(dev->driver); - const struct usb_device_id *id; - int error = -ENODEV; - - dev_dbg(dev, "%s\n", __FUNCTION__); - - if (!driver->probe) - return error; - if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) - return -EHOSTUNREACH; - - id = usb_match_id (intf, driver->id_table); - if (id) { - dev_dbg (dev, "%s - got id\n", __FUNCTION__); - error = driver->probe (intf, id); - } - - return error; -} - -/* called from driver core with usb_bus_type.subsys writelock */ -int usb_unbind_interface(struct device *dev) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct usb_driver *driver = to_usb_driver(intf->dev.driver); - - /* release all urbs for this interface */ - usb_disable_interface(interface_to_usbdev(intf), intf); - - if (driver && driver->disconnect) - driver->disconnect(intf); - - /* reset other interface state */ - usb_set_interface(interface_to_usbdev(intf), - intf->altsetting[0].desc.bInterfaceNumber, - 0); - usb_set_intfdata(intf, NULL); - - return 0; -} - -/** - * usb_register - register a USB driver - * @new_driver: USB operations for the driver - * - * Registers a USB driver with the USB core. The list of unattached - * interfaces will be rescanned whenever a new driver is added, allowing - * the new driver to attach to any recognized devices. - * Returns a negative error code on failure and 0 on success. - * - * NOTE: if you want your driver to use the USB major number, you must call - * usb_register_dev() to enable that functionality. This function no longer - * takes care of that. - */ -int usb_register(struct usb_driver *new_driver) -{ - int retval = 0; - - if (nousb) - return -ENODEV; - - new_driver->driver.name = (char *)new_driver->name; - new_driver->driver.bus = &usb_bus_type; - new_driver->driver.probe = usb_probe_interface; - new_driver->driver.remove = usb_unbind_interface; +static int nousb; /* Disable USB when built into kernel image */ - retval = driver_register(&new_driver->driver); +struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ - if (!retval) { - pr_info("%s: registered new driver %s\n", - usbcore_name, new_driver->name); - usbfs_update_special(); - } else { - printk(KERN_ERR "%s: error %d registering driver %s\n", - usbcore_name, retval, new_driver->name); - } - - return retval; -} - -/** - * usb_deregister - unregister a USB driver - * @driver: USB operations of the driver to unregister - * Context: must be able to sleep - * - * Unlinks the specified driver from the internal USB driver list. - * - * NOTE: If you called usb_register_dev(), you still need to call - * usb_deregister_dev() to clean up your driver's allocated minor numbers, - * this * call will no longer do it for you. - */ -void usb_deregister(struct usb_driver *driver) -{ - pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); - - driver_unregister (&driver->driver); - - usbfs_update_special(); -} /** * usb_ifnum_to_if - get the interface object with a given interface number @@ -202,9 +68,10 @@ void usb_deregister(struct usb_driver *driver) * alternate settings available for this interfaces. * * Don't call this function unless you are bound to one of the interfaces - * on this device or you own the dev->serialize semaphore! + * on this device or you have locked the device! */ -struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) +struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, + unsigned ifnum) { struct usb_host_config *config = dev->actconfig; int i; @@ -235,10 +102,10 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) * drivers avoid such mistakes. * * Don't call this function unless you are bound to the intf interface - * or you own the device's ->serialize semaphore! + * or you have locked the device! */ -struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, - unsigned int altnum) +struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf, + unsigned int altnum) { int i; @@ -249,243 +116,26 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, return NULL; } -/** - * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number - * @dev: the device whose current configuration+altsettings is considered - * @epnum: the desired endpoint, masked with USB_DIR_IN as appropriate. - * - * This walks the device descriptor for the currently active configuration, - * and returns a pointer to the endpoint with that particular endpoint - * number, or null. - * - * Note that interface descriptors are not required to list endpoint - * numbers in any standardized order, so that it would be wrong to - * assume that ep2in precedes either ep5in, ep2out, or even ep1out. - * This routine helps device drivers avoid such mistakes. - */ -struct usb_endpoint_descriptor * -usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) -{ - struct usb_host_config *config = dev->actconfig; - int i, k; - - if (!config) - return NULL; - for (i = 0; i < config->desc.bNumInterfaces; i++) { - struct usb_interface *intf; - struct usb_host_interface *alt; - - /* only endpoints in current altsetting are active */ - intf = config->interface[i]; - alt = intf->cur_altsetting; - - for (k = 0; k < alt->desc.bNumEndpoints; k++) - if (epnum == alt->endpoint[k].desc.bEndpointAddress) - return &alt->endpoint[k].desc; - } - - return NULL; -} - -/** - * usb_driver_claim_interface - bind a driver to an interface - * @driver: the driver to be bound - * @iface: the interface to which it will be bound; must be in the - * usb device's active configuration - * @priv: driver data associated with that interface - * - * This is used by usb device drivers that need to claim more than one - * interface on a device when probing (audio and acm are current examples). - * No device driver should directly modify internal usb_interface or - * usb_device structure members. - * - * Few drivers should need to use this routine, since the most natural - * way to bind to an interface is to return the private data from - * the driver's probe() method. - * - * Callers must own the driver model's usb bus writelock. So driver - * probe() entries don't need extra locking, but other call contexts - * may need to explicitly claim that lock. - */ -int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) -{ - struct device *dev = &iface->dev; - - if (dev->driver) - return -EBUSY; - - dev->driver = &driver->driver; - usb_set_intfdata(iface, priv); - - /* if interface was already added, bind now; else let - * the future device_add() bind it, bypassing probe() - */ - if (!list_empty (&dev->bus_list)) - device_bind_driver(dev); - - return 0; -} - -/** - * usb_driver_release_interface - unbind a driver from an interface - * @driver: the driver to be unbound - * @iface: the interface from which it will be unbound - * - * This can be used by drivers to release an interface without waiting - * for their disconnect() methods to be called. In typical cases this - * also causes the driver disconnect() method to be called. - * - * This call is synchronous, and may not be used in an interrupt context. - * Callers must own the usb_device serialize semaphore and the driver model's - * usb bus writelock. So driver disconnect() entries don't need extra locking, - * but other call contexts may need to explicitly claim those locks. - */ -void usb_driver_release_interface(struct usb_driver *driver, - struct usb_interface *iface) -{ - struct device *dev = &iface->dev; - - /* this should never happen, don't release something that's not ours */ - if (!dev->driver || dev->driver != &driver->driver) - return; - - /* don't disconnect from disconnect(), or before dev_add() */ - if (!list_empty (&dev->driver_list) && !list_empty (&dev->bus_list)) - device_release_driver(dev); - - dev->driver = NULL; - usb_set_intfdata(iface, NULL); -} +struct find_interface_arg { + int minor; + struct usb_interface *interface; +}; -/** - * usb_match_id - find first usb_device_id matching device or interface - * @interface: the interface of interest - * @id: array of usb_device_id structures, terminated by zero entry - * - * usb_match_id searches an array of usb_device_id's and returns - * the first one matching the device or interface, or null. - * This is used when binding (or rebinding) a driver to an interface. - * Most USB device drivers will use this indirectly, through the usb core, - * but some layered driver frameworks use it directly. - * These device tables are exported with MODULE_DEVICE_TABLE, through - * modutils and "modules.usbmap", to support the driver loading - * functionality of USB hotplugging. - * - * What Matches: - * - * The "match_flags" element in a usb_device_id controls which - * members are used. If the corresponding bit is set, the - * value in the device_id must match its corresponding member - * in the device or interface descriptor, or else the device_id - * does not match. - * - * "driver_info" is normally used only by device drivers, - * but you can create a wildcard "matches anything" usb_device_id - * as a driver's "modules.usbmap" entry if you provide an id with - * only a nonzero "driver_info" field. If you do this, the USB device - * driver's probe() routine should use additional intelligence to - * decide whether to bind to the specified interface. - * - * What Makes Good usb_device_id Tables: - * - * The match algorithm is very simple, so that intelligence in - * driver selection must come from smart driver id records. - * Unless you have good reasons to use another selection policy, - * provide match elements only in related groups, and order match - * specifiers from specific to general. Use the macros provided - * for that purpose if you can. - * - * The most specific match specifiers use device descriptor - * data. These are commonly used with product-specific matches; - * the USB_DEVICE macro lets you provide vendor and product IDs, - * and you can also match against ranges of product revisions. - * These are widely used for devices with application or vendor - * specific bDeviceClass values. - * - * Matches based on device class/subclass/protocol specifications - * are slightly more general; use the USB_DEVICE_INFO macro, or - * its siblings. These are used with single-function devices - * where bDeviceClass doesn't specify that each interface has - * its own class. - * - * Matches based on interface class/subclass/protocol are the - * most general; they let drivers bind to any interface on a - * multiple-function device. Use the USB_INTERFACE_INFO - * macro, or its siblings, to match class-per-interface style - * devices (as recorded in bDeviceClass). - * - * Within those groups, remember that not all combinations are - * meaningful. For example, don't give a product version range - * without vendor and product IDs; or specify a protocol without - * its associated class and subclass. - */ -const struct usb_device_id * -usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) +static int __find_interface(struct device * dev, void * data) { - struct usb_host_interface *intf; - struct usb_device *dev; - - /* proc_connectinfo in devio.c may call us with id == NULL. */ - if (id == NULL) - return NULL; - - intf = interface->cur_altsetting; - dev = interface_to_usbdev(interface); - - /* It is important to check that id->driver_info is nonzero, - since an entry that is all zeroes except for a nonzero - id->driver_info is the way to create an entry that - indicates that the driver want to examine every - device and interface. */ - for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || - id->driver_info; id++) { - - if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - id->idVendor != dev->descriptor.idVendor) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - id->idProduct != dev->descriptor.idProduct) - continue; - - /* No need to test id->bcdDevice_lo != 0, since 0 is never - greater than any unsigned number. */ - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && - (id->bcdDevice_lo > dev->descriptor.bcdDevice)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && - (id->bcdDevice_hi < dev->descriptor.bcdDevice)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && - (id->bDeviceClass != dev->descriptor.bDeviceClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && - (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && - (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && - (id->bInterfaceClass != intf->desc.bInterfaceClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && - (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) - continue; + struct find_interface_arg *arg = data; + struct usb_interface *intf; - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && - (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) - continue; + /* can't look at usb devices, only interfaces */ + if (is_usb_device(dev)) + return 0; - return id; + intf = to_usb_interface(dev); + if (intf->minor != -1 && intf->minor == arg->minor) { + arg->interface = intf; + return 1; } - - return NULL; + return 0; } /** @@ -499,198 +149,90 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { - struct list_head *entry; - struct device *dev; - struct usb_interface *intf; - - list_for_each(entry, &drv->driver.devices) { - dev = container_of(entry, struct device, driver_list); - - /* can't look at usb devices, only interfaces */ - if (dev->driver == &usb_generic_driver) - continue; - - intf = to_usb_interface(dev); - if (intf->minor == -1) - continue; - if (intf->minor == minor) - return intf; - } + struct find_interface_arg argb; + int retval; - /* no device found that matches */ - return NULL; + argb.minor = minor; + argb.interface = NULL; + /* eat the error, it will be in argb.interface */ + retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, + __find_interface); + return argb.interface; } -static int usb_device_match (struct device *dev, struct device_driver *drv) +/** + * usb_release_dev - free a usb device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this usb device are + * done. + */ +static void usb_release_dev(struct device *dev) { - struct usb_interface *intf; - struct usb_driver *usb_drv; - const struct usb_device_id *id; + struct usb_device *udev; - /* check for generic driver, which we don't match any device with */ - if (drv == &usb_generic_driver) - return 0; + udev = to_usb_device(dev); - intf = to_usb_interface(dev); +#ifdef CONFIG_USB_SUSPEND + cancel_delayed_work(&udev->autosuspend); + flush_workqueue(ksuspend_usb_wq); +#endif + usb_destroy_configuration(udev); + usb_put_hcd(bus_to_hcd(udev->bus)); + kfree(udev->product); + kfree(udev->manufacturer); + kfree(udev->serial); + kfree(udev); +} - usb_drv = to_usb_driver(drv); - id = usb_drv->id_table; - - id = usb_match_id (intf, usb_drv->id_table); - if (id) - return 1; +#ifdef CONFIG_PM +static int ksuspend_usb_init(void) +{ + ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd"); + if (!ksuspend_usb_wq) + return -ENOMEM; return 0; } - -#ifdef CONFIG_HOTPLUG - -/* - * USB hotplugging invokes what /proc/sys/kernel/hotplug says - * (normally /sbin/hotplug) when USB devices get added or removed. - * - * This invokes a user mode policy agent, typically helping to load driver - * or other modules, configure the device, and more. Drivers can provide - * a MODULE_DEVICE_TABLE to help with module loading subtasks. - * - * We're called either from khubd (the typical case) or from root hub - * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle - * delays in event delivery. Use sysfs (and DEVPATH) to make sure the - * device (and this configuration!) are still present. - */ -static int usb_hotplug (struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static void ksuspend_usb_cleanup(void) { - struct usb_interface *intf; - struct usb_device *usb_dev; - char *scratch; - int i = 0; - int length = 0; - - if (!dev) - return -ENODEV; - - /* driver is often null here; dev_dbg() would oops */ - pr_debug ("usb %s: hotplug\n", dev->bus_id); - - /* Must check driver_data here, as on remove driver is always NULL */ - if ((dev->driver == &usb_generic_driver) || - (dev->driver_data == &usb_generic_driver_data)) - return 0; - - intf = to_usb_interface(dev); - usb_dev = interface_to_usbdev (intf); - - if (usb_dev->devnum < 0) { - pr_debug ("usb %s: already deleted?\n", dev->bus_id); - return -ENODEV; - } - if (!usb_dev->bus) { - pr_debug ("usb %s: bus removed?\n", dev->bus_id); - return -ENODEV; - } - - scratch = buffer; - -#ifdef CONFIG_USB_DEVICEFS - /* If this is available, userspace programs can directly read - * all the device descriptors we don't tell them about. Or - * even act as usermode drivers. - * - * FIXME reduce hardwired intelligence here - */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, - "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; -#endif + destroy_workqueue(ksuspend_usb_wq); +} - /* per-device configurations are common */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, "PRODUCT=%x/%x/%x", - usb_dev->descriptor.idVendor, - usb_dev->descriptor.idProduct, - usb_dev->descriptor.bcdDevice); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; - - /* class-based driver binding models */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; - - if (usb_dev->descriptor.bDeviceClass == 0) { - struct usb_host_interface *alt = intf->cur_altsetting; - - /* 2.4 only exposed interface zero. in 2.5, hotplug - * agents are called for all interfaces, and can use - * $DEVPATH/bInterfaceNumber if necessary. - */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, - "INTERFACE=%d/%d/%d", - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; +#ifdef CONFIG_USB_SUSPEND - } - envp[i++] = NULL; +/* usb_autosuspend_work - callback routine to autosuspend a USB device */ +static void usb_autosuspend_work(struct work_struct *work) +{ + struct usb_device *udev = + container_of(work, struct usb_device, autosuspend.work); - return 0; + usb_pm_lock(udev); + udev->auto_pm = 1; + usb_suspend_both(udev, PMSG_SUSPEND); + usb_pm_unlock(udev); } #else -static int usb_hotplug (struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - return -ENODEV; -} +static void usb_autosuspend_work(struct work_struct *work) +{} -#endif /* CONFIG_HOTPLUG */ +#endif /* CONFIG_USB_SUSPEND */ -/** - * usb_release_dev - free a usb device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this usb device are - * done. - */ -static void usb_release_dev(struct device *dev) -{ - struct usb_device *udev; +#else - udev = to_usb_device(dev); +#define ksuspend_usb_init() 0 +#define ksuspend_usb_cleanup() do {} while (0) - if (udev->bus && udev->bus->op && udev->bus->op->deallocate) - udev->bus->op->deallocate(udev); - usb_destroy_configuration(udev); - usb_bus_put(udev->bus); - kfree (udev); -} +#endif /* CONFIG_PM */ /** * usb_alloc_dev - usb device constructor (usbcore-internal) * @parent: hub to which device is connected; null to allocate a root hub * @bus: bus used to access the device - * @port: zero based index of port; ignored for root hubs + * @port1: one-based index of port; ignored for root hubs * Context: !in_interrupt () * * Only hub drivers (including virtual root hub drivers for host @@ -699,18 +241,15 @@ static void usb_release_dev(struct device *dev) * This call may not be used in a non-sleeping context. */ struct usb_device * -usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port) +usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) { struct usb_device *dev; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; - memset(dev, 0, sizeof(*dev)); - - bus = usb_bus_get(bus); - if (!bus) { + if (!usb_get_hcd(bus_to_hcd(bus))) { kfree(dev); return NULL; } @@ -718,11 +257,18 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port) device_initialize(&dev->dev); dev->dev.bus = &usb_bus_type; dev->dev.dma_mask = bus->controller->dma_mask; - dev->dev.driver_data = &usb_generic_driver_data; - dev->dev.driver = &usb_generic_driver; dev->dev.release = usb_release_dev; dev->state = USB_STATE_ATTACHED; + /* This magic assignment distinguishes devices from interfaces */ + dev->dev.platform_data = &usb_generic_driver; + + INIT_LIST_HEAD(&dev->ep0.urb_list); + dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; + dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; + /* ep0 maxpacket comes later, from device descriptor */ + dev->ep_in[0] = dev->ep_out[0] = &dev->ep0; + /* Save readable and stable topology id, distinguishing devices * by location for diagnostics, tools, driver model, etc. The * string is a path along hub ports, from the root. Each device's @@ -740,10 +286,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port) /* match any labeling on the hubs; it's one-based */ if (parent->devpath [0] == '0') snprintf (dev->devpath, sizeof dev->devpath, - "%d", port + 1); + "%d", port1); else snprintf (dev->devpath, sizeof dev->devpath, - "%s.%d", parent->devpath, port + 1); + "%s.%d", parent->devpath, port1); dev->dev.parent = &parent->dev; sprintf (&dev->dev.bus_id[0], "%d-%s", @@ -752,15 +298,15 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port) /* hub driver sets up TT records */ } + dev->portnum = port1; dev->bus = bus; dev->parent = parent; INIT_LIST_HEAD(&dev->filelist); - init_MUTEX(&dev->serialize); - - if (dev->bus->op->allocate) - dev->bus->op->allocate(dev); - +#ifdef CONFIG_PM + mutex_init(&dev->pm_mutex); + INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); +#endif return dev; } @@ -830,6 +376,80 @@ void usb_put_intf(struct usb_interface *intf) put_device(&intf->dev); } + +/* USB device locking + * + * USB devices and interfaces are locked using the semaphore in their + * embedded struct device. The hub driver guarantees that whenever a + * device is connected or disconnected, drivers are called with the + * USB device locked as well as their particular interface. + * + * Complications arise when several devices are to be locked at the same + * time. Only hub-aware drivers that are part of usbcore ever have to + * do this; nobody else needs to worry about it. The rule for locking + * is simple: + * + * When locking both a device and its parent, always lock the + * the parent first. + */ + +/** + * usb_lock_device_for_reset - cautiously acquire the lock for a + * usb device structure + * @udev: device that's being locked + * @iface: interface bound to the driver making the request (optional) + * + * Attempts to acquire the device lock, but fails if the device is + * NOTATTACHED or SUSPENDED, or if iface is specified and the interface + * 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() + * 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 + * returned when an interface is given and is BINDING, because in that + * case the driver already owns the device lock.) + */ +int usb_lock_device_for_reset(struct usb_device *udev, + const struct usb_interface *iface) +{ + unsigned long jiffies_expire = jiffies + HZ; + + if (udev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + if (udev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + if (iface) { + switch (iface->condition) { + case USB_INTERFACE_BINDING: + return 0; + case USB_INTERFACE_BOUND: + break; + default: + return -EINTR; + } + } + + while (usb_trylock_device(udev) != 0) { + + /* 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; + if (udev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + if (iface && iface->condition != USB_INTERFACE_BOUND) + return -EINTR; + } + return 1; +} + + static struct usb_device *match_device(struct usb_device *dev, u16 vendor_id, u16 product_id) { @@ -837,12 +457,12 @@ static struct usb_device *match_device(struct usb_device *dev, int child; dev_dbg(&dev->dev, "check for vendor %04x, product %04x ...\n", - dev->descriptor.idVendor, - dev->descriptor.idProduct); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); /* see if this device matches */ - if ((dev->descriptor.idVendor == vendor_id) && - (dev->descriptor.idProduct == product_id)) { + if ((vendor_id == le16_to_cpu(dev->descriptor.idVendor)) && + (product_id == le16_to_cpu(dev->descriptor.idProduct))) { dev_dbg (&dev->dev, "matched this device!\n"); ret_dev = usb_get_dev(dev); goto exit; @@ -851,8 +471,10 @@ static struct usb_device *match_device(struct usb_device *dev, /* look through all of the children of this device */ for (child = 0; child < dev->maxchild; ++child) { if (dev->children[child]) { + usb_lock_device(dev->children[child]); ret_dev = match_device(dev->children[child], vendor_id, product_id); + usb_unlock_device(dev->children[child]); if (ret_dev) goto exit; } @@ -880,19 +502,21 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) struct usb_bus *bus; struct usb_device *dev = NULL; - down(&usb_bus_list_lock); + mutex_lock(&usb_bus_list_lock); for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { bus = container_of(buslist, struct usb_bus, bus_list); if (!bus->root_hub) continue; + usb_lock_device(bus->root_hub); dev = match_device(bus->root_hub, vendor_id, product_id); + usb_unlock_device(bus->root_hub); if (dev) goto exit; } exit: - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return dev; } @@ -911,7 +535,7 @@ exit: */ int usb_get_current_frame_number(struct usb_device *dev) { - return dev->bus->op->get_frame_number (dev); + return usb_hcd_get_frame_number (dev); } /*-------------------------------------------------------------------*/ @@ -972,13 +596,13 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, void *usb_buffer_alloc ( struct usb_device *dev, size_t size, - int mem_flags, + gfp_t mem_flags, dma_addr_t *dma ) { - if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc) + if (!dev || !dev->bus) return NULL; - return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma); + return hcd_buffer_alloc (dev->bus, size, mem_flags, dma); } /** @@ -999,9 +623,11 @@ void usb_buffer_free ( dma_addr_t dma ) { - if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free) - return; - dev->bus->op->buffer_free (dev->bus, size, addr, dma); + if (!dev || !dev->bus) + return; + if (!addr) + return; + hcd_buffer_free (dev->bus, size, addr, dma); } /** @@ -1020,6 +646,7 @@ void usb_buffer_free ( * * Reverse the effect of this call with usb_buffer_unmap(). */ +#if 0 struct urb *usb_buffer_map (struct urb *urb) { struct usb_bus *bus; @@ -1049,6 +676,7 @@ struct urb *usb_buffer_map (struct urb *urb) | URB_NO_SETUP_DMA_MAP); return urb; } +#endif /* 0 */ /* XXX DISABLED, no users currently. If you wish to re-enable this * XXX please determine whether the sync is to transfer ownership of @@ -1093,6 +721,7 @@ void usb_buffer_dmasync (struct urb *urb) * * Reverses the effect of usb_buffer_map(). */ +#if 0 void usb_buffer_unmap (struct urb *urb) { struct usb_bus *bus; @@ -1119,6 +748,7 @@ void usb_buffer_unmap (struct urb *urb) urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); } +#endif /* 0 */ /** * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint @@ -1146,8 +776,8 @@ void usb_buffer_unmap (struct urb *urb) * * Reverse the effect of this call with usb_buffer_unmap_sg(). */ -int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int nents) +int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int nents) { struct usb_bus *bus; struct device *controller; @@ -1181,8 +811,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, * Use this when you are re-using a scatterlist's data buffers for * another USB request. */ -void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int n_hw_ents) +void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int n_hw_ents) { struct usb_bus *bus; struct device *controller; @@ -1207,8 +837,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, * * Reverses the effect of usb_buffer_map_sg(). */ -void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int n_hw_ents) +void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int n_hw_ents) { struct usb_bus *bus; struct device *controller; @@ -1223,67 +853,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } -static int usb_generic_suspend(struct device *dev, u32 state) -{ - struct usb_interface *intf; - struct usb_driver *driver; - - if (dev->driver == &usb_generic_driver) - return usb_suspend_device (to_usb_device(dev), state); - - if ((dev->driver == NULL) || - (dev->driver_data == &usb_generic_driver_data)) - return 0; - - intf = to_usb_interface(dev); - driver = to_usb_driver(dev->driver); - - if (driver->suspend) - return driver->suspend(intf, state); - return 0; -} - -static int usb_generic_resume(struct device *dev) -{ - struct usb_interface *intf; - struct usb_driver *driver; - - /* devices resume through their hub */ - if (dev->driver == &usb_generic_driver) - return usb_resume_device (to_usb_device(dev)); - - if ((dev->driver == NULL) || - (dev->driver_data == &usb_generic_driver_data)) - return 0; - - intf = to_usb_interface(dev); - driver = to_usb_driver(dev->driver); - - if (driver->resume) - return driver->resume(intf); - return 0; -} - -struct bus_type usb_bus_type = { - .name = "usb", - .match = usb_device_match, - .hotplug = usb_hotplug, - .suspend = usb_generic_suspend, - .resume = usb_generic_resume, -}; - -#ifndef MODULE - -static int __init usb_setup_disable(char *str) -{ - nousb = 1; - return 1; -} - /* format to disable USB on kernel command line is: nousb */ -__setup("nousb", usb_setup_disable); - -#endif +__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); /* * for external read access to @@ -1304,23 +875,31 @@ static int __init usb_init(void) return 0; } + retval = ksuspend_usb_init(); + if (retval) + goto out; retval = bus_register(&usb_bus_type); if (retval) - goto out; + goto bus_register_failed; retval = usb_host_init(); if (retval) goto host_init_failed; 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); + retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE); if (!retval) goto out; @@ -1328,11 +907,17 @@ static int __init usb_init(void) 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: bus_unregister(&usb_bus_type); +bus_register_failed: + ksuspend_usb_cleanup(); out: return retval; } @@ -1346,12 +931,15 @@ static void __exit usb_exit(void) if (nousb) return; - driver_unregister(&usb_generic_driver); + usb_deregister_device_driver(&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); + ksuspend_usb_cleanup(); } subsys_initcall(usb_init); @@ -1362,27 +950,22 @@ module_exit(usb_exit); * These symbols are exported for device (or host controller) * driver modules to use. */ -EXPORT_SYMBOL(usb_epnum_to_ep_desc); -EXPORT_SYMBOL(usb_register); -EXPORT_SYMBOL(usb_deregister); EXPORT_SYMBOL(usb_disabled); -EXPORT_SYMBOL(usb_alloc_dev); +EXPORT_SYMBOL_GPL(usb_get_intf); +EXPORT_SYMBOL_GPL(usb_put_intf); + EXPORT_SYMBOL(usb_put_dev); EXPORT_SYMBOL(usb_get_dev); EXPORT_SYMBOL(usb_hub_tt_clear_buffer); -EXPORT_SYMBOL(usb_driver_claim_interface); -EXPORT_SYMBOL(usb_driver_release_interface); -EXPORT_SYMBOL(usb_match_id); +EXPORT_SYMBOL(usb_lock_device_for_reset); + EXPORT_SYMBOL(usb_find_interface); EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_altnum_to_altsetting); -EXPORT_SYMBOL(usb_reset_device); -EXPORT_SYMBOL(usb_disconnect); - EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(usb_find_device); @@ -1391,11 +974,11 @@ EXPORT_SYMBOL(usb_get_current_frame_number); EXPORT_SYMBOL (usb_buffer_alloc); EXPORT_SYMBOL (usb_buffer_free); -EXPORT_SYMBOL (usb_buffer_map); #if 0 +EXPORT_SYMBOL (usb_buffer_map); EXPORT_SYMBOL (usb_buffer_dmasync); -#endif EXPORT_SYMBOL (usb_buffer_unmap); +#endif EXPORT_SYMBOL (usb_buffer_map_sg); #if 0