|
@@ -36,6 +36,27 @@
|
|
|
|
|
|
static int ehci_get_frame (struct usb_hcd *hcd);
|
|
|
|
|
|
+#ifdef CONFIG_PCI
|
|
|
+
|
|
|
+static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
|
|
|
+{
|
|
|
+ unsigned uf;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The MosChip MCS9990 controller updates its microframe counter
|
|
|
+ * a little before the frame counter, and occasionally we will read
|
|
|
+ * the invalid intermediate value. Avoid problems by checking the
|
|
|
+ * microframe number (the low-order 3 bits); if they are 0 then
|
|
|
+ * re-read the register to get the correct value.
|
|
|
+ */
|
|
|
+ uf = ehci_readl(ehci, &ehci->regs->frame_index);
|
|
|
+ if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
|
|
|
+ uf = ehci_readl(ehci, &ehci->regs->frame_index);
|
|
|
+ return uf;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
/*
|
|
@@ -481,7 +502,7 @@ static int enable_periodic (struct ehci_hcd *ehci)
|
|
|
/* posted write ... PSS happens later */
|
|
|
|
|
|
/* make sure ehci_work scans these */
|
|
|
- ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index)
|
|
|
+ ehci->next_uframe = ehci_read_frame_index(ehci)
|
|
|
% (ehci->periodic_size << 3);
|
|
|
if (unlikely(ehci->broken_periodic))
|
|
|
ehci->last_periodic_enable = ktime_get_real();
|
|
@@ -1408,7 +1429,7 @@ iso_stream_schedule (
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1);
|
|
|
+ now = ehci_read_frame_index(ehci) & (mod - 1);
|
|
|
|
|
|
/* Typical case: reuse current schedule, stream is still active.
|
|
|
* Hopefully there are no gaps from the host falling behind
|
|
@@ -2275,7 +2296,7 @@ scan_periodic (struct ehci_hcd *ehci)
|
|
|
*/
|
|
|
now_uframe = ehci->next_uframe;
|
|
|
if (ehci->rh_state == EHCI_RH_RUNNING) {
|
|
|
- clock = ehci_readl(ehci, &ehci->regs->frame_index);
|
|
|
+ clock = ehci_read_frame_index(ehci);
|
|
|
clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
|
|
|
} else {
|
|
|
clock = now_uframe + mod - 1;
|
|
@@ -2454,8 +2475,7 @@ restart:
|
|
|
|| ehci->periodic_sched == 0)
|
|
|
break;
|
|
|
ehci->next_uframe = now_uframe;
|
|
|
- now = ehci_readl(ehci, &ehci->regs->frame_index) &
|
|
|
- (mod - 1);
|
|
|
+ now = ehci_read_frame_index(ehci) & (mod - 1);
|
|
|
if (now_uframe == now)
|
|
|
break;
|
|
|
|