diff options
author | James Morris <jmorris@namei.org> | 2010-05-06 10:56:07 +1000 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-05-06 10:56:07 +1000 |
commit | 0ffbe2699cda6afbe08501098dff8a8c2fe6ae09 (patch) | |
tree | 81b1a2305d16c873371b65c5a863c0268036cefe /drivers/usb/core | |
parent | 4e5d6f7ec3833c0da9cf34fa5c53c6058c5908b6 (diff) | |
parent | 7ebd467551ed6ae200d7835a84bbda0dcadaa511 (diff) | |
download | blackbird-op-linux-0ffbe2699cda6afbe08501098dff8a8c2fe6ae09.tar.gz blackbird-op-linux-0ffbe2699cda6afbe08501098dff8a8c2fe6ae09.zip |
Merge branch 'master' into next
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/core/devices.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 50 | ||||
-rw-r--r-- | drivers/usb/core/endpoint.c | 1 | ||||
-rw-r--r-- | drivers/usb/core/file.c | 1 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/inode.c | 4 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 20 |
8 files changed, 60 insertions, 22 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 97a819c23ef3..7e594449600e 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -109,7 +109,7 @@ config USB_SUSPEND config USB_OTG bool depends on USB && EXPERIMENTAL - select USB_SUSPEND + depends on USB_SUSPEND default n diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index d41811bfef2a..19bc03a9fecf 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -50,7 +50,7 @@ #include <linux/fs.h> #include <linux/mm.h> -#include <linux/slab.h> +#include <linux/gfp.h> #include <linux/poll.h> #include <linux/usb.h> #include <linux/smp_lock.h> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index f3c233806fa3..2f3dc4cdf79b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -23,6 +23,7 @@ */ #include <linux/device.h> +#include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/quirks.h> #include <linux/pm_runtime.h> @@ -300,7 +301,7 @@ static int usb_probe_interface(struct device *dev) intf->condition = USB_INTERFACE_BINDING; - /* Bound interfaces are initially active. They are + /* Probed interfaces are initially active. They are * runtime-PM-enabled only if the driver has autosuspend support. * They are sensitive to their children's power states. */ @@ -436,11 +437,11 @@ int usb_driver_claim_interface(struct usb_driver *driver, iface->condition = USB_INTERFACE_BOUND; - /* Bound interfaces are initially active. They are + /* 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. */ - pm_runtime_set_active(dev); + pm_runtime_set_suspended(dev); pm_suspend_ignore_children(dev, false); if (driver->supports_autosuspend) pm_runtime_enable(dev); @@ -1169,7 +1170,7 @@ done: static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) { int status = 0; - int i = 0; + int i = 0, n = 0; struct usb_interface *intf; if (udev->state == USB_STATE_NOTATTACHED || @@ -1178,7 +1179,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) /* Suspend all the interfaces and then udev itself */ if (udev->actconfig) { - for (; i < udev->actconfig->desc.bNumInterfaces; i++) { + n = udev->actconfig->desc.bNumInterfaces; + for (i = n - 1; i >= 0; --i) { intf = udev->actconfig->interface[i]; status = usb_suspend_interface(udev, intf, msg); if (status != 0) @@ -1191,7 +1193,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) /* If the suspend failed, resume interfaces that did get suspended */ if (status != 0) { msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); - while (--i >= 0) { + while (++i < n) { intf = udev->actconfig->interface[i]; usb_resume_interface(udev, intf, msg, 0); } @@ -1262,13 +1264,47 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) return status; } +static void choose_wakeup(struct usb_device *udev, pm_message_t msg) +{ + int w, i; + struct usb_interface *intf; + + /* Remote wakeup is needed only when we actually go to sleep. + * For things like FREEZE and QUIESCE, if the device is already + * autosuspended then its current wakeup setting is okay. + */ + if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) { + if (udev->state != USB_STATE_SUSPENDED) + udev->do_remote_wakeup = 0; + return; + } + + /* If remote wakeup is permitted, see whether any interface drivers + * actually want it. + */ + w = 0; + if (device_may_wakeup(&udev->dev) && udev->actconfig) { + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { + intf = udev->actconfig->interface[i]; + w |= intf->needs_remote_wakeup; + } + } + + /* If the device is autosuspended with the wrong wakeup setting, + * autoresume now so the setting can be changed. + */ + if (udev->state == USB_STATE_SUSPENDED && w != udev->do_remote_wakeup) + pm_runtime_resume(&udev->dev); + udev->do_remote_wakeup = w; +} + /* The device lock is held by the PM core */ int usb_suspend(struct device *dev, pm_message_t msg) { struct usb_device *udev = to_usb_device(dev); do_unbind_rebind(udev, DO_UNBIND); - udev->do_remote_wakeup = device_may_wakeup(&udev->dev); + choose_wakeup(udev, msg); return usb_suspend_both(udev, msg); } diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index d26b9ea981f9..4f84a41ee7a8 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/spinlock.h> +#include <linux/slab.h> #include <linux/idr.h> #include <linux/usb.h> #include "usb.h" diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index c3536f151f02..f06f5dbc8cdc 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/errno.h> #include <linux/rwsem.h> +#include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/usb.h> diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index bdf87a8414a1..2c95153c0f24 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -120,7 +120,7 @@ int usb_choose_configuration(struct usb_device *udev) * than a vendor-specific driver. */ else if (udev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC && - (!desc || desc->bInterfaceClass != + (desc && desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC)) { best = c; break; diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 97b40ce133f0..4a6366a42129 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -515,13 +515,13 @@ static int fs_create_by_name (const char *name, mode_t mode, *dentry = NULL; mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(dentry)) { + if (!IS_ERR(*dentry)) { if ((mode & S_IFMT) == S_IFDIR) error = usbfs_mkdir (parent->d_inode, *dentry, mode); else error = usbfs_create (parent->d_inode, *dentry, mode); } else - error = PTR_ERR(dentry); + error = PTR_ERR(*dentry); mutex_unlock(&parent->d_inode->i_mutex); return error; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 1297e9b16a51..0561430f2ede 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -718,7 +718,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor); /** - * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP + * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP * @dev: device the buffer will be used with * @size: requested buffer size * @mem_flags: affect whether allocation may block @@ -737,30 +737,30 @@ EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor); * architectures where CPU caches are not DMA-coherent. On systems without * bus-snooping caches, these buffers are uncached. * - * When the buffer is no longer used, free it with usb_buffer_free(). + * When the buffer is no longer used, free it with usb_free_coherent(). */ -void *usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags, - dma_addr_t *dma) +void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags, + dma_addr_t *dma) { if (!dev || !dev->bus) return NULL; return hcd_buffer_alloc(dev->bus, size, mem_flags, dma); } -EXPORT_SYMBOL_GPL(usb_buffer_alloc); +EXPORT_SYMBOL_GPL(usb_alloc_coherent); /** - * usb_buffer_free - free memory allocated with usb_buffer_alloc() + * usb_free_coherent - free memory allocated with usb_alloc_coherent() * @dev: device the buffer was used with * @size: requested buffer size * @addr: CPU address of buffer * @dma: DMA address of buffer * * This reclaims an I/O buffer, letting it be reused. The memory must have - * been allocated using usb_buffer_alloc(), and the parameters must match + * been allocated using usb_alloc_coherent(), and the parameters must match * those provided in that allocation request. */ -void usb_buffer_free(struct usb_device *dev, size_t size, void *addr, - dma_addr_t dma) +void usb_free_coherent(struct usb_device *dev, size_t size, void *addr, + dma_addr_t dma) { if (!dev || !dev->bus) return; @@ -768,7 +768,7 @@ void usb_buffer_free(struct usb_device *dev, size_t size, void *addr, return; hcd_buffer_free(dev->bus, size, addr, dma); } -EXPORT_SYMBOL_GPL(usb_buffer_free); +EXPORT_SYMBOL_GPL(usb_free_coherent); /** * usb_buffer_map - create DMA mapping(s) for an urb |