aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-01-07 03:47:42 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:35:02 -0500
commit79592b722e7a8476680197d97352d2cc0f1bffd2 (patch)
treef7900c1a6116414b5e0d81b4359d3601c23e4a19 /drivers/usb
parentaa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9 (diff)
USB: ehci completes high speed ISO URBs sooner
This has some bugfixes for the EHCI driver's ISO transfer scanning logic. It was leaving ITDs and SITDs on the schedule too long, for a few different reasons, which caused trouble. (a) Look at all microframes for high speed transfers, not just the ones we expect to have finished. This way transfers ending mid-frame will complete without needing another IRQ. This also minimizes bogus scheduling underruns (e.g. EL2NSYNC). (b) When we encounter an ISO transfer (either speed, but this hits mostly at full speed) that's not yet been completed, immediately stop scanning; we've caught up to the hardware, no matter what other indications might say. (c) Always clean up ITDs (for high speed transfers) when the HC is no longer running. I'm not sure whether the last one has been observed before, but both the others have been reported with "real world" audio and video code. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-sched.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 001b2c389be2..8a8e08a51ba3 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -2123,17 +2123,9 @@ scan_periodic (struct ehci_hcd *ehci)
2123 for (;;) { 2123 for (;;) {
2124 union ehci_shadow q, *q_p; 2124 union ehci_shadow q, *q_p;
2125 __hc32 type, *hw_p; 2125 __hc32 type, *hw_p;
2126 unsigned uframes; 2126 unsigned incomplete = false;
2127 2127
2128 /* don't scan past the live uframe */
2129 frame = now_uframe >> 3; 2128 frame = now_uframe >> 3;
2130 if (frame == (clock >> 3))
2131 uframes = now_uframe & 0x07;
2132 else {
2133 /* safe to scan the whole frame at once */
2134 now_uframe |= 0x07;
2135 uframes = 8;
2136 }
2137 2129
2138restart: 2130restart:
2139 /* scan each element in frame's queue for completions */ 2131 /* scan each element in frame's queue for completions */
@@ -2171,12 +2163,15 @@ restart:
2171 q = q.fstn->fstn_next; 2163 q = q.fstn->fstn_next;
2172 break; 2164 break;
2173 case Q_TYPE_ITD: 2165 case Q_TYPE_ITD:
2174 /* skip itds for later in the frame */ 2166 /* If this ITD is still active, leave it for
2167 * later processing ... check the next entry.
2168 */
2175 rmb (); 2169 rmb ();
2176 for (uf = live ? uframes : 8; uf < 8; uf++) { 2170 for (uf = 0; uf < 8 && live; uf++) {
2177 if (0 == (q.itd->hw_transaction [uf] 2171 if (0 == (q.itd->hw_transaction [uf]
2178 & ITD_ACTIVE(ehci))) 2172 & ITD_ACTIVE(ehci)))
2179 continue; 2173 continue;
2174 incomplete = true;
2180 q_p = &q.itd->itd_next; 2175 q_p = &q.itd->itd_next;
2181 hw_p = &q.itd->hw_next; 2176 hw_p = &q.itd->hw_next;
2182 type = Q_NEXT_TYPE(ehci, 2177 type = Q_NEXT_TYPE(ehci,
@@ -2184,10 +2179,12 @@ restart:
2184 q = *q_p; 2179 q = *q_p;
2185 break; 2180 break;
2186 } 2181 }
2187 if (uf != 8) 2182 if (uf < 8 && live)
2188 break; 2183 break;
2189 2184
2190 /* this one's ready ... HC won't cache the 2185 /* Take finished ITDs out of the schedule
2186 * and process them: recycle, maybe report
2187 * URB completion. HC won't cache the
2191 * pointer for much longer, if at all. 2188 * pointer for much longer, if at all.
2192 */ 2189 */
2193 *q_p = q.itd->itd_next; 2190 *q_p = q.itd->itd_next;
@@ -2198,8 +2195,12 @@ restart:
2198 q = *q_p; 2195 q = *q_p;
2199 break; 2196 break;
2200 case Q_TYPE_SITD: 2197 case Q_TYPE_SITD:
2198 /* If this SITD is still active, leave it for
2199 * later processing ... check the next entry.
2200 */
2201 if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) 2201 if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
2202 && live) { 2202 && live) {
2203 incomplete = true;
2203 q_p = &q.sitd->sitd_next; 2204 q_p = &q.sitd->sitd_next;
2204 hw_p = &q.sitd->hw_next; 2205 hw_p = &q.sitd->hw_next;
2205 type = Q_NEXT_TYPE(ehci, 2206 type = Q_NEXT_TYPE(ehci,
@@ -2207,6 +2208,11 @@ restart:
2207 q = *q_p; 2208 q = *q_p;
2208 break; 2209 break;
2209 } 2210 }
2211
2212 /* Take finished SITDs out of the schedule
2213 * and process them: recycle, maybe report
2214 * URB completion.
2215 */
2210 *q_p = q.sitd->sitd_next; 2216 *q_p = q.sitd->sitd_next;
2211 *hw_p = q.sitd->hw_next; 2217 *hw_p = q.sitd->hw_next;
2212 type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); 2218 type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
@@ -2232,7 +2238,14 @@ restart:
2232 } 2238 }
2233 } 2239 }
2234 2240
2235 /* stop when we catch up to the HC */ 2241 /* If we can tell we caught up to the hardware, stop now.
2242 * We can't advance our scan without collecting the ISO
2243 * transfers that are still pending in this frame.
2244 */
2245 if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
2246 ehci->next_uframe = now_uframe;
2247 break;
2248 }
2236 2249
2237 // FIXME: this assumes we won't get lapped when 2250 // FIXME: this assumes we won't get lapped when
2238 // latencies climb; that should be rare, but... 2251 // latencies climb; that should be rare, but...