diff options
author | Alan Stern | 2010-05-11 17:44:06 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2010-05-20 22:21:45 +0200 |
commit | 89842ae6515c49405e20c0629a6442b6885ad49d (patch) | |
tree | aab7bc2ef74ffaf607ac1bcc5d2dbbfbc94eb13e /drivers/usb | |
parent | USB: xHCI: Fix wrong usage of macro TRB_TYPE (diff) | |
download | kernel-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.c | 17 |
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() |