From 886ccd4520064408ce5876cfe00554ce52ecf4a7 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Sat, 6 Nov 2010 17:41:28 +0300 Subject: usb: core: fix information leak to userland Structure usbdevfs_connectinfo is copied to userland with padding byted after "slow" field uninitialized. It leads to leaking of contents of kernel stack memory. Signed-off-by: Vasiliy Kulikov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index f1aaff6202a5..045bb4b823e1 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -965,10 +965,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) static int proc_connectinfo(struct dev_state *ps, void __user *arg) { - struct usbdevfs_connectinfo ci; + struct usbdevfs_connectinfo ci = { + .devnum = ps->dev->devnum, + .slow = ps->dev->speed == USB_SPEED_LOW + }; - ci.devnum = ps->dev->devnum; - ci.slow = ps->dev->speed == USB_SPEED_LOW; if (copy_to_user(arg, &ci, sizeof(ci))) return -EFAULT; return 0; -- cgit From 63defa73c8c1193c1273474440c30d34c2524597 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 15 Nov 2010 15:56:54 -0500 Subject: USB: use the no_callbacks flag for interfaces Call pm_runtime_no_callbacks to set no_callbacks flag for USB interfaces. Since interfaces cannot be power-managed separately from their parent devices, there's no reason for the runtime-PM core to invoke any callbacks for them. Signed-off-by: Ming Lei Reviewed-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 82 ++++++++++++++++------------------------------ drivers/usb/core/message.c | 2 ++ 2 files changed, 31 insertions(+), 53 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index c0e60fbcb048..eda2d2c25459 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1612,18 +1612,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 @@ -1717,71 +1708,56 @@ static int autosuspend_check(struct usb_device *udev) 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; - - status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); + if (autosuspend_check(udev) != 0) + return -EAGAIN; - /* 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); - } + status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); - /* Prevent the parent from suspending immediately after */ - else if (udev->parent) - udev->parent->last_busy = jiffies; + /* 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); } - /* Runtime suspend for a USB interface doesn't mean anything. */ + /* Prevent the parent from suspending immediately after */ + else if (udev->parent) + udev->parent->last_busy = jiffies; + 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); + udev->last_busy = jiffies; + 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_suspend(dev); return 0; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index d6e3e410477e..f377e49fcb30 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include /* for usbcore internals */ @@ -1804,6 +1805,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); -- cgit From 045cac6b3b067a9286dabfb789f67ae4f433f88b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 15 Nov 2010 15:57:07 -0500 Subject: USB: use sysfs_merge_group for power attributes This patch (as1426) makes use of the new sysfs_merge_group() and sysfs_unmerge_group() routines to simplify the handling of power attributes for USB devices. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 50 ++++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 448f5b47fc48..9561e087907d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -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 @@ -438,44 +436,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 -- cgit From 6ddf27cdbc218a412d7e993fdc08e30eec2042ce Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Mon, 15 Nov 2010 15:57:30 -0500 Subject: USB: make usb_mark_last_busy use pm_runtime_mark_last_busy Since the runtime-PM core already defines a .last_busy field in device.power, this patch uses it to replace the .last_busy field defined in usb_device and uses pm_runtime_mark_last_busy to implement usb_mark_last_busy. Signed-off-by: Ming Lei Reviewed-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 23 +++++++++++------------ drivers/usb/core/hcd-pci.c | 1 - drivers/usb/core/hcd.c | 1 - drivers/usb/core/hub.c | 1 - drivers/usb/core/message.c | 1 - 5 files changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index eda2d2c25459..0a63e968c683 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "usb.h" @@ -1329,7 +1328,7 @@ 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; + usb_mark_last_busy(udev); do_unbind_rebind(udev, DO_REBIND); } } @@ -1397,7 +1396,7 @@ void usb_autosuspend_device(struct usb_device *udev) { int status; - udev->last_busy = jiffies; + usb_mark_last_busy(udev); status = pm_runtime_put_sync(&udev->dev); dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n", __func__, atomic_read(&udev->dev.power.usage_count), @@ -1482,7 +1481,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", @@ -1512,8 +1511,8 @@ void usb_autopm_put_interface_async(struct usb_interface *intf) unsigned long last_busy; int status = 0; - last_busy = udev->last_busy; - udev->last_busy = jiffies; + last_busy = udev->dev.power.last_busy; + usb_mark_last_busy(udev); atomic_dec(&intf->pm_usage_cnt); pm_runtime_put_noidle(&intf->dev); @@ -1554,7 +1553,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); } @@ -1641,7 +1640,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); } @@ -1697,7 +1696,7 @@ static int autosuspend_check(struct usb_device *udev) * enough, queue a delayed autosuspend request. */ j = ACCESS_ONCE(jiffies); - suspend_time = udev->last_busy + udev->autosuspend_delay; + suspend_time = udev->dev.power.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))); @@ -1725,13 +1724,13 @@ static int usb_runtime_suspend(struct device *dev) * away. */ if (status) { - udev->last_busy = jiffies + + udev->dev.power.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; + usb_mark_last_busy(udev->parent); return status; } @@ -1745,7 +1744,7 @@ static int usb_runtime_resume(struct device *dev) * and all its interfaces. */ status = usb_resume_both(udev, PMSG_AUTO_RESUME); - udev->last_busy = jiffies; + usb_mark_last_busy(udev); return status; } diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 3799573bd385..b55d46070a25 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 61800f77dac8..e70aeaf3dc1a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 27115b45edc5..7c2405eccc4b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f377e49fcb30..832487423826 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include /* for usbcore internals */ -- cgit From fcc4a01eb8661226e80632327673f67bf6a5840b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 15 Nov 2010 15:57:51 -0500 Subject: USB: use the runtime-PM autosuspend implementation This patch (as1428) converts USB over to the new runtime-PM core autosuspend framework. One slightly awkward aspect of the conversion is that USB devices will now have two suspend-delay attributes: the old power/autosuspend file and the new power/autosuspend_delay_ms file. One expresses the delay time in seconds and the other in milliseconds, but otherwise they do the same thing. The old attribute can be deprecated and then removed eventually. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 77 +++-------------------------------------------- drivers/usb/core/hub.c | 1 + drivers/usb/core/quirks.c | 6 ---- drivers/usb/core/sysfs.c | 34 +++------------------ drivers/usb/core/usb.c | 3 +- drivers/usb/core/usb.h | 2 -- 6 files changed, 13 insertions(+), 110 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 0a63e968c683..43c25c29ac1f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1397,32 +1397,7 @@ void usb_autosuspend_device(struct usb_device *udev) int status; usb_mark_last_busy(udev); - 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); + 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); @@ -1508,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->dev.power.last_busy; 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); @@ -1651,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. @@ -1691,17 +1644,6 @@ 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->dev.power.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; } @@ -1719,17 +1661,8 @@ static int usb_runtime_suspend(struct device *dev) 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->dev.power.last_busy = jiffies + - (udev->autosuspend_delay == 0 ? HZ/2 : 0); - } - /* Prevent the parent from suspending immediately after */ - else if (udev->parent) + if (status == 0 && udev->parent) usb_mark_last_busy(udev->parent); return status; @@ -1756,7 +1689,7 @@ static int usb_runtime_idle(struct device *dev) * autosuspend checks. */ if (autosuspend_check(udev) == 0) - pm_runtime_suspend(dev); + pm_runtime_autosuspend(dev); return 0; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7c2405eccc4b..fdb62ca10d86 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1803,6 +1803,7 @@ 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_use_autosuspend(&udev->dev); pm_runtime_enable(&udev->dev); err = usb_enumerate_device(udev); /* Read descriptors */ diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 25719da45e33..e3531da16137 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -124,12 +124,6 @@ void usb_detect_quirks(struct usb_device *udev) */ 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 */ diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 9561e087907d..6781c369ce2d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -334,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; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index fdd4130fbb7d..079cb57bab4f 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -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 diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index cd882203ad34..b975450f403e 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -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; -- cgit From c08512c761e7b9eaaab0e9167a389393f268e93c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 15 Nov 2010 15:57:58 -0500 Subject: USB: improve uses of usb_mark_last_busy This patch (as1434) cleans up the uses of usb_mark_last_busy() in usbcore. The function will be called when a device is resumed and whenever a usage count is decremented. A call that was missing from the hub driver is added: A hub is used whenever one of its ports gets suspended (this prevents hubs from suspending immediately after their last child). In addition, the call to disable autosuspend support for new devices by default is moved from usb_detect_quirks() (where it doesn't really belong) into usb_new_device() along with all the other runtime-PM initializations. Finally, an extra pm_runtime_get_noresume() is added to prevent new devices from autosuspending while they are being registered. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 8 +------- drivers/usb/core/hub.c | 9 +++++++++ drivers/usb/core/quirks.c | 9 --------- 3 files changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 43c25c29ac1f..b9278a1fb9e5 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1261,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); @@ -1328,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); - usb_mark_last_busy(udev); do_unbind_rebind(udev, DO_REBIND); } } @@ -1660,11 +1660,6 @@ static int usb_runtime_suspend(struct device *dev) return -EAGAIN; status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); - - /* Prevent the parent from suspending immediately after */ - if (status == 0 && udev->parent) - usb_mark_last_busy(udev->parent); - return status; } @@ -1677,7 +1672,6 @@ static int usb_runtime_resume(struct device *dev) * and all its interfaces. */ status = usb_resume_both(udev, PMSG_AUTO_RESUME); - usb_mark_last_busy(udev); return status; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index fdb62ca10d86..b98efae6a1cf 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1803,9 +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; } diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index e3531da16137..44c595432d6f 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -117,15 +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); - -#endif - /* For the present, all devices default to USB-PERSIST enabled */ #if 0 /* was: #ifdef CONFIG_PM */ /* Hubs are automatically enabled for USB-PERSIST */ -- cgit From 451a3c24b0135bce54542009b5fde43846c7cf67 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 17 Nov 2010 16:26:55 +0100 Subject: BKL: remove extraneous #include The big kernel lock has been removed from all these files at some point, leaving only the #include. Remove this too as a cleanup. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Torvalds --- drivers/usb/core/devices.c | 1 - drivers/usb/core/devio.c | 1 - drivers/usb/core/file.c | 1 - drivers/usb/core/inode.c | 1 - 4 files changed, 4 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index ddb4dc980923..a3d2e2399655 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 045bb4b823e1..a7131ad630f9 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 9fe34fb78ef1..cf6a5423de09 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "usb.h" diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 9819a4cc3b26..b690aa35df9a 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include "usb.h" -- cgit From 07a8cdd2bb17a4da68136d963b8bc71959bd31a5 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Thu, 18 Nov 2010 18:54:17 +0530 Subject: usb: musb: do not use dma for control transfers The Inventra DMA engine used with the MUSB controller in many SoCs cannot use DMA for control transfers on EP0, but can use DMA for all other transfers. The USB core maps urbs for DMA if hcd->self.uses_dma is true. (hcd->self.uses_dma is true for MUSB as well). Split the uses_dma flag into two - one that says if the controller needs to use PIO for control transfers, and another which says if the controller uses DMA (for all other transfers). Also, populate this flag for all MUSB by default. (Tested on OMAP3 and OMAP4 boards, with EHCI and MUSB HCDs simultaneously in use). Signed-off-by: Maulik Mankad Signed-off-by: Santosh Shilimkar Signed-off-by: Anand Gadiyar Cc: Oliver Neukum Cc: Alan Stern Cc: Praveena NADAHALLY Cc: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/core/hcd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 61800f77dac8..ced846ac4141 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, */ if (usb_endpoint_xfer_control(&urb->ep->desc)) { + if (hcd->self.uses_pio_for_control) + return ret; if (hcd->self.uses_dma) { urb->setup_dma = dma_map_single( hcd->self.controller, -- cgit From f4ce9084476dc518bfd0f35f62f4bd0a130893e0 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Thu, 16 Dec 2010 14:32:24 +0530 Subject: USB: core: Add input prompt and help text for USB_OTG config bd6882 commit (usb: gadget: fix Kconfig warning) removes the duplicate USB_OTG config from gadget/Kconfig. But does not copy the input prompt and help text to the original config defined in core/Kconfig. Add them now. Signed-off-by: Pavankumar Kondeti Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/Kconfig | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 9eed5b52d9de..bcc24779ba0e 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -107,11 +107,19 @@ config USB_SUSPEND If you are unsure about this, say N here. config USB_OTG - bool + bool "OTG support" depends on USB && EXPERIMENTAL depends on USB_SUSPEND default n - + help + The most notable feature of USB OTG is support for a + "Dual-Role" device, which can act as either a device + or a host. The initial role is decided by the type of + plug inserted and can be changed later when two dual + role devices talk to each other. + + Select this only if your board has Mini-AB/Micro-AB + connector. config USB_OTG_WHITELIST bool "Rely on OTG Targeted Peripherals List" -- cgit From da5029563a0a026c64821b09e8e7b4fd81d3fe1b Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 7 Jan 2011 17:49:33 +1100 Subject: fs: dcache scale d_unhashed Protect d_unhashed(dentry) condition with d_lock. This means keeping DCACHE_UNHASHED bit in synch with hash manipulations. Signed-off-by: Nick Piggin --- drivers/usb/core/inode.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index b690aa35df9a..e3ab4437ea96 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -347,10 +347,13 @@ static int usbfs_empty (struct dentry *dentry) list_for_each(list, &dentry->d_subdirs) { struct dentry *de = list_entry(list, struct dentry, d_u.d_child); + spin_lock(&de->d_lock); if (usbfs_positive(de)) { + spin_unlock(&de->d_lock); spin_unlock(&dcache_lock); return 0; } + spin_unlock(&de->d_lock); } spin_unlock(&dcache_lock); -- cgit From 2fd6b7f50797f2e993eea59e0a0b8c6399c811dc Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 7 Jan 2011 17:49:34 +1100 Subject: fs: dcache scale subdirs Protect d_subdirs and d_child with d_lock, except in filesystems that aren't using dcache_lock for these anyway (eg. using i_mutex). Note: if we change the locking rule in future so that ->d_child protection is provided only with ->d_parent->d_lock, it may allow us to reduce some locking. But it would be an exception to an otherwise regular locking scheme, so we'd have to see some good results. Probably not worthwhile. Signed-off-by: Nick Piggin --- drivers/usb/core/inode.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index e3ab4437ea96..89a0e8366585 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -344,18 +344,20 @@ static int usbfs_empty (struct dentry *dentry) struct list_head *list; spin_lock(&dcache_lock); - + spin_lock(&dentry->d_lock); list_for_each(list, &dentry->d_subdirs) { struct dentry *de = list_entry(list, struct dentry, d_u.d_child); - spin_lock(&de->d_lock); + + spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED); if (usbfs_positive(de)) { spin_unlock(&de->d_lock); + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); return 0; } spin_unlock(&de->d_lock); } - + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); return 1; } -- cgit From b5c84bf6f6fa3a7dfdcb556023a62953574b60ee Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 7 Jan 2011 17:49:38 +1100 Subject: fs: dcache remove dcache_lock dcache_lock no longer protects anything. remove it. Signed-off-by: Nick Piggin --- drivers/usb/core/inode.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 89a0e8366585..1b125c224dcf 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -343,7 +343,6 @@ static int usbfs_empty (struct dentry *dentry) { struct list_head *list; - spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); list_for_each(list, &dentry->d_subdirs) { struct dentry *de = list_entry(list, struct dentry, d_u.d_child); @@ -352,13 +351,11 @@ static int usbfs_empty (struct dentry *dentry) if (usbfs_positive(de)) { spin_unlock(&de->d_lock); spin_unlock(&dentry->d_lock); - spin_unlock(&dcache_lock); return 0; } spin_unlock(&de->d_lock); } spin_unlock(&dentry->d_lock); - spin_unlock(&dcache_lock); return 1; } -- cgit