Commit 056761e5 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

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: default avatarDavid 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: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4b828abe
...@@ -177,6 +177,15 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) ...@@ -177,6 +177,15 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
static inline void static inline void
timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) 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)) { if (!test_and_set_bit (action, &ehci->actions)) {
unsigned long t; unsigned long t;
...@@ -192,15 +201,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) ...@@ -192,15 +201,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
t = EHCI_SHRINK_JIFFIES; t = EHCI_SHRINK_JIFFIES;
break; break;
} }
t += jiffies; mod_timer(&ehci->watchdog, 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);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment