summaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorDan Streetman <ddstreet@ieee.org>2010-01-06 09:56:53 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 14:53:35 -0800
commit16985408b5c48585762ec3b9b7bae1dec4ad7437 (patch)
tree1db9d25a5e4319c3fb85d9e71a736e76ad8dc0b0 /drivers/usb/core
parentce126644aa10bf1d8f1c1929b65adab026095761 (diff)
USB: retain USB device power/wakeup setting across reconfiguration
Currently a non-root-hub USB device's wakeup settings are initialized when the device is set to a configured state using device_init_wakeup(), but this is not correct as wakeup is split into "capable" (can_wakeup) and "enabled" (should_wakeup). The settings should be initialized instead in the device initialization (usb_new_device) with the "capable" setting disabled and the "enabled" setting enabled. The "capable" setting should be set based on the device being configured or unconfigured, and "enabled" setting set based on the sysfs power/wakeup control. This patch retains the sysfs power/wakeup setting of a non-root-hub USB device over a USB device re-configuration, which can happen (for example) after a suspend/resume cycle. Signed-off-by: Dan Streetman <ddstreet@ieee.org> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hub.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index bb416cdee1a..6f84d383ece 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1448,11 +1448,11 @@ void usb_set_device_state(struct usb_device *udev,
|| new_state == USB_STATE_SUSPENDED)
; /* No change to wakeup settings */
else if (new_state == USB_STATE_CONFIGURED)
- device_init_wakeup(&udev->dev,
+ device_set_wakeup_capable(&udev->dev,
(udev->actconfig->desc.bmAttributes
& USB_CONFIG_ATT_WAKEUP));
else
- device_init_wakeup(&udev->dev, 0);
+ device_set_wakeup_capable(&udev->dev, 0);
}
if (udev->state == USB_STATE_SUSPENDED &&
new_state != USB_STATE_SUSPENDED)
@@ -1799,10 +1799,18 @@ int usb_new_device(struct usb_device *udev)
{
int err;
- /* Increment the parent's count of unsuspended children */
- if (udev->parent)
+ if (udev->parent) {
+ /* Increment the parent's count of unsuspended children */
usb_autoresume_device(udev->parent);
+ /* Initialize non-root-hub device wakeup to disabled;
+ * device (un)configuration controls wakeup capable
+ * sysfs power/wakeup controls wakeup enabled/disabled
+ */
+ device_init_wakeup(&udev->dev, 0);
+ device_set_wakeup_enable(&udev->dev, 1);
+ }
+
usb_detect_quirks(udev);
err = usb_enumerate_device(udev); /* Read descriptors */
if (err < 0)