X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fusb.c;h=467cb02832f312f4af19417bdc3c6e213e0a7084;hb=762f007b05446f5c63268fb2c28646f28959ee4b;hp=184c24660a4c572b89fd4175d24314dd1fcb8f6c;hpb=0d10e47f9635ecafe5a9dc6e10cb056a87a4daa2;p=linux-2.6-omap-h63xx.git diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 184c24660a4..467cb02832f 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 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ const char *usbcore_name = "usbcore"; static int nousb; /* Disable USB when built into kernel image */ +struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ + /** * usb_ifnum_to_if - get the interface object with a given interface number @@ -67,7 +70,8 @@ static int nousb; /* Disable USB when built into kernel image */ * Don't call this function unless you are bound to one of the interfaces * 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; @@ -100,8 +104,8 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) * Don't call this function unless you are bound to the intf interface * 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; @@ -112,87 +116,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, 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 device lock and the driver model's usb_bus_type.subsys - * writelock. So driver probe() entries don't need extra locking, - * but other call contexts may need to explicitly claim those locks. - */ -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); - iface->condition = USB_INTERFACE_BOUND; - mark_active(iface); - - /* if interface was already added, bind now; else let - * the future device_add() bind it, bypassing probe() - */ - if (device_is_registered(dev)) - 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 device lock and the driver model's usb_bus_type.subsys - * 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 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); - iface->condition = USB_INTERFACE_UNBOUND; - mark_quiesced(iface); -} - struct find_interface_arg { int minor; struct usb_interface *interface; @@ -204,7 +127,7 @@ static int __find_interface(struct device * dev, void * data) struct usb_interface *intf; /* can't look at usb devices, only interfaces */ - if (dev->driver == &usb_generic_driver) + if (is_usb_device(dev)) return 0; intf = to_usb_interface(dev); @@ -227,147 +150,82 @@ static int __find_interface(struct device * dev, void * data) struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { struct find_interface_arg argb; + int retval; argb.minor = minor; argb.interface = NULL; - driver_for_each_device(&drv->driver, NULL, &argb, __find_interface); + /* eat the error, it will be in argb.interface */ + retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, + __find_interface); return argb.interface; } -#ifdef CONFIG_HOTPLUG - -/* - * This sends an uevent to userspace, 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. +/** + * usb_release_dev - free a usb device structure when all users of it are finished. + * @dev: device that's been disconnected * - * 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. + * Will be called only by the device core when all users of this usb device are + * done. */ -static int usb_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static void usb_release_dev(struct device *dev) { - struct usb_interface *intf; - struct usb_device *usb_dev; - struct usb_host_interface *alt; - int i = 0; - int length = 0; - - if (!dev) - return -ENODEV; - - /* driver is often null here; dev_dbg() would oops */ - pr_debug ("usb %s: uevent\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); - alt = intf->cur_altsetting; + struct usb_device *udev; - 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; - } + udev = to_usb_device(dev); -#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 - */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum)) - return -ENOMEM; +#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); +} - /* per-device configurations are common */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PRODUCT=%x/%x/%x", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice))) - return -ENOMEM; +#ifdef CONFIG_PM - /* class-based driver binding models */ - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol)) +static int ksuspend_usb_init(void) +{ + ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd"); + if (!ksuspend_usb_wq) return -ENOMEM; + return 0; +} - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "INTERFACE=%d/%d/%d", - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol)) - return -ENOMEM; +static void ksuspend_usb_cleanup(void) +{ + destroy_workqueue(ksuspend_usb_wq); +} - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice), - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol, - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol)) - return -ENOMEM; +#else - envp[i] = NULL; +#define ksuspend_usb_init() 0 +#define ksuspend_usb_cleanup() do {} while (0) - return 0; -} +#endif -#else +#ifdef CONFIG_USB_SUSPEND -static int usb_uevent(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) +/* usb_autosuspend_work - callback routine to autosuspend a USB device */ +static void usb_autosuspend_work(void *_udev) { - return -ENODEV; -} + struct usb_device *udev = _udev; -#endif /* CONFIG_HOTPLUG */ + usb_pm_lock(udev); + udev->auto_pm = 1; + usb_suspend_both(udev, PMSG_SUSPEND); + usb_pm_unlock(udev); +} -/** - * 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); +static void usb_autosuspend_work(void *_udev) +{} - usb_destroy_configuration(udev); - usb_bus_put(udev->bus); - kfree(udev->product); - kfree(udev->manufacturer); - kfree(udev->serial); - kfree(udev); -} +#endif /** * usb_alloc_dev - usb device constructor (usbcore-internal) @@ -390,8 +248,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) if (!dev) return NULL; - bus = usb_bus_get(bus); - if (!bus) { + if (!usb_get_hcd(bus_to_hcd(bus))) { kfree(dev); return NULL; } @@ -399,11 +256,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) 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; @@ -444,6 +302,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) dev->parent = parent; INIT_LIST_HEAD(&dev->filelist); +#ifdef CONFIG_PM + mutex_init(&dev->pm_mutex); + INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev); +#endif return dev; } @@ -549,7 +411,7 @@ void usb_put_intf(struct usb_interface *intf) * case the driver already owns the device lock.) */ int usb_lock_device_for_reset(struct usb_device *udev, - struct usb_interface *iface) + const struct usb_interface *iface) { unsigned long jiffies_expire = jiffies + HZ; @@ -672,7 +534,139 @@ 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); +} + +/** + * usb_endpoint_dir_in - check if the endpoint has IN direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type IN, otherwise it returns false. + */ +int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +/** + * usb_endpoint_dir_out - check if the endpoint has OUT direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type OUT, otherwise it returns false. + */ +int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +/** + * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type bulk, otherwise it returns false. + */ +int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +/** + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type interrupt, otherwise it returns + * false. + */ +int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +/** + * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type isochronous, otherwise it returns + * false. + */ +int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +/** + * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and IN direction, + * otherwise it returns false. + */ +int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and OUT direction, + * otherwise it returns false. + */ +int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and IN direction, + * otherwise it returns false. + */ +int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and OUT direction, + * otherwise it returns false. + */ +int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and IN direction, + * otherwise it returns false. + */ +int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and OUT direction, + * otherwise it returns false. + */ +int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); } /*-------------------------------------------------------------------*/ @@ -737,9 +731,9 @@ void *usb_buffer_alloc ( 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); } /** @@ -760,9 +754,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); } /** @@ -911,8 +907,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; @@ -946,8 +942,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; @@ -972,8 +968,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; @@ -988,116 +984,6 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } -static int verify_suspended(struct device *dev, void *unused) -{ - if (dev->driver == NULL) - return 0; - return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; -} - -static int usb_generic_suspend(struct device *dev, pm_message_t message) -{ - struct usb_interface *intf; - struct usb_driver *driver; - int status; - - /* USB devices enter SUSPEND state through their hubs, but can be - * marked for FREEZE as soon as their children are already idled. - * But those semantics are useless, so we equate the two (sigh). - */ - if (dev->driver == &usb_generic_driver) { - if (dev->power.power_state.event == message.event) - return 0; - /* we need to rule out bogus requests through sysfs */ - status = device_for_each_child(dev, NULL, verify_suspended); - if (status) - return status; - return usb_suspend_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); - - /* with no hardware, USB interfaces only use FREEZE and ON states */ - if (!is_active(intf)) - return 0; - - if (driver->suspend && driver->resume) { - status = driver->suspend(intf, message); - if (status) - dev_err(dev, "%s error %d\n", "suspend", status); - else - mark_quiesced(intf); - } else { - // FIXME else if there's no suspend method, disconnect... - dev_warn(dev, "no suspend for driver %s?\n", driver->name); - mark_quiesced(intf); - status = 0; - } - return status; -} - -static int usb_generic_resume(struct device *dev) -{ - struct usb_interface *intf; - struct usb_driver *driver; - struct usb_device *udev; - int status; - - if (dev->power.power_state.event == PM_EVENT_ON) - return 0; - - /* mark things as "on" immediately, no matter what errors crop up */ - dev->power.power_state.event = PM_EVENT_ON; - - /* devices resume through their hubs */ - if (dev->driver == &usb_generic_driver) { - udev = to_usb_device(dev); - if (udev->state == USB_STATE_NOTATTACHED) - return 0; - return usb_resume_device (to_usb_device(dev)); - } - - if ((dev->driver == NULL) || - (dev->driver_data == &usb_generic_driver_data)) { - dev->power.power_state.event = PM_EVENT_FREEZE; - return 0; - } - - intf = to_usb_interface(dev); - driver = to_usb_driver(dev->driver); - - udev = interface_to_usbdev(intf); - if (udev->state == USB_STATE_NOTATTACHED) - return 0; - - /* if driver was suspended, it has a resume method; - * however, sysfs can wrongly mark things as suspended - * (on the "no suspend method" FIXME path above) - */ - if (driver->resume) { - status = driver->resume(intf); - if (status) { - dev_err(dev, "%s error %d\n", "resume", status); - mark_quiesced(intf); - } - } else - dev_warn(dev, "no resume for driver %s?\n", driver->name); - return 0; -} - -struct bus_type usb_bus_type = { - .name = "usb", - .match = usb_device_match, - .uevent = usb_uevent, - .suspend = usb_generic_suspend, - .resume = usb_generic_resume, -}; - /* format to disable USB on kernel command line is: nousb */ __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); @@ -1120,9 +1006,12 @@ 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; @@ -1141,7 +1030,7 @@ static int __init usb_init(void) 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; @@ -1158,6 +1047,8 @@ major_init_failed: usb_host_cleanup(); host_init_failed: bus_unregister(&usb_bus_type); +bus_register_failed: + ksuspend_usb_cleanup(); out: return retval; } @@ -1171,7 +1062,7 @@ 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); @@ -1179,6 +1070,7 @@ static void __exit usb_exit(void) usb_hub_cleanup(); usb_host_cleanup(); bus_unregister(&usb_bus_type); + ksuspend_usb_cleanup(); } subsys_initcall(usb_init); @@ -1201,20 +1093,27 @@ EXPORT_SYMBOL(usb_hub_tt_clear_buffer); EXPORT_SYMBOL(usb_lock_device_for_reset); -EXPORT_SYMBOL(usb_driver_claim_interface); -EXPORT_SYMBOL(usb_driver_release_interface); 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_reset_composite_device); - EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(usb_find_device); EXPORT_SYMBOL(usb_get_current_frame_number); +EXPORT_SYMBOL_GPL(usb_endpoint_dir_in); +EXPORT_SYMBOL_GPL(usb_endpoint_dir_out); +EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk); +EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int); +EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc); +EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in); +EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out); +EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in); +EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out); +EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in); +EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out); + EXPORT_SYMBOL (usb_buffer_alloc); EXPORT_SYMBOL (usb_buffer_free);