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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
088f7fec8a
commit
5899f1e020
@@ -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 */
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user