aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c136
1 files changed, 61 insertions, 75 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 7cf3da7babf0..69ebee73c0c1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -36,29 +36,6 @@
36 36
37static int ehci_get_frame (struct usb_hcd *hcd); 37static int ehci_get_frame (struct usb_hcd *hcd);
38 38
39#ifdef CONFIG_PCI
40
41static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
42{
43 unsigned uf;
44
45 /*
46 * The MosChip MCS9990 controller updates its microframe counter
47 * a little before the frame counter, and occasionally we will read
48 * the invalid intermediate value. Avoid problems by checking the
49 * microframe number (the low-order 3 bits); if they are 0 then
50 * re-read the register to get the correct value.
51 */
52 uf = ehci_readl(ehci, &ehci->regs->frame_index);
53 if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
54 uf = ehci_readl(ehci, &ehci->regs->frame_index);
55 return uf;
56}
57
58#endif
59
60/*-------------------------------------------------------------------------*/
61
62/* 39/*
63 * periodic_next_shadow - return "next" pointer on shadow list 40 * periodic_next_shadow - return "next" pointer on shadow list
64 * @periodic: host pointer to qh/itd/sitd 41 * @periodic: host pointer to qh/itd/sitd
@@ -1361,7 +1338,7 @@ sitd_slot_ok (
1361 * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! 1338 * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler!
1362 */ 1339 */
1363 1340
1364#define SCHEDULE_SLOP 80 /* microframes */ 1341#define SCHEDULING_DELAY 40 /* microframes */
1365 1342
1366static int 1343static int
1367iso_stream_schedule ( 1344iso_stream_schedule (
@@ -1370,7 +1347,7 @@ iso_stream_schedule (
1370 struct ehci_iso_stream *stream 1347 struct ehci_iso_stream *stream
1371) 1348)
1372{ 1349{
1373 u32 now, next, start, period, span; 1350 u32 now, base, next, start, period, span;
1374 int status; 1351 int status;
1375 unsigned mod = ehci->periodic_size << 3; 1352 unsigned mod = ehci->periodic_size << 3;
1376 struct ehci_iso_sched *sched = urb->hcpriv; 1353 struct ehci_iso_sched *sched = urb->hcpriv;
@@ -1382,62 +1359,72 @@ iso_stream_schedule (
1382 span <<= 3; 1359 span <<= 3;
1383 } 1360 }
1384 1361
1385 if (span > mod - SCHEDULE_SLOP) {
1386 ehci_dbg (ehci, "iso request %p too long\n", urb);
1387 status = -EFBIG;
1388 goto fail;
1389 }
1390
1391 now = ehci_read_frame_index(ehci) & (mod - 1); 1362 now = ehci_read_frame_index(ehci) & (mod - 1);
1392 1363
1393 /* Typical case: reuse current schedule, stream is still active. 1364 /* Typical case: reuse current schedule, stream is still active.
1394 * Hopefully there are no gaps from the host falling behind 1365 * Hopefully there are no gaps from the host falling behind
1395 * (irq delays etc), but if there are we'll take the next 1366 * (irq delays etc). If there are, the behavior depends on
1396 * slot in the schedule, implicitly assuming URB_ISO_ASAP. 1367 * whether URB_ISO_ASAP is set.
1397 */ 1368 */
1398 if (likely (!list_empty (&stream->td_list))) { 1369 if (likely (!list_empty (&stream->td_list))) {
1399 u32 excess;
1400 1370
1401 /* For high speed devices, allow scheduling within the 1371 /* Take the isochronous scheduling threshold into account */
1402 * isochronous scheduling threshold. For full speed devices 1372 if (ehci->i_thresh)
1403 * and Intel PCI-based controllers, don't (work around for 1373 next = now + ehci->i_thresh; /* uframe cache */
1404 * Intel ICH9 bug).
1405 */
1406 if (!stream->highspeed && ehci->fs_i_thresh)
1407 next = now + ehci->i_thresh;
1408 else 1374 else
1409 next = now; 1375 next = (now + 2 + 7) & ~0x07; /* full frame cache */
1410 1376
1411 /* Fell behind (by up to twice the slop amount)? 1377 /*
1412 * We decide based on the time of the last currently-scheduled 1378 * Use ehci->last_iso_frame as the base. There can't be any
1413 * slot, not the time of the next available slot. 1379 * TDs scheduled for earlier than that.
1414 */ 1380 */
1415 excess = (stream->next_uframe - period - next) & (mod - 1); 1381 base = ehci->last_iso_frame << 3;
1416 if (excess >= mod - 2 * SCHEDULE_SLOP) 1382 next = (next - base) & (mod - 1);
1417 start = next + excess - mod + period * 1383 start = (stream->next_uframe - base) & (mod - 1);
1418 DIV_ROUND_UP(mod - excess, period); 1384
1419 else 1385 /* Is the schedule already full? */
1420 start = next + excess + period; 1386 if (unlikely(start < period)) {
1421 if (start - now >= mod) { 1387 ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
1422 ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", 1388 urb, stream->next_uframe, base,
1423 urb, start - now - period, period, 1389 period, mod);
1424 mod); 1390 status = -ENOSPC;
1425 status = -EFBIG;
1426 goto fail; 1391 goto fail;
1427 } 1392 }
1393
1394 /* Behind the scheduling threshold? */
1395 if (unlikely(start < next)) {
1396
1397 /* USB_ISO_ASAP: Round up to the first available slot */
1398 if (urb->transfer_flags & URB_ISO_ASAP)
1399 start += (next - start + period - 1) & -period;
1400
1401 /*
1402 * Not ASAP: Use the next slot in the stream. If
1403 * the entire URB falls before the threshold, fail.
1404 */
1405 else if (start + span - period < next) {
1406 ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
1407 urb, start + base,
1408 span - period, next + base);
1409 status = -EXDEV;
1410 goto fail;
1411 }
1412 }
1413
1414 start += base;
1428 } 1415 }
1429 1416
1430 /* need to schedule; when's the next (u)frame we could start? 1417 /* need to schedule; when's the next (u)frame we could start?
1431 * this is bigger than ehci->i_thresh allows; scheduling itself 1418 * this is bigger than ehci->i_thresh allows; scheduling itself
1432 * isn't free, the slop should handle reasonably slow cpus. it 1419 * isn't free, the delay should handle reasonably slow cpus. it
1433 * can also help high bandwidth if the dma and irq loads don't 1420 * can also help high bandwidth if the dma and irq loads don't
1434 * jump until after the queue is primed. 1421 * jump until after the queue is primed.
1435 */ 1422 */
1436 else { 1423 else {
1437 int done = 0; 1424 int done = 0;
1438 start = SCHEDULE_SLOP + (now & ~0x07);
1439 1425
1440 /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ 1426 base = now & ~0x07;
1427 start = base + SCHEDULING_DELAY;
1441 1428
1442 /* find a uframe slot with enough bandwidth. 1429 /* find a uframe slot with enough bandwidth.
1443 * Early uframes are more precious because full-speed 1430 * Early uframes are more precious because full-speed
@@ -1464,19 +1451,16 @@ iso_stream_schedule (
1464 1451
1465 /* no room in the schedule */ 1452 /* no room in the schedule */
1466 if (!done) { 1453 if (!done) {
1467 ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", 1454 ehci_dbg(ehci, "iso sched full %p", urb);
1468 urb, now, now + mod);
1469 status = -ENOSPC; 1455 status = -ENOSPC;
1470 goto fail; 1456 goto fail;
1471 } 1457 }
1472 } 1458 }
1473 1459
1474 /* Tried to schedule too far into the future? */ 1460 /* Tried to schedule too far into the future? */
1475 if (unlikely(start - now + span - period 1461 if (unlikely(start - base + span - period >= mod)) {
1476 >= mod - 2 * SCHEDULE_SLOP)) { 1462 ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
1477 ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", 1463 urb, start - base, span - period, mod);
1478 urb, start - now, span - period,
1479 mod - 2 * SCHEDULE_SLOP);
1480 status = -EFBIG; 1464 status = -EFBIG;
1481 goto fail; 1465 goto fail;
1482 } 1466 }
@@ -1490,7 +1474,7 @@ iso_stream_schedule (
1490 1474
1491 /* Make sure scan_isoc() sees these */ 1475 /* Make sure scan_isoc() sees these */
1492 if (ehci->isoc_count == 0) 1476 if (ehci->isoc_count == 0)
1493 ehci->next_frame = now >> 3; 1477 ehci->last_iso_frame = now >> 3;
1494 return 0; 1478 return 0;
1495 1479
1496 fail: 1480 fail:
@@ -1646,7 +1630,7 @@ static void itd_link_urb(
1646 1630
1647 /* don't need that schedule data any more */ 1631 /* don't need that schedule data any more */
1648 iso_sched_free (stream, iso_sched); 1632 iso_sched_free (stream, iso_sched);
1649 urb->hcpriv = NULL; 1633 urb->hcpriv = stream;
1650 1634
1651 ++ehci->isoc_count; 1635 ++ehci->isoc_count;
1652 enable_periodic(ehci); 1636 enable_periodic(ehci);
@@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
1708 urb->actual_length += desc->actual_length; 1692 urb->actual_length += desc->actual_length;
1709 } else { 1693 } else {
1710 /* URB was too late */ 1694 /* URB was too late */
1711 desc->status = -EXDEV; 1695 urb->error_count++;
1712 } 1696 }
1713 } 1697 }
1714 1698
@@ -2045,7 +2029,7 @@ static void sitd_link_urb(
2045 2029
2046 /* don't need that schedule data any more */ 2030 /* don't need that schedule data any more */
2047 iso_sched_free (stream, sched); 2031 iso_sched_free (stream, sched);
2048 urb->hcpriv = NULL; 2032 urb->hcpriv = stream;
2049 2033
2050 ++ehci->isoc_count; 2034 ++ehci->isoc_count;
2051 enable_periodic(ehci); 2035 enable_periodic(ehci);
@@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
2081 t = hc32_to_cpup(ehci, &sitd->hw_results); 2065 t = hc32_to_cpup(ehci, &sitd->hw_results);
2082 2066
2083 /* report transfer status */ 2067 /* report transfer status */
2084 if (t & SITD_ERRS) { 2068 if (unlikely(t & SITD_ERRS)) {
2085 urb->error_count++; 2069 urb->error_count++;
2086 if (t & SITD_STS_DBE) 2070 if (t & SITD_STS_DBE)
2087 desc->status = usb_pipein (urb->pipe) 2071 desc->status = usb_pipein (urb->pipe)
@@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
2091 desc->status = -EOVERFLOW; 2075 desc->status = -EOVERFLOW;
2092 else /* XACT, MMF, etc */ 2076 else /* XACT, MMF, etc */
2093 desc->status = -EPROTO; 2077 desc->status = -EPROTO;
2078 } else if (unlikely(t & SITD_STS_ACTIVE)) {
2079 /* URB was too late */
2080 urb->error_count++;
2094 } else { 2081 } else {
2095 desc->status = 0; 2082 desc->status = 0;
2096 desc->actual_length = desc->length - SITD_LENGTH(t); 2083 desc->actual_length = desc->length - SITD_LENGTH(t);
@@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci)
2220 now_frame = (uf >> 3) & fmask; 2207 now_frame = (uf >> 3) & fmask;
2221 live = true; 2208 live = true;
2222 } else { 2209 } else {
2223 now_frame = (ehci->next_frame - 1) & fmask; 2210 now_frame = (ehci->last_iso_frame - 1) & fmask;
2224 live = false; 2211 live = false;
2225 } 2212 }
2226 ehci->now_frame = now_frame; 2213 ehci->now_frame = now_frame;
2227 2214
2228 frame = ehci->next_frame;
2229 for (;;) { 2215 for (;;) {
2230 union ehci_shadow q, *q_p; 2216 union ehci_shadow q, *q_p;
2231 __hc32 type, *hw_p; 2217 __hc32 type, *hw_p;
2232 2218
2219 frame = ehci->last_iso_frame;
2233restart: 2220restart:
2234 /* scan each element in frame's queue for completions */ 2221 /* scan each element in frame's queue for completions */
2235 q_p = &ehci->pshadow [frame]; 2222 q_p = &ehci->pshadow [frame];
@@ -2334,7 +2321,6 @@ restart:
2334 /* Stop when we have reached the current frame */ 2321 /* Stop when we have reached the current frame */
2335 if (frame == now_frame) 2322 if (frame == now_frame)
2336 break; 2323 break;
2337 frame = (frame + 1) & fmask; 2324 ehci->last_iso_frame = (frame + 1) & fmask;
2338 } 2325 }
2339 ehci->next_frame = now_frame;
2340} 2326}