aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci.h
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-09-18 20:03:16 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:59:00 -0400
commit26f953fd884ea4879585287917f855c63c6b2666 (patch)
tree78e6bd71dc1bb4089bc8589eb995765d64d4797d /drivers/usb/host/ehci.h
parent353a4098c61272b33a02ec5802fb3859fec91a0e (diff)
USB: EHCI update VIA workaround
This revamps handling of the hardware "async advance" IRQ, and its watchdog timer. Basically it dis-entangles that important timeout from the others, simplifying the associated state and code to make it more robust. This reportedly improves behavior of EHCI on some systems with VIA chips, and AFAIK won't affect non-VIA hardware. VIA systems need this code to recover from silcon bugs whereby the "async advance" IRQ isn't issued. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci.h')
-rw-r--r--drivers/usb/host/ehci.h22
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082a73d7..6aac39f50e07 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -58,7 +58,6 @@ struct ehci_hcd { /* one per controller */
58 /* async schedule support */ 58 /* async schedule support */
59 struct ehci_qh *async; 59 struct ehci_qh *async;
60 struct ehci_qh *reclaim; 60 struct ehci_qh *reclaim;
61 unsigned reclaim_ready : 1;
62 unsigned scanning : 1; 61 unsigned scanning : 1;
63 62
64 /* periodic schedule support */ 63 /* periodic schedule support */
@@ -81,6 +80,7 @@ struct ehci_hcd { /* one per controller */
81 struct dma_pool *itd_pool; /* itd per iso urb */ 80 struct dma_pool *itd_pool; /* itd per iso urb */
82 struct dma_pool *sitd_pool; /* sitd per split iso urb */ 81 struct dma_pool *sitd_pool; /* sitd per split iso urb */
83 82
83 struct timer_list iaa_watchdog;
84 struct timer_list watchdog; 84 struct timer_list watchdog;
85 unsigned long actions; 85 unsigned long actions;
86 unsigned stamp; 86 unsigned stamp;
@@ -114,9 +114,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
114} 114}
115 115
116 116
117static inline void
118iaa_watchdog_start (struct ehci_hcd *ehci)
119{
120 WARN_ON(timer_pending(&ehci->iaa_watchdog));
121 mod_timer (&ehci->iaa_watchdog,
122 jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
123}
124
125static inline void iaa_watchdog_done (struct ehci_hcd *ehci)
126{
127 del_timer (&ehci->iaa_watchdog);
128}
129
117enum ehci_timer_action { 130enum ehci_timer_action {
118 TIMER_IO_WATCHDOG, 131 TIMER_IO_WATCHDOG,
119 TIMER_IAA_WATCHDOG,
120 TIMER_ASYNC_SHRINK, 132 TIMER_ASYNC_SHRINK,
121 TIMER_ASYNC_OFF, 133 TIMER_ASYNC_OFF,
122}; 134};
@@ -134,9 +146,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
134 unsigned long t; 146 unsigned long t;
135 147
136 switch (action) { 148 switch (action) {
137 case TIMER_IAA_WATCHDOG:
138 t = EHCI_IAA_JIFFIES;
139 break;
140 case TIMER_IO_WATCHDOG: 149 case TIMER_IO_WATCHDOG:
141 t = EHCI_IO_JIFFIES; 150 t = EHCI_IO_JIFFIES;
142 break; 151 break;
@@ -153,8 +162,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
153 // async queue SHRINK often precedes IAA. while it's ready 162 // async queue SHRINK often precedes IAA. while it's ready
154 // to go OFF neither can matter, and afterwards the IO 163 // to go OFF neither can matter, and afterwards the IO
155 // watchdog stops unless there's still periodic traffic. 164 // watchdog stops unless there's still periodic traffic.
156 if (action != TIMER_IAA_WATCHDOG 165 if (time_before_eq(t, ehci->watchdog.expires)
157 && t > ehci->watchdog.expires
158 && timer_pending (&ehci->watchdog)) 166 && timer_pending (&ehci->watchdog))
159 return; 167 return;
160 mod_timer (&ehci->watchdog, t); 168 mod_timer (&ehci->watchdog, t);