diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-04-05 16:03:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-05-23 02:45:49 -0400 |
commit | ef7f6c7084b333c7524dcd297e0578d43733a2a2 (patch) | |
tree | 7c536304f8c98c0d25a583a3b15a80c1300fc614 /drivers/usb | |
parent | 4fe5354f61cad4c0550285283c83c66c070c198e (diff) |
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.c | 18 |
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) | |||
983 | 983 | ||
984 | #else | 984 | #else |
985 | 985 | ||
986 | #define autosuspend_check(udev) 0 | 986 | static inline int autosuspend_check(struct usb_device *udev) |
987 | { | ||
988 | return 0; | ||
989 | } | ||
987 | 990 | ||
988 | #endif /* CONFIG_USB_SUSPEND */ | 991 | #endif /* CONFIG_USB_SUSPEND */ |
989 | 992 | ||
@@ -1041,7 +1044,6 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1041 | if (status < 0) | 1044 | if (status < 0) |
1042 | goto done; | 1045 | goto done; |
1043 | } | 1046 | } |
1044 | cancel_delayed_work(&udev->autosuspend); | ||
1045 | 1047 | ||
1046 | /* Suspend all the interfaces and then udev itself */ | 1048 | /* Suspend all the interfaces and then udev itself */ |
1047 | if (udev->actconfig) { | 1049 | if (udev->actconfig) { |
@@ -1062,9 +1064,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1062 | usb_resume_interface(intf); | 1064 | usb_resume_interface(intf); |
1063 | } | 1065 | } |
1064 | 1066 | ||
1067 | /* Try another autosuspend when the interfaces aren't busy */ | ||
1068 | if (udev->auto_pm) | ||
1069 | autosuspend_check(udev); | ||
1070 | |||
1065 | /* If the suspend succeeded, propagate it up the tree */ | 1071 | /* If the suspend succeeded, propagate it up the tree */ |
1066 | } else if (parent) | 1072 | } else { |
1067 | usb_autosuspend_device(parent); | 1073 | cancel_delayed_work(&udev->autosuspend); |
1074 | if (parent) | ||
1075 | usb_autosuspend_device(parent); | ||
1076 | } | ||
1068 | 1077 | ||
1069 | done: | 1078 | done: |
1070 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | 1079 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); |
@@ -1475,6 +1484,7 @@ int usb_external_resume_device(struct usb_device *udev) | |||
1475 | usb_pm_lock(udev); | 1484 | usb_pm_lock(udev); |
1476 | udev->auto_pm = 0; | 1485 | udev->auto_pm = 0; |
1477 | status = usb_resume_both(udev); | 1486 | status = usb_resume_both(udev); |
1487 | udev->last_busy = jiffies; | ||
1478 | usb_pm_unlock(udev); | 1488 | usb_pm_unlock(udev); |
1479 | 1489 | ||
1480 | /* Now that the device is awake, we can start trying to autosuspend | 1490 | /* Now that the device is awake, we can start trying to autosuspend |