summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-04-05 16:03:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-05-22 23:45:49 -0700
commitef7f6c7084b333c7524dcd297e0578d43733a2a2 (patch)
tree7c536304f8c98c0d25a583a3b15a80c1300fc614 /drivers/usb
parent4fe5354f61cad4c0550285283c83c66c070c198e (diff)
downloadlinux-ef7f6c7084b333c7524dcd297e0578d43733a2a2.tar.gz
linux-ef7f6c7084b333c7524dcd297e0578d43733a2a2.tar.bz2
linux-ef7f6c7084b333c7524dcd297e0578d43733a2a2.zip
USB: more autosuspend timer stuff
This patch (as879) ties up some loose ends from an earlier patch. These are things I didn't think to include at the time but which clearly belonged there. If an autosuspend fails because driver activity races with the autosuspend call, restart the autosuspend timer. When a device is resumed by an external request, it counts as device activity and should update the last_busy time so that the next autoresume won't occur immediately. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/driver.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index b9f7f90aef82..2619986e5300 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -983,7 +983,10 @@ static int autosuspend_check(struct usb_device *udev)
#else
-#define autosuspend_check(udev) 0
+static inline int autosuspend_check(struct usb_device *udev)
+{
+ return 0;
+}
#endif /* CONFIG_USB_SUSPEND */
@@ -1041,7 +1044,6 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
if (status < 0)
goto done;
}
- cancel_delayed_work(&udev->autosuspend);
/* Suspend all the interfaces and then udev itself */
if (udev->actconfig) {
@@ -1062,9 +1064,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
usb_resume_interface(intf);
}
+ /* Try another autosuspend when the interfaces aren't busy */
+ if (udev->auto_pm)
+ autosuspend_check(udev);
+
/* If the suspend succeeded, propagate it up the tree */
- } else if (parent)
- usb_autosuspend_device(parent);
+ } else {
+ cancel_delayed_work(&udev->autosuspend);
+ if (parent)
+ usb_autosuspend_device(parent);
+ }
done:
// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
@@ -1475,6 +1484,7 @@ int usb_external_resume_device(struct usb_device *udev)
usb_pm_lock(udev);
udev->auto_pm = 0;
status = usb_resume_both(udev);
+ udev->last_busy = jiffies;
usb_pm_unlock(udev);
/* Now that the device is awake, we can start trying to autosuspend