Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (144 commits) USB: add support for Dream Cheeky DL100B Webmail Notifier (1d34:0004) USB: serial: ftdi_sio: add support for TIOCSERGETLSR USB: ehci-mxc: Setup portsc register prior to accessing OTG viewport USB: atmel_usba_udc: fix freeing irq in usba_udc_remove() usb: ehci-omap: fix tll channel enable mask usb: ohci-omap3: fix trivial typo USB: gadget: ci13xxx: don't assume that PAGE_SIZE is 4096 USB: gadget: ci13xxx: fix complete() callback for no_interrupt rq's USB: gadget: update ci13xxx to work with g_ether USB: gadgets: ci13xxx: fix probing of compiled-in gadget drivers Revert "USB: musb: pm: don't rely fully on clock support" Revert "USB: musb: blackfin: pm: make it work" USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path USB: uas: Ensure we only bind to a UAS interface USB: uas: Rename sense pipe and sense urb to status pipe and status urb USB: uas: Use kzalloc instead of kmalloc USB: uas: Fix up the Sense IU usb: musb: core: kill unneeded #include's DA8xx: assign name to MUSB IRQ resource usb: gadget: g_ncm added ... Manually fix up trivial conflicts in USB Kconfig changes in: arch/arm/mach-omap2/Kconfig arch/sh/Kconfig drivers/usb/Kconfig drivers/usb/host/ehci-hcd.c and annoying chip clock data conflicts in: arch/arm/mach-omap2/clock3xxx_data.c arch/arm/mach-omap2/clock44xx_data.c
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/quirks.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "usb.h"
|
||||
|
||||
@@ -1262,6 +1261,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
|
||||
udev->reset_resume);
|
||||
}
|
||||
}
|
||||
usb_mark_last_busy(udev);
|
||||
|
||||
done:
|
||||
dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
|
||||
@@ -1329,7 +1329,6 @@ int usb_resume(struct device *dev, pm_message_t msg)
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
udev->last_busy = jiffies;
|
||||
do_unbind_rebind(udev, DO_REBIND);
|
||||
}
|
||||
}
|
||||
@@ -1397,33 +1396,8 @@ void usb_autosuspend_device(struct usb_device *udev)
|
||||
{
|
||||
int status;
|
||||
|
||||
udev->last_busy = jiffies;
|
||||
status = pm_runtime_put_sync(&udev->dev);
|
||||
dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
|
||||
__func__, atomic_read(&udev->dev.power.usage_count),
|
||||
status);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
|
||||
* @udev: the usb_device to autosuspend
|
||||
*
|
||||
* This routine should be called when a core subsystem thinks @udev may
|
||||
* be ready to autosuspend.
|
||||
*
|
||||
* @udev's usage counter left unchanged. If it is 0 and all the interfaces
|
||||
* are inactive then an autosuspend will be attempted. The attempt may
|
||||
* fail or be delayed.
|
||||
*
|
||||
* The caller must hold @udev's device lock.
|
||||
*
|
||||
* This routine can run only in process context.
|
||||
*/
|
||||
void usb_try_autosuspend_device(struct usb_device *udev)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pm_runtime_idle(&udev->dev);
|
||||
usb_mark_last_busy(udev);
|
||||
status = pm_runtime_put_sync_autosuspend(&udev->dev);
|
||||
dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
|
||||
__func__, atomic_read(&udev->dev.power.usage_count),
|
||||
status);
|
||||
@@ -1482,7 +1456,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
int status;
|
||||
|
||||
udev->last_busy = jiffies;
|
||||
usb_mark_last_busy(udev);
|
||||
atomic_dec(&intf->pm_usage_cnt);
|
||||
status = pm_runtime_put_sync(&intf->dev);
|
||||
dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
|
||||
@@ -1509,32 +1483,11 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
|
||||
void usb_autopm_put_interface_async(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
unsigned long last_busy;
|
||||
int status = 0;
|
||||
int status;
|
||||
|
||||
last_busy = udev->last_busy;
|
||||
udev->last_busy = jiffies;
|
||||
usb_mark_last_busy(udev);
|
||||
atomic_dec(&intf->pm_usage_cnt);
|
||||
pm_runtime_put_noidle(&intf->dev);
|
||||
|
||||
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.
|
||||
*
|
||||
* We have to use the interface's timer. Attempts to
|
||||
* schedule a suspend for the device would fail because
|
||||
* the interface is still active.
|
||||
*/
|
||||
if (intf->dev.power.timer_expires == 0 ||
|
||||
round_jiffies_up(last_busy) !=
|
||||
round_jiffies_up(jiffies)) {
|
||||
status = pm_schedule_suspend(&intf->dev,
|
||||
jiffies_to_msecs(
|
||||
round_jiffies_up_relative(
|
||||
udev->autosuspend_delay)));
|
||||
}
|
||||
}
|
||||
status = pm_runtime_put(&intf->dev);
|
||||
dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
|
||||
__func__, atomic_read(&intf->dev.power.usage_count),
|
||||
status);
|
||||
@@ -1554,7 +1507,7 @@ void usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
||||
udev->last_busy = jiffies;
|
||||
usb_mark_last_busy(udev);
|
||||
atomic_dec(&intf->pm_usage_cnt);
|
||||
pm_runtime_put_noidle(&intf->dev);
|
||||
}
|
||||
@@ -1612,18 +1565,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
|
||||
*/
|
||||
int usb_autopm_get_interface_async(struct usb_interface *intf)
|
||||
{
|
||||
int status = 0;
|
||||
enum rpm_status s;
|
||||
|
||||
/* Don't request a resume unless the interface is already suspending
|
||||
* or suspended. Doing so would force a running suspend timer to be
|
||||
* cancelled.
|
||||
*/
|
||||
pm_runtime_get_noresume(&intf->dev);
|
||||
s = ACCESS_ONCE(intf->dev.power.runtime_status);
|
||||
if (s == RPM_SUSPENDING || s == RPM_SUSPENDED)
|
||||
status = pm_request_resume(&intf->dev);
|
||||
int status;
|
||||
|
||||
status = pm_runtime_get(&intf->dev);
|
||||
if (status < 0 && status != -EINPROGRESS)
|
||||
pm_runtime_put_noidle(&intf->dev);
|
||||
else
|
||||
@@ -1650,7 +1594,7 @@ void usb_autopm_get_interface_no_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
||||
udev->last_busy = jiffies;
|
||||
usb_mark_last_busy(udev);
|
||||
atomic_inc(&intf->pm_usage_cnt);
|
||||
pm_runtime_get_noresume(&intf->dev);
|
||||
}
|
||||
@@ -1661,7 +1605,6 @@ static int autosuspend_check(struct usb_device *udev)
|
||||
{
|
||||
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.
|
||||
@@ -1701,87 +1644,46 @@ static int autosuspend_check(struct usb_device *udev)
|
||||
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.
|
||||
*/
|
||||
j = ACCESS_ONCE(jiffies);
|
||||
suspend_time = udev->last_busy + udev->autosuspend_delay;
|
||||
if (time_before(j, suspend_time)) {
|
||||
pm_schedule_suspend(&udev->dev, jiffies_to_msecs(
|
||||
round_jiffies_up_relative(suspend_time - j)));
|
||||
return -EAGAIN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_runtime_suspend(struct device *dev)
|
||||
{
|
||||
int status = 0;
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int status;
|
||||
|
||||
/* A USB device can be suspended if it passes the various autosuspend
|
||||
* checks. Runtime suspend for a USB device means suspending all the
|
||||
* interfaces and then the device itself.
|
||||
*/
|
||||
if (is_usb_device(dev)) {
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
if (autosuspend_check(udev) != 0)
|
||||
return -EAGAIN;
|
||||
|
||||
if (autosuspend_check(udev) != 0)
|
||||
return -EAGAIN;
|
||||
|
||||
status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
|
||||
|
||||
/* If an interface fails the suspend, adjust the last_busy
|
||||
* time so that we don't get another suspend attempt right
|
||||
* away.
|
||||
*/
|
||||
if (status) {
|
||||
udev->last_busy = jiffies +
|
||||
(udev->autosuspend_delay == 0 ?
|
||||
HZ/2 : 0);
|
||||
}
|
||||
|
||||
/* Prevent the parent from suspending immediately after */
|
||||
else if (udev->parent)
|
||||
udev->parent->last_busy = jiffies;
|
||||
}
|
||||
|
||||
/* Runtime suspend for a USB interface doesn't mean anything. */
|
||||
status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int usb_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int status;
|
||||
|
||||
/* Runtime resume for a USB device means resuming both the device
|
||||
* and all its interfaces.
|
||||
*/
|
||||
if (is_usb_device(dev)) {
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int status;
|
||||
|
||||
status = usb_resume_both(udev, PMSG_AUTO_RESUME);
|
||||
udev->last_busy = jiffies;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Runtime resume for a USB interface doesn't mean anything. */
|
||||
return 0;
|
||||
status = usb_resume_both(udev, PMSG_AUTO_RESUME);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int usb_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
/* An idle USB device can be suspended if it passes the various
|
||||
* autosuspend checks. An idle interface can be suspended at
|
||||
* any time.
|
||||
* autosuspend checks.
|
||||
*/
|
||||
if (is_usb_device(dev)) {
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
if (autosuspend_check(udev) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pm_runtime_suspend(dev);
|
||||
if (autosuspend_check(udev) == 0)
|
||||
pm_runtime_autosuspend(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
|
||||
|
@@ -38,7 +38,6 @@
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
|
@@ -24,7 +24,6 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/byteorder.h>
|
||||
@@ -1804,8 +1803,15 @@ int usb_new_device(struct usb_device *udev)
|
||||
|
||||
/* Tell the runtime-PM framework the device is active */
|
||||
pm_runtime_set_active(&udev->dev);
|
||||
pm_runtime_get_noresume(&udev->dev);
|
||||
pm_runtime_use_autosuspend(&udev->dev);
|
||||
pm_runtime_enable(&udev->dev);
|
||||
|
||||
/* By default, forbid autosuspend for all devices. It will be
|
||||
* allowed for hubs during binding.
|
||||
*/
|
||||
usb_disable_autosuspend(udev);
|
||||
|
||||
err = usb_enumerate_device(udev); /* Read descriptors */
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
@@ -1831,6 +1837,8 @@ int usb_new_device(struct usb_device *udev)
|
||||
}
|
||||
|
||||
(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
|
||||
usb_mark_last_busy(udev);
|
||||
pm_runtime_put_sync_autosuspend(&udev->dev);
|
||||
return err;
|
||||
|
||||
fail:
|
||||
@@ -2221,6 +2229,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
|
||||
usb_set_device_state(udev, USB_STATE_SUSPENDED);
|
||||
msleep(10);
|
||||
}
|
||||
usb_mark_last_busy(hub->hdev);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@@ -1804,6 +1804,7 @@ free_interfaces:
|
||||
INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
|
||||
intf->minor = -1;
|
||||
device_initialize(&intf->dev);
|
||||
pm_runtime_no_callbacks(&intf->dev);
|
||||
dev_set_name(&intf->dev, "%d-%s:%d.%d",
|
||||
dev->bus->busnum, dev->devpath,
|
||||
configuration, alt->desc.bInterfaceNumber);
|
||||
|
@@ -117,21 +117,6 @@ void usb_detect_quirks(struct usb_device *udev)
|
||||
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
|
||||
udev->quirks);
|
||||
|
||||
#ifdef CONFIG_USB_SUSPEND
|
||||
|
||||
/* By default, disable autosuspend for all devices. The hub driver
|
||||
* will enable it for hubs.
|
||||
*/
|
||||
usb_disable_autosuspend(udev);
|
||||
|
||||
/* Autosuspend can also be disabled if the initial autosuspend_delay
|
||||
* is negative.
|
||||
*/
|
||||
if (udev->autosuspend_delay < 0)
|
||||
usb_autoresume_device(udev);
|
||||
|
||||
#endif
|
||||
|
||||
/* For the present, all devices default to USB-PERSIST enabled */
|
||||
#if 0 /* was: #ifdef CONFIG_PM */
|
||||
/* Hubs are automatically enabled for USB-PERSIST */
|
||||
|
@@ -233,8 +233,6 @@ static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static const char power_group[] = "power";
|
||||
|
||||
static ssize_t
|
||||
show_persist(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -278,7 +276,7 @@ static int add_persist_attributes(struct device *dev)
|
||||
if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
|
||||
rc = sysfs_add_file_to_group(&dev->kobj,
|
||||
&dev_attr_persist.attr,
|
||||
power_group);
|
||||
power_group_name);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -287,7 +285,7 @@ static void remove_persist_attributes(struct device *dev)
|
||||
{
|
||||
sysfs_remove_file_from_group(&dev->kobj,
|
||||
&dev_attr_persist.attr,
|
||||
power_group);
|
||||
power_group_name);
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -336,44 +334,20 @@ static DEVICE_ATTR(active_duration, S_IRUGO, show_active_duration, NULL);
|
||||
static ssize_t
|
||||
show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
|
||||
return sprintf(buf, "%d\n", dev->power.autosuspend_delay / 1000);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
set_autosuspend(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int value, old_delay;
|
||||
int rc;
|
||||
int value;
|
||||
|
||||
if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
|
||||
value <= - INT_MAX/HZ)
|
||||
if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/1000 ||
|
||||
value <= -INT_MAX/1000)
|
||||
return -EINVAL;
|
||||
value *= HZ;
|
||||
|
||||
usb_lock_device(udev);
|
||||
old_delay = udev->autosuspend_delay;
|
||||
udev->autosuspend_delay = value;
|
||||
|
||||
if (old_delay < 0) { /* Autosuspend wasn't allowed */
|
||||
if (value >= 0)
|
||||
usb_autosuspend_device(udev);
|
||||
} else { /* Autosuspend was allowed */
|
||||
if (value < 0) {
|
||||
rc = usb_autoresume_device(udev);
|
||||
if (rc < 0) {
|
||||
count = rc;
|
||||
udev->autosuspend_delay = old_delay;
|
||||
}
|
||||
} else {
|
||||
usb_try_autosuspend_device(udev);
|
||||
}
|
||||
}
|
||||
|
||||
usb_unlock_device(udev);
|
||||
pm_runtime_set_autosuspend_delay(dev, value * 1000);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -438,44 +412,30 @@ set_level(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
|
||||
|
||||
static struct attribute *power_attrs[] = {
|
||||
&dev_attr_autosuspend.attr,
|
||||
&dev_attr_level.attr,
|
||||
&dev_attr_connected_duration.attr,
|
||||
&dev_attr_active_duration.attr,
|
||||
NULL,
|
||||
};
|
||||
static struct attribute_group power_attr_group = {
|
||||
.name = power_group_name,
|
||||
.attrs = power_attrs,
|
||||
};
|
||||
|
||||
static int add_power_attributes(struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (is_usb_device(dev)) {
|
||||
rc = sysfs_add_file_to_group(&dev->kobj,
|
||||
&dev_attr_autosuspend.attr,
|
||||
power_group);
|
||||
if (rc == 0)
|
||||
rc = sysfs_add_file_to_group(&dev->kobj,
|
||||
&dev_attr_level.attr,
|
||||
power_group);
|
||||
if (rc == 0)
|
||||
rc = sysfs_add_file_to_group(&dev->kobj,
|
||||
&dev_attr_connected_duration.attr,
|
||||
power_group);
|
||||
if (rc == 0)
|
||||
rc = sysfs_add_file_to_group(&dev->kobj,
|
||||
&dev_attr_active_duration.attr,
|
||||
power_group);
|
||||
}
|
||||
if (is_usb_device(dev))
|
||||
rc = sysfs_merge_group(&dev->kobj, &power_attr_group);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void remove_power_attributes(struct device *dev)
|
||||
{
|
||||
sysfs_remove_file_from_group(&dev->kobj,
|
||||
&dev_attr_active_duration.attr,
|
||||
power_group);
|
||||
sysfs_remove_file_from_group(&dev->kobj,
|
||||
&dev_attr_connected_duration.attr,
|
||||
power_group);
|
||||
sysfs_remove_file_from_group(&dev->kobj,
|
||||
&dev_attr_level.attr,
|
||||
power_group);
|
||||
sysfs_remove_file_from_group(&dev->kobj,
|
||||
&dev_attr_autosuspend.attr,
|
||||
power_group);
|
||||
sysfs_unmerge_group(&dev->kobj, &power_attr_group);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@@ -445,7 +445,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
||||
INIT_LIST_HEAD(&dev->filelist);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
dev->autosuspend_delay = usb_autosuspend_delay * HZ;
|
||||
pm_runtime_set_autosuspend_delay(&dev->dev,
|
||||
usb_autosuspend_delay * 1000);
|
||||
dev->connect_time = jiffies;
|
||||
dev->active_duration = -jiffies;
|
||||
#endif
|
||||
|
@@ -75,14 +75,12 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
||||
#ifdef CONFIG_USB_SUSPEND
|
||||
|
||||
extern void usb_autosuspend_device(struct usb_device *udev);
|
||||
extern void usb_try_autosuspend_device(struct usb_device *udev);
|
||||
extern int usb_autoresume_device(struct usb_device *udev);
|
||||
extern int usb_remote_wakeup(struct usb_device *dev);
|
||||
|
||||
#else
|
||||
|
||||
#define usb_autosuspend_device(udev) do {} while (0)
|
||||
#define usb_try_autosuspend_device(udev) do {} while (0)
|
||||
static inline int usb_autoresume_device(struct usb_device *udev)
|
||||
{
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user