aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:23:07 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:56:47 -0400
commitf42890782241a60d107f23d08089a4a12b507a11 (patch)
tree8e2049cf96ccdbfa7bca7bdbfb38aa329c18325d /drivers
parent18aafe64d75d0e27dae206cacf4171e4e485d285 (diff)
USB: EHCI: simplify isochronous scanning
This patch (as1587) simplifies ehci-hcd's scan_isoc() routine by eliminating some local variables, declaring boolean-valued values as bool rather than unsigned, changing variable names to make more sense, and so on. The logic at the end of the routine is cut down significantly. The scanning doesn't have to catch up all the way to where the hardware is; it merely has to catch up to where the hardware was when the last interrupt occurred. If the hardware has made more progress since then and issued another interrupt, a rescan will catch up to it. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ehci-hcd.c3
-rw-r--r--drivers/usb/host/ehci-sched.c114
-rw-r--r--drivers/usb/host/ehci.h6
3 files changed, 32 insertions, 91 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 9f26080889f5..340c9c4894bf 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -488,9 +488,6 @@ static int ehci_init(struct usb_hcd *hcd)
488 else // N microframes cached 488 else // N microframes cached
489 ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); 489 ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
490 490
491 ehci->next_uframe = -1;
492 ehci->clock_frame = -1;
493
494 /* 491 /*
495 * dedicate a qh for the async ring head, since we couldn't unlink 492 * dedicate a qh for the async ring head, since we couldn't unlink
496 * a 'real' qh without stopping the async schedule [4.8]. use it 493 * a 'real' qh without stopping the async schedule [4.8]. use it
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 26ce8fef0e5b..7cf3da7babf0 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -497,8 +497,6 @@ static void disable_periodic(struct ehci_hcd *ehci)
497 if (--ehci->periodic_count) 497 if (--ehci->periodic_count)
498 return; 498 return;
499 499
500 ehci->next_uframe = -1; /* the periodic schedule is empty */
501
502 /* Don't turn off the schedule until PSS is 1 */ 500 /* Don't turn off the schedule until PSS is 1 */
503 ehci_poll_PSS(ehci); 501 ehci_poll_PSS(ehci);
504} 502}
@@ -1220,7 +1218,7 @@ itd_urb_transaction (
1220 if (likely(!list_empty(&stream->free_list))) { 1218 if (likely(!list_empty(&stream->free_list))) {
1221 itd = list_first_entry(&stream->free_list, 1219 itd = list_first_entry(&stream->free_list,
1222 struct ehci_itd, itd_list); 1220 struct ehci_itd, itd_list);
1223 if (itd->frame == ehci->clock_frame) 1221 if (itd->frame == ehci->now_frame)
1224 goto alloc_itd; 1222 goto alloc_itd;
1225 list_del (&itd->itd_list); 1223 list_del (&itd->itd_list);
1226 itd_dma = itd->itd_dma; 1224 itd_dma = itd->itd_dma;
@@ -1492,7 +1490,7 @@ iso_stream_schedule (
1492 1490
1493 /* Make sure scan_isoc() sees these */ 1491 /* Make sure scan_isoc() sees these */
1494 if (ehci->isoc_count == 0) 1492 if (ehci->isoc_count == 0)
1495 ehci->next_uframe = now; 1493 ehci->next_frame = now >> 3;
1496 return 0; 1494 return 0;
1497 1495
1498 fail: 1496 fail:
@@ -1666,11 +1664,8 @@ static void itd_link_urb(
1666 * (b) only this endpoint's completions submit URBs. It seems some silicon 1664 * (b) only this endpoint's completions submit URBs. It seems some silicon
1667 * corrupts things if you reuse completed descriptors very quickly... 1665 * corrupts things if you reuse completed descriptors very quickly...
1668 */ 1666 */
1669static unsigned 1667static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
1670itd_complete ( 1668{
1671 struct ehci_hcd *ehci,
1672 struct ehci_itd *itd
1673) {
1674 struct urb *urb = itd->urb; 1669 struct urb *urb = itd->urb;
1675 struct usb_iso_packet_descriptor *desc; 1670 struct usb_iso_packet_descriptor *desc;
1676 u32 t; 1671 u32 t;
@@ -1678,7 +1673,7 @@ itd_complete (
1678 int urb_index = -1; 1673 int urb_index = -1;
1679 struct ehci_iso_stream *stream = itd->stream; 1674 struct ehci_iso_stream *stream = itd->stream;
1680 struct usb_device *dev; 1675 struct usb_device *dev;
1681 unsigned retval = false; 1676 bool retval = false;
1682 1677
1683 /* for each uframe with a packet */ 1678 /* for each uframe with a packet */
1684 for (uframe = 0; uframe < 8; uframe++) { 1679 for (uframe = 0; uframe < 8; uframe++) {
@@ -1917,7 +1912,7 @@ sitd_urb_transaction (
1917 if (likely(!list_empty(&stream->free_list))) { 1912 if (likely(!list_empty(&stream->free_list))) {
1918 sitd = list_first_entry(&stream->free_list, 1913 sitd = list_first_entry(&stream->free_list,
1919 struct ehci_sitd, sitd_list); 1914 struct ehci_sitd, sitd_list);
1920 if (sitd->frame == ehci->clock_frame) 1915 if (sitd->frame == ehci->now_frame)
1921 goto alloc_sitd; 1916 goto alloc_sitd;
1922 list_del (&sitd->sitd_list); 1917 list_del (&sitd->sitd_list);
1923 sitd_dma = sitd->sitd_dma; 1918 sitd_dma = sitd->sitd_dma;
@@ -2071,18 +2066,15 @@ static void sitd_link_urb(
2071 * (b) only this endpoint's completions submit URBs. It seems some silicon 2066 * (b) only this endpoint's completions submit URBs. It seems some silicon
2072 * corrupts things if you reuse completed descriptors very quickly... 2067 * corrupts things if you reuse completed descriptors very quickly...
2073 */ 2068 */
2074static unsigned 2069static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
2075sitd_complete ( 2070{
2076 struct ehci_hcd *ehci,
2077 struct ehci_sitd *sitd
2078) {
2079 struct urb *urb = sitd->urb; 2071 struct urb *urb = sitd->urb;
2080 struct usb_iso_packet_descriptor *desc; 2072 struct usb_iso_packet_descriptor *desc;
2081 u32 t; 2073 u32 t;
2082 int urb_index = -1; 2074 int urb_index = -1;
2083 struct ehci_iso_stream *stream = sitd->stream; 2075 struct ehci_iso_stream *stream = sitd->stream;
2084 struct usb_device *dev; 2076 struct usb_device *dev;
2085 unsigned retval = false; 2077 bool retval = false;
2086 2078
2087 urb_index = sitd->index; 2079 urb_index = sitd->index;
2088 desc = &urb->iso_frame_desc [urb_index]; 2080 desc = &urb->iso_frame_desc [urb_index];
@@ -2214,34 +2206,29 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
2214 2206
2215static void scan_isoc(struct ehci_hcd *ehci) 2207static void scan_isoc(struct ehci_hcd *ehci)
2216{ 2208{
2217 unsigned now_uframe, frame, clock, clock_frame, mod; 2209 unsigned uf, now_frame, frame;
2218 unsigned modified; 2210 unsigned fmask = ehci->periodic_size - 1;
2219 2211 bool modified, live;
2220 mod = ehci->periodic_size << 3;
2221 2212
2222 /* 2213 /*
2223 * When running, scan from last scan point up to "now" 2214 * When running, scan from last scan point up to "now"
2224 * else clean up by scanning everything that's left. 2215 * else clean up by scanning everything that's left.
2225 * Touches as few pages as possible: cache-friendly. 2216 * Touches as few pages as possible: cache-friendly.
2226 */ 2217 */
2227 now_uframe = ehci->next_uframe;
2228 if (ehci->rh_state >= EHCI_RH_RUNNING) { 2218 if (ehci->rh_state >= EHCI_RH_RUNNING) {
2229 clock = ehci_read_frame_index(ehci); 2219 uf = ehci_read_frame_index(ehci);
2230 clock_frame = (clock >> 3) & (ehci->periodic_size - 1); 2220 now_frame = (uf >> 3) & fmask;
2221 live = true;
2231 } else { 2222 } else {
2232 clock = now_uframe + mod - 1; 2223 now_frame = (ehci->next_frame - 1) & fmask;
2233 clock_frame = -1; 2224 live = false;
2234 } 2225 }
2235 ehci->clock_frame = clock_frame; 2226 ehci->now_frame = now_frame;
2236 clock &= mod - 1;
2237 clock_frame = clock >> 3;
2238 2227
2228 frame = ehci->next_frame;
2239 for (;;) { 2229 for (;;) {
2240 union ehci_shadow q, *q_p; 2230 union ehci_shadow q, *q_p;
2241 __hc32 type, *hw_p; 2231 __hc32 type, *hw_p;
2242 unsigned incomplete = false;
2243
2244 frame = now_uframe >> 3;
2245 2232
2246restart: 2233restart:
2247 /* scan each element in frame's queue for completions */ 2234 /* scan each element in frame's queue for completions */
@@ -2249,13 +2236,9 @@ restart:
2249 hw_p = &ehci->periodic [frame]; 2236 hw_p = &ehci->periodic [frame];
2250 q.ptr = q_p->ptr; 2237 q.ptr = q_p->ptr;
2251 type = Q_NEXT_TYPE(ehci, *hw_p); 2238 type = Q_NEXT_TYPE(ehci, *hw_p);
2252 modified = 0; 2239 modified = false;
2253 2240
2254 while (q.ptr != NULL) { 2241 while (q.ptr != NULL) {
2255 unsigned uf;
2256 int live;
2257
2258 live = (ehci->rh_state >= EHCI_RH_RUNNING);
2259 switch (hc32_to_cpu(ehci, type)) { 2242 switch (hc32_to_cpu(ehci, type)) {
2260 case Q_TYPE_ITD: 2243 case Q_TYPE_ITD:
2261 /* If this ITD is still active, leave it for 2244 /* If this ITD is still active, leave it for
@@ -2263,7 +2246,7 @@ restart:
2263 * No need to check for activity unless the 2246 * No need to check for activity unless the
2264 * frame is current. 2247 * frame is current.
2265 */ 2248 */
2266 if (frame == clock_frame && live) { 2249 if (frame == now_frame && live) {
2267 rmb(); 2250 rmb();
2268 for (uf = 0; uf < 8; uf++) { 2251 for (uf = 0; uf < 8; uf++) {
2269 if (q.itd->hw_transaction[uf] & 2252 if (q.itd->hw_transaction[uf] &
@@ -2271,7 +2254,6 @@ restart:
2271 break; 2254 break;
2272 } 2255 }
2273 if (uf < 8) { 2256 if (uf < 8) {
2274 incomplete = true;
2275 q_p = &q.itd->itd_next; 2257 q_p = &q.itd->itd_next;
2276 hw_p = &q.itd->hw_next; 2258 hw_p = &q.itd->hw_next;
2277 type = Q_NEXT_TYPE(ehci, 2259 type = Q_NEXT_TYPE(ehci,
@@ -2303,14 +2285,12 @@ restart:
2303 * No need to check for activity unless the 2285 * No need to check for activity unless the
2304 * frame is current. 2286 * frame is current.
2305 */ 2287 */
2306 if (((frame == clock_frame) || 2288 if (((frame == now_frame) ||
2307 (((frame + 1) & (ehci->periodic_size - 1)) 2289 (((frame + 1) & fmask) == now_frame))
2308 == clock_frame))
2309 && live 2290 && live
2310 && (q.sitd->hw_results & 2291 && (q.sitd->hw_results &
2311 SITD_ACTIVE(ehci))) { 2292 SITD_ACTIVE(ehci))) {
2312 2293
2313 incomplete = true;
2314 q_p = &q.sitd->sitd_next; 2294 q_p = &q.sitd->sitd_next;
2315 hw_p = &q.sitd->hw_next; 2295 hw_p = &q.sitd->hw_next;
2316 type = Q_NEXT_TYPE(ehci, 2296 type = Q_NEXT_TYPE(ehci,
@@ -2347,50 +2327,14 @@ restart:
2347 } 2327 }
2348 2328
2349 /* assume completion callbacks modify the queue */ 2329 /* assume completion callbacks modify the queue */
2350 if (unlikely (modified)) { 2330 if (unlikely(modified && ehci->isoc_count > 0))
2351 if (likely(ehci->isoc_count > 0)) 2331 goto restart;
2352 goto restart;
2353 /* short-circuit this scan */
2354 now_uframe = clock;
2355 break;
2356 }
2357 } 2332 }
2358 2333
2359 /* If we can tell we caught up to the hardware, stop now. 2334 /* Stop when we have reached the current frame */
2360 * We can't advance our scan without collecting the ISO 2335 if (frame == now_frame)
2361 * transfers that are still pending in this frame.
2362 */
2363 if (incomplete && ehci->rh_state >= EHCI_RH_RUNNING) {
2364 ehci->next_uframe = now_uframe;
2365 break; 2336 break;
2366 } 2337 frame = (frame + 1) & fmask;
2367
2368 // FIXME: this assumes we won't get lapped when
2369 // latencies climb; that should be rare, but...
2370 // detect it, and just go all the way around.
2371 // FLR might help detect this case, so long as latencies
2372 // don't exceed periodic_size msec (default 1.024 sec).
2373
2374 // FIXME: likewise assumes HC doesn't halt mid-scan
2375
2376 if (now_uframe == clock) {
2377 unsigned now;
2378
2379 if (ehci->rh_state < EHCI_RH_RUNNING
2380 || ehci->isoc_count == 0)
2381 break;
2382 ehci->next_uframe = now_uframe;
2383 now = ehci_read_frame_index(ehci) & (mod - 1);
2384 if (now_uframe == now)
2385 break;
2386
2387 /* rescan the rest of this frame, then ... */
2388 clock = now;
2389 clock_frame = clock >> 3;
2390 ehci->clock_frame = clock_frame;
2391 } else {
2392 now_uframe++;
2393 now_uframe &= mod - 1;
2394 }
2395 } 2338 }
2339 ehci->next_frame = now_frame;
2396} 2340}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 254f414bd0bd..7de58fe52d51 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -141,19 +141,19 @@ struct ehci_hcd { /* one per controller */
141 struct ehci_qh *intr_unlink; 141 struct ehci_qh *intr_unlink;
142 struct ehci_qh *intr_unlink_last; 142 struct ehci_qh *intr_unlink_last;
143 unsigned intr_unlink_cycle; 143 unsigned intr_unlink_cycle;
144 int next_uframe; /* scan periodic, start here */ 144 unsigned now_frame; /* frame from HC hardware */
145 unsigned next_frame; /* scan periodic, start here */
145 unsigned intr_count; /* intr activity count */ 146 unsigned intr_count; /* intr activity count */
146 unsigned isoc_count; /* isoc activity count */ 147 unsigned isoc_count; /* isoc activity count */
147 unsigned periodic_count; /* periodic activity count */ 148 unsigned periodic_count; /* periodic activity count */
148 unsigned uframe_periodic_max; /* max periodic time per uframe */ 149 unsigned uframe_periodic_max; /* max periodic time per uframe */
149 150
150 151
151 /* list of itds & sitds completed while clock_frame was still active */ 152 /* list of itds & sitds completed while now_frame was still active */
152 struct list_head cached_itd_list; 153 struct list_head cached_itd_list;
153 struct ehci_itd *last_itd_to_free; 154 struct ehci_itd *last_itd_to_free;
154 struct list_head cached_sitd_list; 155 struct list_head cached_sitd_list;
155 struct ehci_sitd *last_sitd_to_free; 156 struct ehci_sitd *last_sitd_to_free;
156 unsigned clock_frame;
157 157
158 /* per root hub port */ 158 /* per root hub port */
159 unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; 159 unsigned long reset_done [EHCI_MAX_ROOT_PORTS];