USB: EHCI: add separate IAA watchdog timer
This patch (as1028) was mostly written by David Brownell; I made only a few changes (extra log info and a small bug fix -- which might account for why David's version had to be reverted). It adds a new watchdog timer to the ehci-hcd driver to be used exclusively for detecting lost or missing IAA notifications. Previously a shared timer had been used, which may have led to some problems as reported by Christian Hoffmann. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
2e2eb83ffd
commit
07d29b63ef
@@ -74,7 +74,6 @@ struct ehci_hcd { /* one per controller */
|
||||
/* async schedule support */
|
||||
struct ehci_qh *async;
|
||||
struct ehci_qh *reclaim;
|
||||
unsigned reclaim_ready : 1;
|
||||
unsigned scanning : 1;
|
||||
|
||||
/* periodic schedule support */
|
||||
@@ -105,6 +104,7 @@ struct ehci_hcd { /* one per controller */
|
||||
struct dma_pool *itd_pool; /* itd per iso urb */
|
||||
struct dma_pool *sitd_pool; /* sitd per split iso urb */
|
||||
|
||||
struct timer_list iaa_watchdog;
|
||||
struct timer_list watchdog;
|
||||
unsigned long actions;
|
||||
unsigned stamp;
|
||||
@@ -148,9 +148,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
iaa_watchdog_start(struct ehci_hcd *ehci)
|
||||
{
|
||||
WARN_ON(timer_pending(&ehci->iaa_watchdog));
|
||||
mod_timer(&ehci->iaa_watchdog,
|
||||
jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
|
||||
}
|
||||
|
||||
static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
|
||||
{
|
||||
del_timer(&ehci->iaa_watchdog);
|
||||
}
|
||||
|
||||
enum ehci_timer_action {
|
||||
TIMER_IO_WATCHDOG,
|
||||
TIMER_IAA_WATCHDOG,
|
||||
TIMER_ASYNC_SHRINK,
|
||||
TIMER_ASYNC_OFF,
|
||||
};
|
||||
@@ -168,9 +180,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
|
||||
unsigned long t;
|
||||
|
||||
switch (action) {
|
||||
case TIMER_IAA_WATCHDOG:
|
||||
t = EHCI_IAA_JIFFIES;
|
||||
break;
|
||||
case TIMER_IO_WATCHDOG:
|
||||
t = EHCI_IO_JIFFIES;
|
||||
break;
|
||||
@@ -187,8 +196,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
|
||||
// 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 (action != TIMER_IAA_WATCHDOG
|
||||
&& t > ehci->watchdog.expires
|
||||
if (time_before_eq(t, ehci->watchdog.expires)
|
||||
&& timer_pending (&ehci->watchdog))
|
||||
return;
|
||||
mod_timer (&ehci->watchdog, t);
|
||||
|
Reference in New Issue
Block a user