diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2010-01-08 12:57:02 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:54:11 -0500 |
commit | 5899f1e020c8d53b2b6fbd6a6cf39c891ccdfade (patch) | |
tree | acd9041996aa81db4bdc9a30fe1926e511d7eb77 /drivers | |
parent | 088f7fec8a0e683db72fd8826c5d3ab914e197b1 (diff) |
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')
-rw-r--r-- | drivers/usb/core/quirks.c | 10 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 22 |
2 files changed, 27 insertions, 5 deletions
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 4314f259524..f073c5cb4e7 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
@@ -103,11 +103,21 @@ void usb_detect_quirks(struct usb_device *udev) | |||
103 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", | 103 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", |
104 | udev->quirks); | 104 | udev->quirks); |
105 | 105 | ||
106 | #ifdef CONFIG_USB_SUSPEND | ||
107 | |||
106 | /* By default, disable autosuspend for all devices. The hub driver | 108 | /* By default, disable autosuspend for all devices. The hub driver |
107 | * will enable it for hubs. | 109 | * will enable it for hubs. |
108 | */ | 110 | */ |
109 | usb_disable_autosuspend(udev); | 111 | usb_disable_autosuspend(udev); |
110 | 112 | ||
113 | /* Autosuspend can also be disabled if the initial autosuspend_delay | ||
114 | * is negative. | ||
115 | */ | ||
116 | if (udev->autosuspend_delay < 0) | ||
117 | usb_autoresume_device(udev); | ||
118 | |||
119 | #endif | ||
120 | |||
111 | /* For the present, all devices default to USB-PERSIST enabled */ | 121 | /* For the present, all devices default to USB-PERSIST enabled */ |
112 | #if 0 /* was: #ifdef CONFIG_PM */ | 122 | #if 0 /* was: #ifdef CONFIG_PM */ |
113 | /* Hubs are automatically enabled for USB-PERSIST */ | 123 | /* Hubs are automatically enabled for USB-PERSIST */ |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 313e241f5cc..43c002e3a9a 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, | |||
346 | const char *buf, size_t count) | 346 | const char *buf, size_t count) |
347 | { | 347 | { |
348 | struct usb_device *udev = to_usb_device(dev); | 348 | struct usb_device *udev = to_usb_device(dev); |
349 | int value; | 349 | int value, old_delay; |
350 | int rc; | ||
350 | 351 | ||
351 | if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ || | 352 | if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ || |
352 | value <= - INT_MAX/HZ) | 353 | value <= - INT_MAX/HZ) |
@@ -354,13 +355,24 @@ set_autosuspend(struct device *dev, struct device_attribute *attr, | |||
354 | value *= HZ; | 355 | value *= HZ; |
355 | 356 | ||
356 | usb_lock_device(udev); | 357 | usb_lock_device(udev); |
358 | old_delay = udev->autosuspend_delay; | ||
357 | udev->autosuspend_delay = value; | 359 | udev->autosuspend_delay = value; |
358 | if (value >= 0) | 360 | |
359 | usb_try_autosuspend_device(udev); | 361 | if (old_delay < 0) { /* Autosuspend wasn't allowed */ |
360 | else { | 362 | if (value >= 0) |
361 | if (usb_autoresume_device(udev) == 0) | ||
362 | usb_autosuspend_device(udev); | 363 | usb_autosuspend_device(udev); |
364 | } else { /* Autosuspend was allowed */ | ||
365 | if (value < 0) { | ||
366 | rc = usb_autoresume_device(udev); | ||
367 | if (rc < 0) { | ||
368 | count = rc; | ||
369 | udev->autosuspend_delay = old_delay; | ||
370 | } | ||
371 | } else { | ||
372 | usb_try_autosuspend_device(udev); | ||
373 | } | ||
363 | } | 374 | } |
375 | |||
364 | usb_unlock_device(udev); | 376 | usb_unlock_device(udev); |
365 | return count; | 377 | return count; |
366 | } | 378 | } |