summaryrefslogtreecommitdiff
path: root/drivers/usb/core/sysfs.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-01-08 20:57:02 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-03 01:54:11 +0300
commit5899f1e020c8d53b2b6fbd6a6cf39c891ccdfade (patch)
treeacd9041996aa81db4bdc9a30fe1926e511d7eb77 /drivers/usb/core/sysfs.c
parent088f7fec8a0e683db72fd8826c5d3ab914e197b1 (diff)
downloadlinux-5899f1e020c8d53b2b6fbd6a6cf39c891ccdfade.tar.xz
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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r--drivers/usb/core/sysfs.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 313e241f5ccc..43c002e3a9aa 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -346,7 +346,8 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
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 ||
value <= - INT_MAX/HZ)
@@ -354,13 +355,24 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
value *= HZ;
usb_lock_device(udev);
+ old_delay = udev->autosuspend_delay;
udev->autosuspend_delay = value;
- if (value >= 0)
- usb_try_autosuspend_device(udev);
- else {
- if (usb_autoresume_device(udev) == 0)
+
+ if (old_delay < 0) { /* Autosuspend wasn't allowed */
+ if (value >= 0)
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);
return count;
}