Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −11
Original line number Original line Diff line number Diff line
@@ -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.