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

Commit 5899f1e0 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: change handling of negative autosuspend delays



This patch (as1327) changes the way negative autosuspend delays
prevent device from autosuspending.  The current code checks for
negative values explicitly in the autosuspend_check() routine.  The
updated code keeps things from getting that far by using
usb_autoresume_device() to increment the usage counter when a negative
delay is set, and by using usb_autosuspend_device() to decrement the
usage counter when a non-negative delay is set.

This complicates the set_autosuspend() attribute method code slightly,
but it will reduce the overall power management overhead.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 088f7fec
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -103,11 +103,21 @@ void usb_detect_quirks(struct usb_device *udev)
		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
				udev->quirks);
				udev->quirks);


#ifdef	CONFIG_USB_SUSPEND

	/* By default, disable autosuspend for all devices.  The hub driver
	/* By default, disable autosuspend for all devices.  The hub driver
	 * will enable it for hubs.
	 * will enable it for hubs.
	 */
	 */
	usb_disable_autosuspend(udev);
	usb_disable_autosuspend(udev);


	/* Autosuspend can also be disabled if the initial autosuspend_delay
	 * is negative.
	 */
	if (udev->autosuspend_delay < 0)
		usb_autoresume_device(udev);

#endif

	/* For the present, all devices default to USB-PERSIST enabled */
	/* For the present, all devices default to USB-PERSIST enabled */
#if 0		/* was: #ifdef CONFIG_PM */
#if 0		/* was: #ifdef CONFIG_PM */
	/* Hubs are automatically enabled for USB-PERSIST */
	/* Hubs are automatically enabled for USB-PERSIST */
+17 −5
Original line number Original line Diff line number Diff line
@@ -346,7 +346,8 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
		const char *buf, size_t count)
{
{
	struct usb_device *udev = to_usb_device(dev);
	struct usb_device *udev = to_usb_device(dev);
	int value;
	int value, old_delay;
	int rc;


	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
			value <= - INT_MAX/HZ)
			value <= - INT_MAX/HZ)
@@ -354,13 +355,24 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
	value *= HZ;
	value *= HZ;


	usb_lock_device(udev);
	usb_lock_device(udev);
	old_delay = udev->autosuspend_delay;
	udev->autosuspend_delay = value;
	udev->autosuspend_delay = value;

	if (old_delay < 0) {	/* Autosuspend wasn't allowed */
		if (value >= 0)
		if (value >= 0)
		usb_try_autosuspend_device(udev);
	else {
		if (usb_autoresume_device(udev) == 0)
			usb_autosuspend_device(udev);
			usb_autosuspend_device(udev);
	} else {		/* Autosuspend was allowed */
		if (value < 0) {
			rc = usb_autoresume_device(udev);
			if (rc < 0) {
				count = rc;
				udev->autosuspend_delay = old_delay;
			}
			}
		} else {
			usb_try_autosuspend_device(udev);
		}
	}

	usb_unlock_device(udev);
	usb_unlock_device(udev);
	return count;
	return count;
}
}