Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>


authored by

Dan Streetman and committed by
Greg Kroah-Hartman
16985408 ce126644

+12 -4
+12 -4
drivers/usb/core/hub.c
··· 1448 1448 || new_state == USB_STATE_SUSPENDED) 1449 1449 ; /* No change to wakeup settings */ 1450 1450 else if (new_state == USB_STATE_CONFIGURED) 1451 - device_init_wakeup(&udev->dev, 1451 + device_set_wakeup_capable(&udev->dev, 1452 1452 (udev->actconfig->desc.bmAttributes 1453 1453 & USB_CONFIG_ATT_WAKEUP)); 1454 1454 else 1455 - device_init_wakeup(&udev->dev, 0); 1455 + device_set_wakeup_capable(&udev->dev, 0); 1456 1456 } 1457 1457 if (udev->state == USB_STATE_SUSPENDED && 1458 1458 new_state != USB_STATE_SUSPENDED) ··· 1799 1799 { 1800 1800 int err; 1801 1801 1802 - /* Increment the parent's count of unsuspended children */ 1803 - if (udev->parent) 1802 + if (udev->parent) { 1803 + /* Increment the parent's count of unsuspended children */ 1804 1804 usb_autoresume_device(udev->parent); 1805 + 1806 + /* Initialize non-root-hub device wakeup to disabled; 1807 + * device (un)configuration controls wakeup capable 1808 + * sysfs power/wakeup controls wakeup enabled/disabled 1809 + */ 1810 + device_init_wakeup(&udev->dev, 0); 1811 + device_set_wakeup_enable(&udev->dev, 1); 1812 + } 1805 1813 1806 1814 usb_detect_quirks(udev); 1807 1815 err = usb_enumerate_device(udev); /* Read descriptors */