diff options
author | David Brownell <david-b@pacbell.net> | 2008-06-13 23:56:48 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-07-03 18:20:36 -0700 |
commit | 056761e55c8687ddf3db14226213f2e8dc2689bc (patch) | |
tree | 0a462ad33cc3c78bc7c520c50aa2b6c9c2a7c1cd /drivers/usb/host | |
parent | 4b828abed217527ca815727a1a251334bd8e5e04 (diff) | |
download | op-kernel-dev-056761e55c8687ddf3db14226213f2e8dc2689bc.zip op-kernel-dev-056761e55c8687ddf3db14226213f2e8dc2689bc.tar.gz |
USB: ehci - fix timer regression
This patch fixes a regression in the EHCI driver's TIMER_IO_WATCHDOG
behavior. The patch "USB: EHCI: add separate IAA watchdog timer" changed
how that timer is handled, so that short timeouts on the remaining
timer (unfortunately, overloaded) would never be used.
This takes a more direct approach, reorganizing the code slightly to
be explicit about only the I/O watchdog role now being overridable.
It also replaces a now-obsolete comment describing older timer behavior.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Leonid <leonidv11@gmail.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci.h | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 35a0309..90245fd 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -177,6 +177,15 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) static inline void timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) { + /* Don't override timeouts which shrink or (later) disable + * the async ring; just the I/O watchdog. Note that if a + * SHRINK were pending, OFF would never be requested. + */ + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; + if (!test_and_set_bit (action, &ehci->actions)) { unsigned long t; @@ -192,15 +201,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) t = EHCI_SHRINK_JIFFIES; break; } - t += jiffies; - // all timings except IAA watchdog can be overridden. - // async queue SHRINK often precedes IAA. while it's ready - // to go OFF neither can matter, and afterwards the IO - // watchdog stops unless there's still periodic traffic. - if (time_before_eq(t, ehci->watchdog.expires) - && timer_pending (&ehci->watchdog)) - return; - mod_timer (&ehci->watchdog, t); + mod_timer(&ehci->watchdog, t + jiffies); } } |