diff options
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 2abf8543f083..56a32033adb3 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -36,6 +36,27 @@ | |||
36 | 36 | ||
37 | static int ehci_get_frame (struct usb_hcd *hcd); | 37 | static int ehci_get_frame (struct usb_hcd *hcd); |
38 | 38 | ||
39 | #ifdef CONFIG_PCI | ||
40 | |||
41 | static 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 | |||
39 | /*-------------------------------------------------------------------------*/ | 60 | /*-------------------------------------------------------------------------*/ |
40 | 61 | ||
41 | /* | 62 | /* |
@@ -479,10 +500,9 @@ static int enable_periodic (struct ehci_hcd *ehci) | |||
479 | cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; | 500 | cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; |
480 | ehci_writel(ehci, cmd, &ehci->regs->command); | 501 | ehci_writel(ehci, cmd, &ehci->regs->command); |
481 | /* posted write ... PSS happens later */ | 502 | /* posted write ... PSS happens later */ |
482 | ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; | ||
483 | 503 | ||
484 | /* make sure ehci_work scans these */ | 504 | /* make sure ehci_work scans these */ |
485 | ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) | 505 | ehci->next_uframe = ehci_read_frame_index(ehci) |
486 | % (ehci->periodic_size << 3); | 506 | % (ehci->periodic_size << 3); |
487 | if (unlikely(ehci->broken_periodic)) | 507 | if (unlikely(ehci->broken_periodic)) |
488 | ehci->last_periodic_enable = ktime_get_real(); | 508 | ehci->last_periodic_enable = ktime_get_real(); |
@@ -677,7 +697,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
677 | 697 | ||
678 | /* reschedule QH iff another request is queued */ | 698 | /* reschedule QH iff another request is queued */ |
679 | if (!list_empty(&qh->qtd_list) && | 699 | if (!list_empty(&qh->qtd_list) && |
680 | HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | 700 | ehci->rh_state == EHCI_RH_RUNNING) { |
681 | rc = qh_schedule(ehci, qh); | 701 | rc = qh_schedule(ehci, qh); |
682 | 702 | ||
683 | /* An error here likely indicates handshake failure | 703 | /* An error here likely indicates handshake failure |
@@ -1409,7 +1429,7 @@ iso_stream_schedule ( | |||
1409 | goto fail; | 1429 | goto fail; |
1410 | } | 1430 | } |
1411 | 1431 | ||
1412 | now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1); | 1432 | now = ehci_read_frame_index(ehci) & (mod - 1); |
1413 | 1433 | ||
1414 | /* Typical case: reuse current schedule, stream is still active. | 1434 | /* Typical case: reuse current schedule, stream is still active. |
1415 | * Hopefully there are no gaps from the host falling behind | 1435 | * Hopefully there are no gaps from the host falling behind |
@@ -1459,10 +1479,15 @@ iso_stream_schedule ( | |||
1459 | 1479 | ||
1460 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | 1480 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ |
1461 | 1481 | ||
1462 | /* find a uframe slot with enough bandwidth */ | 1482 | /* find a uframe slot with enough bandwidth. |
1463 | next = start + period; | 1483 | * Early uframes are more precious because full-speed |
1464 | for (; start < next; start++) { | 1484 | * iso IN transfers can't use late uframes, |
1465 | 1485 | * and therefore they should be allocated last. | |
1486 | */ | ||
1487 | next = start; | ||
1488 | start += period; | ||
1489 | do { | ||
1490 | start--; | ||
1466 | /* check schedule: enough space? */ | 1491 | /* check schedule: enough space? */ |
1467 | if (stream->highspeed) { | 1492 | if (stream->highspeed) { |
1468 | if (itd_slot_ok(ehci, mod, start, | 1493 | if (itd_slot_ok(ehci, mod, start, |
@@ -1475,7 +1500,7 @@ iso_stream_schedule ( | |||
1475 | start, sched, period)) | 1500 | start, sched, period)) |
1476 | break; | 1501 | break; |
1477 | } | 1502 | } |
1478 | } | 1503 | } while (start > next); |
1479 | 1504 | ||
1480 | /* no room in the schedule */ | 1505 | /* no room in the schedule */ |
1481 | if (start == next) { | 1506 | if (start == next) { |
@@ -2275,8 +2300,8 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2275 | * Touches as few pages as possible: cache-friendly. | 2300 | * Touches as few pages as possible: cache-friendly. |
2276 | */ | 2301 | */ |
2277 | now_uframe = ehci->next_uframe; | 2302 | now_uframe = ehci->next_uframe; |
2278 | if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | 2303 | if (ehci->rh_state == EHCI_RH_RUNNING) { |
2279 | clock = ehci_readl(ehci, &ehci->regs->frame_index); | 2304 | clock = ehci_read_frame_index(ehci); |
2280 | clock_frame = (clock >> 3) & (ehci->periodic_size - 1); | 2305 | clock_frame = (clock >> 3) & (ehci->periodic_size - 1); |
2281 | } else { | 2306 | } else { |
2282 | clock = now_uframe + mod - 1; | 2307 | clock = now_uframe + mod - 1; |
@@ -2310,7 +2335,7 @@ restart: | |||
2310 | union ehci_shadow temp; | 2335 | union ehci_shadow temp; |
2311 | int live; | 2336 | int live; |
2312 | 2337 | ||
2313 | live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state); | 2338 | live = (ehci->rh_state == EHCI_RH_RUNNING); |
2314 | switch (hc32_to_cpu(ehci, type)) { | 2339 | switch (hc32_to_cpu(ehci, type)) { |
2315 | case Q_TYPE_QH: | 2340 | case Q_TYPE_QH: |
2316 | /* handle any completions */ | 2341 | /* handle any completions */ |
@@ -2435,7 +2460,7 @@ restart: | |||
2435 | * We can't advance our scan without collecting the ISO | 2460 | * We can't advance our scan without collecting the ISO |
2436 | * transfers that are still pending in this frame. | 2461 | * transfers that are still pending in this frame. |
2437 | */ | 2462 | */ |
2438 | if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | 2463 | if (incomplete && ehci->rh_state == EHCI_RH_RUNNING) { |
2439 | ehci->next_uframe = now_uframe; | 2464 | ehci->next_uframe = now_uframe; |
2440 | break; | 2465 | break; |
2441 | } | 2466 | } |
@@ -2451,12 +2476,11 @@ restart: | |||
2451 | if (now_uframe == clock) { | 2476 | if (now_uframe == clock) { |
2452 | unsigned now; | 2477 | unsigned now; |
2453 | 2478 | ||
2454 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) | 2479 | if (ehci->rh_state != EHCI_RH_RUNNING |
2455 | || ehci->periodic_sched == 0) | 2480 | || ehci->periodic_sched == 0) |
2456 | break; | 2481 | break; |
2457 | ehci->next_uframe = now_uframe; | 2482 | ehci->next_uframe = now_uframe; |
2458 | now = ehci_readl(ehci, &ehci->regs->frame_index) & | 2483 | now = ehci_read_frame_index(ehci) & (mod - 1); |
2459 | (mod - 1); | ||
2460 | if (now_uframe == now) | 2484 | if (now_uframe == now) |
2461 | break; | 2485 | break; |
2462 | 2486 | ||