diff options
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1543c838b3d..2abf8543f08 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -172,7 +172,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) } } #ifdef DEBUG - if (usecs > 100) + if (usecs > ehci->uframe_periodic_max) ehci_err (ehci, "uframe %d sched overrun: %d usecs\n", frame * 8 + uframe, usecs); #endif @@ -471,8 +471,10 @@ static int enable_periodic (struct ehci_hcd *ehci) */ status = handshake_on_error_set_halt(ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125); - if (status) + if (status) { + usb_hc_died(ehci_to_hcd(ehci)); return status; + } cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; ehci_writel(ehci, cmd, &ehci->regs->command); @@ -510,8 +512,10 @@ static int disable_periodic (struct ehci_hcd *ehci) */ status = handshake_on_error_set_halt(ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); - if (status) + if (status) { + usb_hc_died(ehci_to_hcd(ehci)); return status; + } cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE; ehci_writel(ehci, cmd, &ehci->regs->command); @@ -705,11 +709,8 @@ static int check_period ( if (uframe >= 8) return 0; - /* - * 80% periodic == 100 usec/uframe available - * convert "usecs we need" to "max already claimed" - */ - usecs = 100 - usecs; + /* convert "usecs we need" to "max already claimed" */ + usecs = ehci->uframe_periodic_max - usecs; /* we "know" 2 and 4 uframe intervals were rejected; so * for period 0, check _every_ microframe in the schedule. @@ -1282,9 +1283,9 @@ itd_slot_ok ( { uframe %= period; do { - /* can't commit more than 80% periodic == 100 usec */ + /* can't commit more than uframe_periodic_max usec */ if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) - > (100 - usecs)) + > (ehci->uframe_periodic_max - usecs)) return 0; /* we know urb->interval is 2^N uframes */ @@ -1341,7 +1342,7 @@ sitd_slot_ok ( #endif /* check starts (OUT uses more than one) */ - max_used = 100 - stream->usecs; + max_used = ehci->uframe_periodic_max - stream->usecs; for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { if (periodic_usecs (ehci, frame, uf) > max_used) return 0; @@ -1350,7 +1351,7 @@ sitd_slot_ok ( /* for IN, check CSPLIT */ if (stream->c_usecs) { uf = uframe & 7; - max_used = 100 - stream->c_usecs; + max_used = ehci->uframe_periodic_max - stream->c_usecs; do { tmp = 1 << uf; tmp <<= 8; @@ -2287,6 +2288,7 @@ scan_periodic (struct ehci_hcd *ehci) } clock &= mod - 1; clock_frame = clock >> 3; + ++ehci->periodic_stamp; for (;;) { union ehci_shadow q, *q_p; @@ -2315,10 +2317,14 @@ restart: temp.qh = qh_get (q.qh); type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next); q = q.qh->qh_next; - modified = qh_completions (ehci, temp.qh); - if (unlikely(list_empty(&temp.qh->qtd_list) || - temp.qh->needs_rescan)) - intr_deschedule (ehci, temp.qh); + if (temp.qh->stamp != ehci->periodic_stamp) { + modified = qh_completions(ehci, temp.qh); + if (!modified) + temp.qh->stamp = ehci->periodic_stamp; + if (unlikely(list_empty(&temp.qh->qtd_list) || + temp.qh->needs_rescan)) + intr_deschedule(ehci, temp.qh); + } qh_put (temp.qh); break; case Q_TYPE_FSTN: @@ -2460,6 +2466,7 @@ restart: if (ehci->clock_frame != clock_frame) { free_cached_lists(ehci); ehci->clock_frame = clock_frame; + ++ehci->periodic_stamp; } } else { now_uframe++; |