diff options
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 114 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 6 |
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 | */ |
1669 | static unsigned | 1667 | static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) |
1670 | itd_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 | */ |
2074 | static unsigned | 2069 | static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) |
2075 | sitd_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 | ||
2215 | static void scan_isoc(struct ehci_hcd *ehci) | 2207 | static 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 | ||
2246 | restart: | 2233 | restart: |
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]; |