Commit 7560d32e authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: improve runtime remote wakeup settings

This patch (as1362) adjusts the way the USB autosuspend routines
handle remote-wakeup settings.  They aren't supposed to use
device_may_wakeup(); that test is intended only for system sleep, not
runtime power management.  Instead the code checks to see if any
interface drivers need remote wakeup; if they do then it is enabled,
provided the device is capable of it.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ff9c895f
...@@ -1486,9 +1486,6 @@ int usb_autoresume_device(struct usb_device *udev) ...@@ -1486,9 +1486,6 @@ int usb_autoresume_device(struct usb_device *udev)
* 0, a delayed autosuspend request for @intf's device is attempted. The * 0, a delayed autosuspend request for @intf's device is attempted. The
* attempt may fail (see autosuspend_check()). * attempt may fail (see autosuspend_check()).
* *
* If the driver has set @intf->needs_remote_wakeup then autosuspend will
* take place only if the device's remote-wakeup facility is enabled.
*
* This routine can run only in process context. * This routine can run only in process context.
*/ */
void usb_autopm_put_interface(struct usb_interface *intf) void usb_autopm_put_interface(struct usb_interface *intf)
...@@ -1673,14 +1670,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume); ...@@ -1673,14 +1670,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
/* Internal routine to check whether we may autosuspend a device. */ /* Internal routine to check whether we may autosuspend a device. */
static int autosuspend_check(struct usb_device *udev) static int autosuspend_check(struct usb_device *udev)
{ {
int i; int w, i;
struct usb_interface *intf; struct usb_interface *intf;
unsigned long suspend_time, j; unsigned long suspend_time, j;
/* Fail if autosuspend is disabled, or any interfaces are in use, or /* Fail if autosuspend is disabled, or any interfaces are in use, or
* any interface drivers require remote wakeup but it isn't available. * any interface drivers require remote wakeup but it isn't available.
*/ */
udev->do_remote_wakeup = device_may_wakeup(&udev->dev); w = 0;
if (udev->actconfig) { if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
...@@ -1694,12 +1691,7 @@ static int autosuspend_check(struct usb_device *udev) ...@@ -1694,12 +1691,7 @@ static int autosuspend_check(struct usb_device *udev)
continue; continue;
if (atomic_read(&intf->dev.power.usage_count) > 0) if (atomic_read(&intf->dev.power.usage_count) > 0)
return -EBUSY; return -EBUSY;
if (intf->needs_remote_wakeup && w |= intf->needs_remote_wakeup;
!udev->do_remote_wakeup) {
dev_dbg(&udev->dev, "remote wakeup needed "
"for autosuspend\n");
return -EOPNOTSUPP;
}
/* Don't allow autosuspend if the device will need /* Don't allow autosuspend if the device will need
* a reset-resume and any of its interface drivers * a reset-resume and any of its interface drivers
...@@ -1715,6 +1707,11 @@ static int autosuspend_check(struct usb_device *udev) ...@@ -1715,6 +1707,11 @@ static int autosuspend_check(struct usb_device *udev)
} }
} }
} }
if (w && !device_can_wakeup(&udev->dev)) {
dev_dbg(&udev->dev, "remote wakeup needed for autosuspend\n");
return -EOPNOTSUPP;
}
udev->do_remote_wakeup = w;
/* If everything is okay but the device hasn't been idle for long /* If everything is okay but the device hasn't been idle for long
* enough, queue a delayed autosuspend request. * enough, queue a delayed autosuspend request.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment