aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
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...