Browse Source

USB: Allow autosuspend delay to equal 0

This patch (as867) adds an entry for the new power/autosuspend
attribute in Documentation/ABI/testing, and it changes the behavior of
the delay value.  Now a delay of 0 means to autosuspend as soon as
possible, and negative values will prevent autosuspend.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Alan Stern 18 years ago
parent
commit
eaafbc3a8a

+ 15 - 0
Documentation/ABI/testing/sysfs-bus-usb

@@ -0,0 +1,15 @@
+What:		/sys/bus/usb/devices/.../power/autosuspend
+Date:		March 2007
+KernelVersion:	2.6.21
+Contact:	Alan Stern <stern@rowland.harvard.edu>
+Description:
+		Each USB device directory will contain a file named
+		power/autosuspend.  This file holds the time (in seconds)
+		the device must be idle before it will be autosuspended.
+		0 means the device will be autosuspended as soon as
+		possible.  Negative values will prevent the device from
+		being autosuspended at all, and writing a negative value
+		will resume the device if it is already suspended.
+
+		The autosuspend delay for newly-created devices is set to
+		the value of the usbcore.autosuspend module parameter.

+ 1 - 1
Documentation/kernel-parameters.txt

@@ -1792,7 +1792,7 @@ and is between 256 and 4096 characters. It is defined in the file
 			for newly-detected USB devices (default 2).  This
 			for newly-detected USB devices (default 2).  This
 			is the time required before an idle device will be
 			is the time required before an idle device will be
 			autosuspended.  Devices for which the delay is set
 			autosuspended.  Devices for which the delay is set
-			to 0 won't be autosuspended at all.
+			to a negative value won't be autosuspended at all.
 
 
 	usbhid.mousepoll=
 	usbhid.mousepoll=
 			[USBHID] The interval which mice are to be polled at.
 			[USBHID] The interval which mice are to be polled at.

+ 1 - 1
drivers/usb/core/driver.c

@@ -970,7 +970,7 @@ static int autosuspend_check(struct usb_device *udev)
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 	if (udev->pm_usage_cnt > 0)
 	if (udev->pm_usage_cnt > 0)
 		return -EBUSY;
 		return -EBUSY;
-	if (!udev->autosuspend_delay)
+	if (udev->autosuspend_delay < 0)
 		return -EPERM;
 		return -EPERM;
 
 
 	if (udev->actconfig) {
 	if (udev->actconfig) {

+ 10 - 6
drivers/usb/core/sysfs.c

@@ -165,7 +165,7 @@ show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
 {
 {
 	struct usb_device *udev = to_usb_device(dev);
 	struct usb_device *udev = to_usb_device(dev);
 
 
-	return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ);
+	return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
 }
 }
 
 
 static ssize_t
 static ssize_t
@@ -173,17 +173,21 @@ 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);
-	unsigned value, old;
+	int value;
 
 
-	if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ)
+	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
+			value <= - INT_MAX/HZ)
 		return -EINVAL;
 		return -EINVAL;
 	value *= HZ;
 	value *= HZ;
 
 
-	old = udev->autosuspend_delay;
 	udev->autosuspend_delay = value;
 	udev->autosuspend_delay = value;
-	if (value > 0 && old == 0)
+	if (value >= 0)
 		usb_try_autosuspend_device(udev);
 		usb_try_autosuspend_device(udev);
-
+	else {
+		usb_lock_device(udev);
+		usb_external_resume_device(udev);
+		usb_unlock_device(udev);
+	}
 	return count;
 	return count;
 }
 }
 
 

+ 1 - 1
drivers/usb/core/usb.c

@@ -55,7 +55,7 @@ struct workqueue_struct *ksuspend_usb_wq;
 #ifdef	CONFIG_USB_SUSPEND
 #ifdef	CONFIG_USB_SUSPEND
 static int usb_autosuspend_delay = 2;		/* Default delay value,
 static int usb_autosuspend_delay = 2;		/* Default delay value,
 						 * in seconds */
 						 * in seconds */
-module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644);
+module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
 MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
 MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
 
 
 #else
 #else

+ 1 - 1
include/linux/usb.h

@@ -394,7 +394,7 @@ struct usb_device {
 	struct delayed_work autosuspend; /* for delayed autosuspends */
 	struct delayed_work autosuspend; /* for delayed autosuspends */
 	struct mutex pm_mutex;		/* protects PM operations */
 	struct mutex pm_mutex;		/* protects PM operations */
 
 
-	unsigned autosuspend_delay;	/* in jiffies */
+	int autosuspend_delay;		/* in jiffies */
 
 
 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
 	unsigned auto_pm:1;		/* autosuspend/resume in progress */
 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */
 	unsigned do_remote_wakeup:1;	/* remote wakeup should be enabled */