diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 21:26:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 21:26:12 -0700 |
commit | 7a9b149212f3716c598afe973b6261fd58453b7a (patch) | |
tree | 477716d84c71da124448b72278e98da28aadbd3d /drivers/usb/core | |
parent | 3d62e3fdce8ef265a3706c52ae1ca6ab84e30f0e (diff) | |
parent | e26bcf37234c67624f62d9fc95f922b8dbda1363 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (229 commits)
USB: remove unused usb_buffer_alloc and usb_buffer_free macros
usb: musb: update gfp/slab.h includes
USB: ftdi_sio: fix legacy SIO-device header
USB: kl5usb105: reimplement using generic framework
USB: kl5usb105: minor clean ups
USB: kl5usb105: fix memory leak
USB: io_ti: use kfifo to implement write buffering
USB: io_ti: remove unsused private counter
USB: ti_usb: use kfifo to implement write buffering
USB: ir-usb: fix incorrect write-buffer length
USB: aircable: fix incorrect write-buffer length
USB: safe_serial: straighten out read processing
USB: safe_serial: reimplement read using generic framework
USB: safe_serial: reimplement write using generic framework
usb-storage: always print quirks
USB: usb-storage: trivial debug improvements
USB: oti6858: use port write fifo
USB: oti6858: use kfifo to implement write buffering
USB: cypress_m8: use kfifo to implement write buffering
USB: cypress_m8: remove unused drain define
...
Fix up conflicts (due to usb_buffer_alloc/free renaming) in
drivers/input/tablet/acecad.c
drivers/input/tablet/kbtab.c
drivers/input/tablet/wacom_sys.c
drivers/media/video/gspca/gspca.c
sound/usb/usbaudio.c
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/buffer.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/config.c | 214 | ||||
-rw-r--r-- | drivers/usb/core/devices.c | 19 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 60 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 246 | ||||
-rw-r--r-- | drivers/usb/core/hcd.h | 578 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 30 | ||||
-rw-r--r-- | drivers/usb/core/hub.h | 205 | ||||
-rw-r--r-- | drivers/usb/core/inode.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 133 | ||||
-rw-r--r-- | drivers/usb/core/quirks.c | 4 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 22 | ||||
-rw-r--r-- | drivers/usb/core/urb.c | 18 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 94 |
17 files changed, 397 insertions, 1237 deletions
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 3ba2fff7149..2c6965484fe 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -14,7 +14,7 @@ #include <linux/dma-mapping.h> #include <linux/dmapool.h> #include <linux/usb.h> -#include "hcd.h" +#include <linux/usb/hcd.h> /* diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 0d3af6a6ee4..83126b03e7c 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -1,12 +1,14 @@ #include <linux/usb.h> #include <linux/usb/ch9.h> +#include <linux/usb/hcd.h> +#include <linux/usb/quirks.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/device.h> #include <asm/byteorder.h> #include "usb.h" -#include "hcd.h" + #define USB_MAXALTSETTING 128 /* Hard limit */ #define USB_MAXENDPOINTS 30 /* Hard limit */ @@ -19,32 +21,6 @@ static inline const char *plural(int n) return (n == 1 ? "" : "s"); } -/* FIXME: this is a kludge */ -static int find_next_descriptor_more(unsigned char *buffer, int size, - int dt1, int dt2, int dt3, int *num_skipped) -{ - struct usb_descriptor_header *h; - int n = 0; - unsigned char *buffer0 = buffer; - - /* Find the next descriptor of type dt1 or dt2 or dt3 */ - while (size > 0) { - h = (struct usb_descriptor_header *) buffer; - if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2 || - h->bDescriptorType == dt3) - break; - buffer += h->bLength; - size -= h->bLength; - ++n; - } - - /* Store the number of descriptors skipped and return the - * number of bytes skipped */ - if (num_skipped) - *num_skipped = n; - return buffer - buffer0; -} - static int find_next_descriptor(unsigned char *buffer, int size, int dt1, int dt2, int *num_skipped) { @@ -69,47 +45,41 @@ static int find_next_descriptor(unsigned char *buffer, int size, return buffer - buffer0; } -static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, +static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, - int num_ep, unsigned char *buffer, int size) + unsigned char *buffer, int size) { - unsigned char *buffer_start = buffer; - struct usb_ss_ep_comp_descriptor *desc; - int retval; - int num_skipped; + struct usb_ss_ep_comp_descriptor *desc; int max_tx; - int i; + /* The SuperSpeed endpoint companion descriptor is supposed to + * be the first thing immediately following the endpoint descriptor. + */ desc = (struct usb_ss_ep_comp_descriptor *) buffer; - if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { + if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP || + size < USB_DT_SS_EP_COMP_SIZE) { dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " " interface %d altsetting %d ep %d: " "using minimum values\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); - /* - * The next descriptor is for an Endpoint or Interface, - * no extra descriptors to copy into the companion structure, - * and we didn't eat up any of the buffer. + + /* Fill in some default values. + * Leave bmAttributes as zero, which will mean no streams for + * bulk, and isoc won't support multiple bursts of packets. + * With bursts of only one packet, and a Mult of 1, the max + * amount of data moved per endpoint service interval is one + * packet. */ - return 0; + ep->ss_ep_comp.bLength = USB_DT_SS_EP_COMP_SIZE; + ep->ss_ep_comp.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; + if (usb_endpoint_xfer_isoc(&ep->desc) || + usb_endpoint_xfer_int(&ep->desc)) + ep->ss_ep_comp.wBytesPerInterval = + ep->desc.wMaxPacketSize; + return; } - memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE); - desc = &ep->ss_ep_comp->desc; - buffer += desc->bLength; - size -= desc->bLength; - /* Eat up the other descriptors we don't care about */ - ep->ss_ep_comp->extra = buffer; - i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, - USB_DT_INTERFACE, &num_skipped); - ep->ss_ep_comp->extralen = i; - buffer += i; - size -= i; - retval = buffer - buffer_start; - if (num_skipped > 0) - dev_dbg(ddev, "skipped %d descriptor%s after %s\n", - num_skipped, plural(num_skipped), - "SuperSpeed endpoint companion"); + memcpy(&ep->ss_ep_comp, desc, USB_DT_SS_EP_COMP_SIZE); /* Check the various values */ if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) { @@ -117,47 +87,48 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, "config %d interface %d altsetting %d ep %d: " "setting to zero\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); - desc->bMaxBurst = 0; - } - if (desc->bMaxBurst > 15) { + ep->ss_ep_comp.bMaxBurst = 0; + } else if (desc->bMaxBurst > 15) { dev_warn(ddev, "Endpoint with bMaxBurst = %d in " "config %d interface %d altsetting %d ep %d: " "setting to 15\n", desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress); - desc->bMaxBurst = 15; + ep->ss_ep_comp.bMaxBurst = 15; } - if ((usb_endpoint_xfer_control(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) - && desc->bmAttributes != 0) { + + if ((usb_endpoint_xfer_control(&ep->desc) || + usb_endpoint_xfer_int(&ep->desc)) && + desc->bmAttributes != 0) { dev_warn(ddev, "%s endpoint with bmAttributes = %d in " "config %d interface %d altsetting %d ep %d: " "setting to zero\n", usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk", desc->bmAttributes, cfgno, inum, asnum, ep->desc.bEndpointAddress); - desc->bmAttributes = 0; - } - if (usb_endpoint_xfer_bulk(&ep->desc) && desc->bmAttributes > 16) { + ep->ss_ep_comp.bmAttributes = 0; + } else if (usb_endpoint_xfer_bulk(&ep->desc) && + desc->bmAttributes > 16) { dev_warn(ddev, "Bulk endpoint with more than 65536 streams in " "config %d interface %d altsetting %d ep %d: " "setting to max\n", cfgno, inum, asnum, ep->desc.bEndpointAddress); - desc->bmAttributes = 16; - } - if (usb_endpoint_xfer_isoc(&ep->desc) && desc->bmAttributes > 2) { + ep->ss_ep_comp.bmAttributes = 16; + } else if (usb_endpoint_xfer_isoc(&ep->desc) && + desc->bmAttributes > 2) { dev_warn(ddev, "Isoc endpoint has Mult of %d in " "config %d interface %d altsetting %d ep %d: " "setting to 3\n", desc->bmAttributes + 1, cfgno, inum, asnum, ep->desc.bEndpointAddress); - desc->bmAttributes = 2; + ep->ss_ep_comp.bmAttributes = 2; } - if (usb_endpoint_xfer_isoc(&ep->desc)) { + + if (usb_endpoint_xfer_isoc(&ep->desc)) max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1) * (desc->bmAttributes + 1); - } else if (usb_endpoint_xfer_int(&ep->desc)) { + else if (usb_endpoint_xfer_int(&ep->desc)) max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1); - } else { - goto valid; - } + else + max_tx = 999999; if (desc->wBytesPerInterval > max_tx) { dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in " "config %d interface %d altsetting %d ep %d: " @@ -166,10 +137,8 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, desc->wBytesPerInterval, cfgno, inum, asnum, ep->desc.bEndpointAddress, max_tx); - desc->wBytesPerInterval = max_tx; + ep->ss_ep_comp.wBytesPerInterval = max_tx; } -valid: - return retval; } static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, @@ -291,61 +260,19 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, cfgno, inum, asnum, d->bEndpointAddress, maxp); } - /* Allocate room for and parse any SS endpoint companion descriptors */ - if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) { - endpoint->extra = buffer; - i = find_next_descriptor_more(buffer, size, USB_DT_SS_ENDPOINT_COMP, - USB_DT_ENDPOINT, USB_DT_INTERFACE, &n); - endpoint->extralen = i; - buffer += i; - size -= i; - - /* Allocate space for the SS endpoint companion descriptor */ - endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp), - GFP_KERNEL); - if (!endpoint->ss_ep_comp) - return -ENOMEM; - /* Fill in some default values (may be overwritten later) */ - endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE; - endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP; - endpoint->ss_ep_comp->desc.bMaxBurst = 0; - /* - * Leave bmAttributes as zero, which will mean no streams for - * bulk, and isoc won't support multiple bursts of packets. - * With bursts of only one packet, and a Mult of 1, the max - * amount of data moved per endpoint service interval is one - * packet. - */ - if (usb_endpoint_xfer_isoc(&endpoint->desc) || - usb_endpoint_xfer_int(&endpoint->desc)) - endpoint->ss_ep_comp->desc.wBytesPerInterval = - endpoint->desc.wMaxPacketSize; - - if (size > 0) { - retval = usb_parse_ss_endpoint_companion(ddev, cfgno, - inum, asnum, endpoint, num_ep, buffer, - size); - if (retval >= 0) { - buffer += retval; - retval = buffer - buffer0; - } - } else { - dev_warn(ddev, "config %d interface %d altsetting %d " - "endpoint 0x%X has no " - "SuperSpeed companion descriptor\n", - cfgno, inum, asnum, d->bEndpointAddress); - retval = buffer - buffer0; - } - } else { - /* Skip over any Class Specific or Vendor Specific descriptors; - * find the next endpoint or interface descriptor */ - endpoint->extra = buffer; - i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, - USB_DT_INTERFACE, &n); - endpoint->extralen = i; - retval = buffer - buffer0 + i; - } + /* Parse a possible SuperSpeed endpoint companion descriptor */ + if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) + usb_parse_ss_endpoint_companion(ddev, cfgno, + inum, asnum, endpoint, buffer, size); + + /* Skip over any Class Specific or Vendor Specific descriptors; + * find the next endpoint or interface descriptor */ + endpoint->extra = buffer; + i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT, + USB_DT_INTERFACE, &n); + endpoint->extralen = i; + retval = buffer - buffer0 + i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", n, plural(n), "endpoint"); @@ -478,9 +405,10 @@ skip_to_next_interface_descriptor: return buffer - buffer0 + i; } -static int usb_parse_configuration(struct device *ddev, int cfgidx, +static int usb_parse_configuration(struct usb_device *dev, int cfgidx, struct usb_host_config *config, unsigned char *buffer, int size) { + struct device *ddev = &dev->dev; unsigned char *buffer0 = buffer; int cfgno; int nintf, nintf_orig; @@ -549,6 +477,16 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx, } inum = d->bInterfaceNumber; + + if ((dev->quirks & USB_QUIRK_HONOR_BNUMINTERFACES) && + n >= nintf_orig) { + dev_warn(ddev, "config %d has more interface " + "descriptors, than it declares in " + "bNumInterfaces, ignoring interface " + "number: %d\n", cfgno, inum); + continue; + } + if (inum >= nintf_orig) dev_warn(ddev, "config %d has an invalid " "interface number: %d but max is %d\n", @@ -722,7 +660,6 @@ int usb_get_configuration(struct usb_device *dev) int ncfg = dev->descriptor.bNumConfigurations; int result = 0; unsigned int cfgno, length; - unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; @@ -751,17 +688,16 @@ int usb_get_configuration(struct usb_device *dev) if (!dev->rawdescriptors) goto err2; - buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); - if (!buffer) + desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); + if (!desc) goto err2; - desc = (struct usb_config_descriptor *)buffer; result = 0; for (; cfgno < ncfg; cfgno++) { /* We grab just the first descriptor so we know how long * the whole configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, - buffer, USB_DT_CONFIG_SIZE); + desc, USB_DT_CONFIG_SIZE); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s: %d\n", cfgno, "start", result); @@ -800,7 +736,7 @@ int usb_get_configuration(struct usb_device *dev) dev->rawdescriptors[cfgno] = bigbuffer; - result = usb_parse_configuration(&dev->dev, cfgno, + result = usb_parse_configuration(dev, cfgno, &dev->config[cfgno], bigbuffer, length); if (result < 0) { ++cfgno; @@ -810,7 +746,7 @@ int usb_get_configuration(struct usb_device *dev) result = 0; err: - kfree(buffer); + kfree(desc); out_not_authorized: dev->descriptor.bNumConfigurations = cfgno; err2: diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 19bc03a9fec..3449742c00e 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -1,7 +1,8 @@ /* * devices.c * (C) Copyright 1999 Randy Dunlap. - * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device) + * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. + * (proc file per device) * (C) Copyright 1999 Deti Fliegl (new USB architecture) * * This program is free software; you can redistribute it and/or modify @@ -55,11 +56,11 @@ #include <linux/usb.h> #include <linux/smp_lock.h> #include <linux/usbdevice_fs.h> +#include <linux/usb/hcd.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "usb.h" -#include "hcd.h" /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ #define ALLOW_SERIAL_NUMBER @@ -138,8 +139,8 @@ struct class_info { char *class_name; }; -static const struct class_info clas_info[] = -{ /* max. 5 chars. per name string */ +static const struct class_info clas_info[] = { + /* max. 5 chars. per name string */ {USB_CLASS_PER_INTERFACE, ">ifc"}, {USB_CLASS_AUDIO, "audio"}, {USB_CLASS_COMM, "comm."}, @@ -191,8 +192,10 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, if (speed == USB_SPEED_HIGH) { switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) { - case 1 << 11: bandwidth = 2; break; - case 2 << 11: bandwidth = 3; break; + case 1 << 11: + bandwidth = 2; break; + case 2 << 11: + bandwidth = 3; break; } } @@ -200,7 +203,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Ctrl"; - if (speed == USB_SPEED_HIGH) /* uframes per NAK */ + if (speed == USB_SPEED_HIGH) /* uframes per NAK */ interval = desc->bInterval; else interval = 0; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 3466fdc5bb1..c2f62a3993d 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -43,6 +43,7 @@ #include <linux/module.h> #include <linux/usb.h> #include <linux/usbdevice_fs.h> +#include <linux/usb/hcd.h> /* for usbcore internals */ #include <linux/cdev.h> #include <linux/notifier.h> #include <linux/security.h> @@ -50,9 +51,7 @@ #include <asm/byteorder.h> #include <linux/moduleparam.h> -#include "hcd.h" /* for usbcore internals */ #include "usb.h" -#include "hub.h" #define USB_MAXBUS 64 #define USB_DEVICE_MAX USB_MAXBUS * 128 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2f3dc4cdf79..ded550eda5d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -26,8 +26,9 @@ #include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/quirks.h> +#include <linux/usb/hcd.h> #include <linux/pm_runtime.h> -#include "hcd.h" + #include "usb.h" @@ -333,7 +334,8 @@ static int usb_probe_interface(struct device *dev) usb_cancel_queued_reset(intf); /* Unbound interfaces are always runtime-PM-disabled and -suspended */ - pm_runtime_disable(dev); + if (driver->supports_autosuspend) + pm_runtime_disable(dev); pm_runtime_set_suspended(dev); usb_autosuspend_device(udev); @@ -388,7 +390,8 @@ static int usb_unbind_interface(struct device *dev) intf->needs_remote_wakeup = 0; /* Unbound interfaces are always runtime-PM-disabled and -suspended */ - pm_runtime_disable(dev); + if (driver->supports_autosuspend) + pm_runtime_disable(dev); pm_runtime_set_suspended(dev); /* Undo any residual pm_autopm_get_interface_* calls */ @@ -437,14 +440,17 @@ int usb_driver_claim_interface(struct usb_driver *driver, iface->condition = USB_INTERFACE_BOUND; - /* Claimed interfaces are initially inactive (suspended). They are - * runtime-PM-enabled only if the driver has autosuspend support. - * They are sensitive to their children's power states. + /* Claimed interfaces are initially inactive (suspended) and + * runtime-PM-enabled, but only if the driver has autosuspend + * support. Otherwise they are marked active, to prevent the + * device from being autosuspended, but left disabled. In either + * case they are sensitive to their children's power states. */ - pm_runtime_set_suspended(dev); pm_suspend_ignore_children(dev, false); if (driver->supports_autosuspend) pm_runtime_enable(dev); + else + pm_runtime_set_active(dev); /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() @@ -1355,13 +1361,9 @@ int usb_resume(struct device *dev, pm_message_t msg) * * The caller must hold @udev's device lock. */ -int usb_enable_autosuspend(struct usb_device *udev) +void usb_enable_autosuspend(struct usb_device *udev) { - if (udev->autosuspend_disabled) { - udev->autosuspend_disabled = 0; - usb_autosuspend_device(udev); - } - return 0; + pm_runtime_allow(&udev->dev); } EXPORT_SYMBOL_GPL(usb_enable_autosuspend); @@ -1374,16 +1376,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend); * * The caller must hold @udev's device lock. */ -int usb_disable_autosuspend(struct usb_device *udev) +void usb_disable_autosuspend(struct usb_device *udev) { - int rc = 0; - - if (!udev->autosuspend_disabled) { - rc = usb_autoresume_device(udev); - if (rc == 0) - udev->autosuspend_disabled = 1; - } - return rc; + pm_runtime_forbid(&udev->dev); } EXPORT_SYMBOL_GPL(usb_disable_autosuspend); @@ -1485,9 +1480,6 @@ int usb_autoresume_device(struct usb_device *udev) * 0, a delayed autosuspend request for @intf's device is attempted. The * attempt may fail (see autosuspend_check()). * - * If the driver has set @intf->needs_remote_wakeup then autosuspend will - * take place only if the device's remote-wakeup facility is enabled. - * * This routine can run only in process context. */ void usb_autopm_put_interface(struct usb_interface *intf) @@ -1530,7 +1522,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf) atomic_dec(&intf->pm_usage_cnt); pm_runtime_put_noidle(&intf->dev); - if (!udev->autosuspend_disabled) { + if (udev->dev.power.runtime_auto) { /* Optimization: Don't schedule a delayed autosuspend if * the timer is already running and the expiration time * wouldn't change. @@ -1672,14 +1664,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume); /* Internal routine to check whether we may autosuspend a device. */ static int autosuspend_check(struct usb_device *udev) { - int i; + int w, i; struct usb_interface *intf; unsigned long suspend_time, j; /* Fail if autosuspend is disabled, or any interfaces are in use, or * any interface drivers require remote wakeup but it isn't available. */ - udev->do_remote_wakeup = device_may_wakeup(&udev->dev); + w = 0; if (udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; @@ -1693,12 +1685,7 @@ static int autosuspend_check(struct usb_device *udev) continue; if (atomic_read(&intf->dev.power.usage_count) > 0) return -EBUSY; - if (intf->needs_remote_wakeup && - !udev->do_remote_wakeup) { - dev_dbg(&udev->dev, "remote wakeup needed " - "for autosuspend\n"); - return -EOPNOTSUPP; - } + w |= intf->needs_remote_wakeup; /* Don't allow autosuspend if the device will need * a reset-resume and any of its interface drivers @@ -1714,6 +1701,11 @@ static int autosuspend_check(struct usb_device *udev) } } } + if (w && !device_can_wakeup(&udev->dev)) { + dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n"); + return -EOPNOTSUPP; + } + udev->do_remote_wakeup = w; /* If everything is okay but the device hasn't been idle for long * enough, queue a delayed autosuspend request. diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 2c95153c0f2..9a34ccb0a1c 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -18,8 +18,8 @@ */ #include <linux/usb.h> +#include <linux/usb/hcd.h> #include "usb.h" -#include "hcd.h" static inline const char *plural(int n) { diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 15286533c15..1cf2d1e79a5 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -21,6 +21,7 @@ #include <linux/pci.h> #include <linux/pm_runtime.h> #include <linux/usb.h> +#include <linux/usb/hcd.h> #include <asm/io.h> #include <asm/irq.h> @@ -33,7 +34,6 @@ #endif #include "usb.h" -#include "hcd.h" /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 2f8cedda800..12742f152f4 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -38,14 +38,12 @@ #include <asm/unaligned.h> #include <linux/platform_device.h> #include <linux/workqueue.h> -#include <linux/mutex.h> #include <linux/pm_runtime.h> #include <linux/usb.h> +#include <linux/usb/hcd.h> #include "usb.h" -#include "hcd.h" -#include "hub.h" /*-------------------------------------------------------------------------*/ @@ -1261,6 +1259,51 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle, *dma_handle = 0; } +static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) +{ + enum dma_data_direction dir; + + if (urb->transfer_flags & URB_SETUP_MAP_SINGLE) + dma_unmap_single(hcd->self.controller, + urb->setup_dma, + sizeof(struct usb_ctrlrequest), + DMA_TO_DEVICE); + else if (urb->transfer_flags & URB_SETUP_MAP_LOCAL) + hcd_free_coherent(urb->dev->bus, + &urb->setup_dma, + (void **) &urb->setup_packet, + sizeof(struct usb_ctrlrequest), + DMA_TO_DEVICE); + + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + if (urb->transfer_flags & URB_DMA_MAP_SG) + dma_unmap_sg(hcd->self.controller, + urb->sg, + urb->num_sgs, + dir); + else if (urb->transfer_flags & URB_DMA_MAP_PAGE) + dma_unmap_page(hcd->self.controller, + urb->transfer_dma, + urb->transfer_buffer_length, + dir); + else if (urb->transfer_flags & URB_DMA_MAP_SINGLE) + dma_unmap_single(hcd->self.controller, + urb->transfer_dma, + urb->transfer_buffer_length, + dir); + else if (urb->transfer_flags & URB_MAP_LOCAL) + hcd_free_coherent(urb->dev->bus, + &urb->transfer_dma, + &urb->transfer_buffer, + urb->transfer_buffer_length, + dir); + + /* Make it safe to call this routine more than once */ + urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL | + URB_DMA_MAP_SG | URB_DMA_MAP_PAGE | + URB_DMA_MAP_SINGLE | URB_MAP_LOCAL); +} + static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { @@ -1272,11 +1315,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, * unless it uses pio or talks to another transport, * or uses the provided scatter gather list for bulk. */ - if (is_root_hub(urb->dev)) - return 0; - if (usb_endpoint_xfer_control(&urb->ep->desc) - && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { + if (usb_endpoint_xfer_control(&urb->ep->desc)) { if (hcd->self.uses_dma) { urb->setup_dma = dma_map_single( hcd->self.controller, @@ -1286,27 +1326,64 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, if (dma_mapping_error(hcd->self.controller, urb->setup_dma)) return -EAGAIN; - } else if (hcd->driver->flags & HCD_LOCAL_MEM) + urb->transfer_flags |= URB_SETUP_MAP_SINGLE; + } else if (hcd->driver->flags & HCD_LOCAL_MEM) { ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, &urb->setup_dma, (void **)&urb->setup_packet, sizeof(struct usb_ctrlrequest), DMA_TO_DEVICE); + if (ret) + return ret; + urb->transfer_flags |= URB_SETUP_MAP_LOCAL; + } } dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - if (ret == 0 && urb->transfer_buffer_length != 0 + if (urb->transfer_buffer_length != 0 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { if (hcd->self.uses_dma) { - urb->transfer_dma = dma_map_single ( - hcd->self.controller, - urb->transfer_buffer, - urb->transfer_buffer_length, - dir); - if (dma_mapping_error(hcd->self.controller, + if (urb->num_sgs) { + int n = dma_map_sg( + hcd->self.controller, + urb->sg, + urb->num_sgs, + dir); + if (n <= 0) + ret = -EAGAIN; + else + urb->transfer_flags |= URB_DMA_MAP_SG; + if (n != urb->num_sgs) { + urb->num_sgs = n; + urb->transfer_flags |= + URB_DMA_SG_COMBINED; + } + } else if (urb->sg) { + struct scatterlist *sg = urb->sg; + urb->transfer_dma = dma_map_page( + hcd->self.controller, + sg_page(sg), + sg->offset, + urb->transfer_buffer_length, + dir); + if (dma_mapping_error(hcd->self.controller, urb->transfer_dma)) - return -EAGAIN; + ret = -EAGAIN; + else + urb->transfer_flags |= URB_DMA_MAP_PAGE; + } else { + urb->transfer_dma = dma_map_single( + hcd->self.controller, + urb->transfer_buffer, + urb->transfer_buffer_length, + dir); + if (dma_mapping_error(hcd->self.controller, + urb->transfer_dma)) + ret = -EAGAIN; + else + urb->transfer_flags |= URB_DMA_MAP_SINGLE; + } } else if (hcd->driver->flags & HCD_LOCAL_MEM) { ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, @@ -1314,55 +1391,16 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, &urb->transfer_buffer, urb->transfer_buffer_length, dir); - - if (ret && usb_endpoint_xfer_control(&urb->ep->desc) - && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) - hcd_free_coherent(urb->dev->bus, - &urb->setup_dma, - (void **)&urb->setup_packet, - sizeof(struct usb_ctrlrequest), - DMA_TO_DEVICE); + if (ret == 0) + urb->transfer_flags |= URB_MAP_LOCAL; } + if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE | + URB_SETUP_MAP_LOCAL))) + unmap_urb_for_dma(hcd, urb); } return ret; } -static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) -{ - enum dma_data_direction dir; - - if (is_root_hub(urb->dev)) - return; - - if (usb_endpoint_xfer_control(&urb->ep->desc) - && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { - if (hcd->self.uses_dma) - dma_unmap_single(hcd->self.controller, urb->setup_dma, - sizeof(struct usb_ctrlrequest), - DMA_TO_DEVICE); - else if (hcd->driver->flags & HCD_LOCAL_MEM) - hcd_free_coherent(urb->dev->bus, &urb->setup_dma, - (void **)&urb->setup_packet, - sizeof(struct usb_ctrlrequest), - DMA_TO_DEVICE); - } - - dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - if (urb->transfer_buffer_length != 0 - && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { - if (hcd->self.uses_dma) - dma_unmap_single(hcd->self.controller, - urb->transfer_dma, - urb->transfer_buffer_length, - dir); - else if (hcd->driver->flags & HCD_LOCAL_MEM) - hcd_free_coherent(urb->dev->bus, &urb->transfer_dma, - &urb->transfer_buffer, - urb->transfer_buffer_length, - dir); - } -} - /*-------------------------------------------------------------------------*/ /* may be called in any context with a valid urb->dev usecount @@ -1391,21 +1429,20 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) * URBs must be submitted in process context with interrupts * enabled. */ - status = map_urb_for_dma(hcd, urb, mem_flags); - if (unlikely(status)) { - usbmon_urb_submit_error(&hcd->self, urb, status); - goto error; - } - if (is_root_hub(urb-&g |