summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-06-13 23:56:48 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-07-03 18:20:36 -0700
commit056761e55c8687ddf3db14226213f2e8dc2689bc (patch)
tree0a462ad33cc3c78bc7c520c50aa2b6c9c2a7c1cd /drivers
parent4b828abed217527ca815727a1a251334bd8e5e04 (diff)
downloadlinux-3.10-056761e55c8687ddf3db14226213f2e8dc2689bc.tar.gz
linux-3.10-056761e55c8687ddf3db14226213f2e8dc2689bc.tar.bz2
linux-3.10-056761e55c8687ddf3db14226213f2e8dc2689bc.zip
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')
-rw-r--r--drivers/usb/host/ehci.h19
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 35a03095757..90245fd8bac 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);
}
}