diff options
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 216 |
1 files changed, 215 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 5871944e614..4859900bd13 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -163,6 +163,190 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2) | |||
163 | return 1; | 163 | return 1; |
164 | } | 164 | } |
165 | 165 | ||
166 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | ||
167 | |||
168 | /* Which uframe does the low/fullspeed transfer start in? | ||
169 | * | ||
170 | * The parameter is the mask of ssplits in "H-frame" terms | ||
171 | * and this returns the transfer start uframe in "B-frame" terms, | ||
172 | * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 | ||
173 | * will cause a transfer in "B-frame" uframe 0. "B-frames" lag | ||
174 | * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. | ||
175 | */ | ||
176 | static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask) | ||
177 | { | ||
178 | unsigned char smask = QH_SMASK & le32_to_cpu(mask); | ||
179 | if (!smask) { | ||
180 | ehci_err(ehci, "invalid empty smask!\n"); | ||
181 | /* uframe 7 can't have bw so this will indicate failure */ | ||
182 | return 7; | ||
183 | } | ||
184 | return ffs(smask) - 1; | ||
185 | } | ||
186 | |||
187 | static const unsigned char | ||
188 | max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; | ||
189 | |||
190 | /* carryover low/fullspeed bandwidth that crosses uframe boundries */ | ||
191 | static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) | ||
192 | { | ||
193 | int i; | ||
194 | for (i=0; i<7; i++) { | ||
195 | if (max_tt_usecs[i] < tt_usecs[i]) { | ||
196 | tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; | ||
197 | tt_usecs[i] = max_tt_usecs[i]; | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* How many of the tt's periodic downstream 1000 usecs are allocated? | ||
203 | * | ||
204 | * While this measures the bandwidth in terms of usecs/uframe, | ||
205 | * the low/fullspeed bus has no notion of uframes, so any particular | ||
206 | * low/fullspeed transfer can "carry over" from one uframe to the next, | ||
207 | * since the TT just performs downstream transfers in sequence. | ||
208 | * | ||
209 | * For example two seperate 100 usec transfers can start in the same uframe, | ||
210 | * and the second one would "carry over" 75 usecs into the next uframe. | ||
211 | */ | ||
212 | static void | ||
213 | periodic_tt_usecs ( | ||
214 | struct ehci_hcd *ehci, | ||
215 | struct usb_device *dev, | ||
216 | unsigned frame, | ||
217 | unsigned short tt_usecs[8] | ||
218 | ) | ||
219 | { | ||
220 | __le32 *hw_p = &ehci->periodic [frame]; | ||
221 | union ehci_shadow *q = &ehci->pshadow [frame]; | ||
222 | unsigned char uf; | ||
223 | |||
224 | memset(tt_usecs, 0, 16); | ||
225 | |||
226 | while (q->ptr) { | ||
227 | switch (Q_NEXT_TYPE(*hw_p)) { | ||
228 | case Q_TYPE_ITD: | ||
229 | hw_p = &q->itd->hw_next; | ||
230 | q = &q->itd->itd_next; | ||
231 | continue; | ||
232 | case Q_TYPE_QH: | ||
233 | if (same_tt(dev, q->qh->dev)) { | ||
234 | uf = tt_start_uframe(ehci, q->qh->hw_info2); | ||
235 | tt_usecs[uf] += q->qh->tt_usecs; | ||
236 | } | ||
237 | hw_p = &q->qh->hw_next; | ||
238 | q = &q->qh->qh_next; | ||
239 | continue; | ||
240 | case Q_TYPE_SITD: | ||
241 | if (same_tt(dev, q->sitd->urb->dev)) { | ||
242 | uf = tt_start_uframe(ehci, q->sitd->hw_uframe); | ||
243 | tt_usecs[uf] += q->sitd->stream->tt_usecs; | ||
244 | } | ||
245 | hw_p = &q->sitd->hw_next; | ||
246 | q = &q->sitd->sitd_next; | ||
247 | continue; | ||
248 | // case Q_TYPE_FSTN: | ||
249 | default: | ||
250 | ehci_dbg(ehci, | ||
251 | "ignoring periodic frame %d FSTN\n", frame); | ||
252 | hw_p = &q->fstn->hw_next; | ||
253 | q = &q->fstn->fstn_next; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | carryover_tt_bandwidth(tt_usecs); | ||
258 | |||
259 | if (max_tt_usecs[7] < tt_usecs[7]) | ||
260 | ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", | ||
261 | frame, tt_usecs[7] - max_tt_usecs[7]); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Return true if the device's tt's downstream bus is available for a | ||
266 | * periodic transfer of the specified length (usecs), starting at the | ||
267 | * specified frame/uframe. Note that (as summarized in section 11.19 | ||
268 | * of the usb 2.0 spec) TTs can buffer multiple transactions for each | ||
269 | * uframe. | ||
270 | * | ||
271 | * The uframe parameter is when the fullspeed/lowspeed transfer | ||
272 | * should be executed in "B-frame" terms, which is the same as the | ||
273 | * highspeed ssplit's uframe (which is in "H-frame" terms). For example | ||
274 | * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. | ||
275 | * See the EHCI spec sec 4.5 and fig 4.7. | ||
276 | * | ||
277 | * This checks if the full/lowspeed bus, at the specified starting uframe, | ||
278 | * has the specified bandwidth available, according to rules listed | ||
279 | * in USB 2.0 spec section 11.18.1 fig 11-60. | ||
280 | * | ||
281 | * This does not check if the transfer would exceed the max ssplit | ||
282 | * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, | ||
283 | * since proper scheduling limits ssplits to less than 16 per uframe. | ||
284 | */ | ||
285 | static int tt_available ( | ||
286 | struct ehci_hcd *ehci, | ||
287 | unsigned period, | ||
288 | struct usb_device *dev, | ||
289 | unsigned frame, | ||
290 | unsigned uframe, | ||
291 | u16 usecs | ||
292 | ) | ||
293 | { | ||
294 | if ((period == 0) || (uframe >= 7)) /* error */ | ||
295 | return 0; | ||
296 | |||
297 | for (; frame < ehci->periodic_size; frame += period) { | ||
298 | unsigned short tt_usecs[8]; | ||
299 | |||
300 | periodic_tt_usecs (ehci, dev, frame, tt_usecs); | ||
301 | |||
302 | ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in" | ||
303 | " schedule %d/%d/%d/%d/%d/%d/%d/%d\n", | ||
304 | frame, usecs, uframe, | ||
305 | tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3], | ||
306 | tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]); | ||
307 | |||
308 | if (max_tt_usecs[uframe] <= tt_usecs[uframe]) { | ||
309 | ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n", | ||
310 | frame, uframe); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | /* special case for isoc transfers larger than 125us: | ||
315 | * the first and each subsequent fully used uframe | ||
316 | * must be empty, so as to not illegally delay | ||
317 | * already scheduled transactions | ||
318 | */ | ||
319 | if (125 < usecs) { | ||
320 | int ufs = (usecs / 125) - 1; | ||
321 | int i; | ||
322 | for (i = uframe; i < (uframe + ufs) && i < 8; i++) | ||
323 | if (0 < tt_usecs[i]) { | ||
324 | ehci_vdbg(ehci, | ||
325 | "multi-uframe xfer can't fit " | ||
326 | "in frame %d uframe %d\n", | ||
327 | frame, i); | ||
328 | return 0; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | tt_usecs[uframe] += usecs; | ||
333 | |||
334 | carryover_tt_bandwidth(tt_usecs); | ||
335 | |||
336 | /* fail if the carryover pushed bw past the last uframe's limit */ | ||
337 | if (max_tt_usecs[7] < tt_usecs[7]) { | ||
338 | ehci_vdbg(ehci, | ||
339 | "tt unavailable usecs %d frame %d uframe %d\n", | ||
340 | usecs, frame, uframe); | ||
341 | return 0; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | return 1; | ||
346 | } | ||
347 | |||
348 | #else | ||
349 | |||
166 | /* return true iff the device's transaction translator is available | 350 | /* return true iff the device's transaction translator is available |
167 | * for a periodic transfer starting at the specified frame, using | 351 | * for a periodic transfer starting at the specified frame, using |
168 | * all the uframes in the mask. | 352 | * all the uframes in the mask. |
@@ -237,6 +421,8 @@ static int tt_no_collision ( | |||
237 | return 1; | 421 | return 1; |
238 | } | 422 | } |
239 | 423 | ||
424 | #endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ | ||
425 | |||
240 | /*-------------------------------------------------------------------------*/ | 426 | /*-------------------------------------------------------------------------*/ |
241 | 427 | ||
242 | static int enable_periodic (struct ehci_hcd *ehci) | 428 | static int enable_periodic (struct ehci_hcd *ehci) |
@@ -481,7 +667,7 @@ static int check_intr_schedule ( | |||
481 | ) | 667 | ) |
482 | { | 668 | { |
483 | int retval = -ENOSPC; | 669 | int retval = -ENOSPC; |
484 | u8 mask; | 670 | u8 mask = 0; |
485 | 671 | ||
486 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ | 672 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ |
487 | goto done; | 673 | goto done; |
@@ -494,6 +680,24 @@ static int check_intr_schedule ( | |||
494 | goto done; | 680 | goto done; |
495 | } | 681 | } |
496 | 682 | ||
683 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | ||
684 | if (tt_available (ehci, qh->period, qh->dev, frame, uframe, | ||
685 | qh->tt_usecs)) { | ||
686 | unsigned i; | ||
687 | |||
688 | /* TODO : this may need FSTN for SSPLIT in uframe 5. */ | ||
689 | for (i=uframe+1; i<8 && i<uframe+4; i++) | ||
690 | if (!check_period (ehci, frame, i, | ||
691 | qh->period, qh->c_usecs)) | ||
692 | goto done; | ||
693 | else | ||
694 | mask |= 1 << i; | ||
695 | |||
696 | retval = 0; | ||
697 | |||
698 | *c_maskp = cpu_to_le32 (mask << 8); | ||
699 | } | ||
700 | #else | ||
497 | /* Make sure this tt's buffer is also available for CSPLITs. | 701 | /* Make sure this tt's buffer is also available for CSPLITs. |
498 | * We pessimize a bit; probably the typical full speed case | 702 | * We pessimize a bit; probably the typical full speed case |
499 | * doesn't need the second CSPLIT. | 703 | * doesn't need the second CSPLIT. |
@@ -514,6 +718,7 @@ static int check_intr_schedule ( | |||
514 | goto done; | 718 | goto done; |
515 | retval = 0; | 719 | retval = 0; |
516 | } | 720 | } |
721 | #endif | ||
517 | done: | 722 | done: |
518 | return retval; | 723 | return retval; |
519 | } | 724 | } |
@@ -1047,12 +1252,21 @@ sitd_slot_ok ( | |||
1047 | frame = uframe >> 3; | 1252 | frame = uframe >> 3; |
1048 | uf = uframe & 7; | 1253 | uf = uframe & 7; |
1049 | 1254 | ||
1255 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | ||
1256 | /* The tt's fullspeed bus bandwidth must be available. | ||
1257 | * tt_available scheduling guarantees 10+% for control/bulk. | ||
1258 | */ | ||
1259 | if (!tt_available (ehci, period_uframes << 3, | ||
1260 | stream->udev, frame, uf, stream->tt_usecs)) | ||
1261 | return 0; | ||
1262 | #else | ||
1050 | /* tt must be idle for start(s), any gap, and csplit. | 1263 | /* tt must be idle for start(s), any gap, and csplit. |
1051 | * assume scheduling slop leaves 10+% for control/bulk. | 1264 | * assume scheduling slop leaves 10+% for control/bulk. |
1052 | */ | 1265 | */ |
1053 | if (!tt_no_collision (ehci, period_uframes << 3, | 1266 | if (!tt_no_collision (ehci, period_uframes << 3, |
1054 | stream->udev, frame, mask)) | 1267 | stream->udev, frame, mask)) |
1055 | return 0; | 1268 | return 0; |
1269 | #endif | ||
1056 | 1270 | ||
1057 | /* check starts (OUT uses more than one) */ | 1271 | /* check starts (OUT uses more than one) */ |
1058 | max_used = 100 - stream->usecs; | 1272 | max_used = 100 - stream->usecs; |