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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ff9c895f07
commit
7560d32ec7
@@ -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);
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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.
|
||||||
|
Reference in New Issue
Block a user