summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern2010-05-11 17:44:06 +0200
committerGreg Kroah-Hartman2010-05-20 22:21:45 +0200
commit89842ae6515c49405e20c0629a6442b6885ad49d (patch)
treeaab7bc2ef74ffaf607ac1bcc5d2dbbfbc94eb13e /drivers/usb
parentUSB: xHCI: Fix wrong usage of macro TRB_TYPE (diff)
downloadkernel-qcow2-linux-89842ae6515c49405e20c0629a6442b6885ad49d.tar.gz
kernel-qcow2-linux-89842ae6515c49405e20c0629a6442b6885ad49d.tar.xz
kernel-qcow2-linux-89842ae6515c49405e20c0629a6442b6885ad49d.zip
USB: fix interface runtime-PM settings
This patch (as1379) reworks the logic for handling USB interface runtime-PM settings -- hopefully it's right this time! The problem is that when a driver is unbound or binding fails, runtime PM for the interface always gets disabled. But pm_runtime_disable() nests, so it shouldn't be called unless the interface was previously enabled for runtime PM. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Reported-by: Rob Duncan <Robert.Duncan@exar.com> Tested-by: Rob Duncan <Robert.Duncan@exar.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/driver.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 207146743ea7..ded550eda5d9 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -334,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);
@@ -389,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 */
@@ -438,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()