aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2011-10-12 10:39:14 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-18 16:49:33 -0400
commit68aa95d5d4de31c9348c1628ffa85c805305ebc5 (patch)
tree7782dad26b9672be03b78a70cae1105f395dafe2 /drivers/usb/host
parent91960c2ef095c4b0744349e80a933921cbdcfd6e (diff)
EHCI: workaround for MosChip controller bug
This patch (as1489) works around a hardware bug in MosChip EHCI controllers. Evidently when one of these controllers increments the frame-index register, it changes the three low-order bits (the microframe counter) before changing the higher order bits (the frame counter). If the register is read at just the wrong time, the value obtained is too low by 8. When the appropriate quirk flag is set, we work around this problem by reading the frame-index register a second time if the first value's three low-order bits are all 0. This gives the hardware a chance to finish updating the register, yielding the correct value. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Tested-by: Jason N Pitt <jpitt@fhcrc.org> CC: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-dbg.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c3
-rw-r--r--drivers/usb/host/ehci-pci.c5
-rw-r--r--drivers/usb/host/ehci-sched.c30
-rw-r--r--drivers/usb/host/ehci.h17
5 files changed, 49 insertions, 8 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 9952505d2357..d6d74d2e09f4 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -821,7 +821,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
821 next += temp; 821 next += temp;
822 822
823 temp = scnprintf (next, size, "uframe %04x\n", 823 temp = scnprintf (next, size, "uframe %04x\n",
824 ehci_readl(ehci, &ehci->regs->frame_index)); 824 ehci_read_frame_index(ehci));
825 size -= temp; 825 size -= temp;
826 next += temp; 826 next += temp;
827 827
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 05abbcd93cf4..59e81615e09c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1195,8 +1195,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
1195static int ehci_get_frame (struct usb_hcd *hcd) 1195static int ehci_get_frame (struct usb_hcd *hcd)
1196{ 1196{
1197 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 1197 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
1198 return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) % 1198 return (ehci_read_frame_index(ehci) >> 3) % ehci->periodic_size;
1199 ehci->periodic_size;
1200} 1199}
1201 1200
1202/*-------------------------------------------------------------------------*/ 1201/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 8311de7c0a75..f4b627d343ac 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -224,6 +224,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
224 pci_dev_put(p_smbus); 224 pci_dev_put(p_smbus);
225 } 225 }
226 break; 226 break;
227 case PCI_VENDOR_ID_NETMOS:
228 /* MosChip frame-index-register bug */
229 ehci_info(ehci, "applying MosChip frame-index workaround\n");
230 ehci->frame_index_bug = 1;
231 break;
227 } 232 }
228 233
229 /* optional debug port, normally in the first BAR */ 234 /* optional debug port, normally in the first BAR */
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 488151bb45cb..2e829fae6482 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -36,6 +36,27 @@
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
39/*-------------------------------------------------------------------------*/ 60/*-------------------------------------------------------------------------*/
40 61
41/* 62/*
@@ -481,7 +502,7 @@ static int enable_periodic (struct ehci_hcd *ehci)
481 /* posted write ... PSS happens later */ 502 /* posted write ... PSS happens later */
482 503
483 /* make sure ehci_work scans these */ 504 /* make sure ehci_work scans these */
484 ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) 505 ehci->next_uframe = ehci_read_frame_index(ehci)
485 % (ehci->periodic_size << 3); 506 % (ehci->periodic_size << 3);
486 if (unlikely(ehci->broken_periodic)) 507 if (unlikely(ehci->broken_periodic))
487 ehci->last_periodic_enable = ktime_get_real(); 508 ehci->last_periodic_enable = ktime_get_real();
@@ -1408,7 +1429,7 @@ iso_stream_schedule (
1408 goto fail; 1429 goto fail;
1409 } 1430 }
1410 1431
1411 now = ehci_readl(ehci, &ehci->regs->frame_index) & (mod - 1); 1432 now = ehci_read_frame_index(ehci) & (mod - 1);
1412 1433
1413 /* Typical case: reuse current schedule, stream is still active. 1434 /* Typical case: reuse current schedule, stream is still active.
1414 * Hopefully there are no gaps from the host falling behind 1435 * Hopefully there are no gaps from the host falling behind
@@ -2275,7 +2296,7 @@ scan_periodic (struct ehci_hcd *ehci)
2275 */ 2296 */
2276 now_uframe = ehci->next_uframe; 2297 now_uframe = ehci->next_uframe;
2277 if (ehci->rh_state == EHCI_RH_RUNNING) { 2298 if (ehci->rh_state == EHCI_RH_RUNNING) {
2278 clock = ehci_readl(ehci, &ehci->regs->frame_index); 2299 clock = ehci_read_frame_index(ehci);
2279 clock_frame = (clock >> 3) & (ehci->periodic_size - 1); 2300 clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
2280 } else { 2301 } else {
2281 clock = now_uframe + mod - 1; 2302 clock = now_uframe + mod - 1;
@@ -2454,8 +2475,7 @@ restart:
2454 || ehci->periodic_sched == 0) 2475 || ehci->periodic_sched == 0)
2455 break; 2476 break;
2456 ehci->next_uframe = now_uframe; 2477 ehci->next_uframe = now_uframe;
2457 now = ehci_readl(ehci, &ehci->regs->frame_index) & 2478 now = ehci_read_frame_index(ehci) & (mod - 1);
2458 (mod - 1);
2459 if (now_uframe == now) 2479 if (now_uframe == now)
2460 break; 2480 break;
2461 2481
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index c161d97de7dd..0a5fda73b3f2 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -146,6 +146,7 @@ struct ehci_hcd { /* one per controller */
146 unsigned fs_i_thresh:1; /* Intel iso scheduling */ 146 unsigned fs_i_thresh:1; /* Intel iso scheduling */
147 unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ 147 unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/
148 unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ 148 unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
149 unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
149 150
150 /* required for usb32 quirk */ 151 /* required for usb32 quirk */
151 #define OHCI_CTRL_HCFS (3 << 6) 152 #define OHCI_CTRL_HCFS (3 << 6)
@@ -747,6 +748,22 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
747 748
748/*-------------------------------------------------------------------------*/ 749/*-------------------------------------------------------------------------*/
749 750
751#ifdef CONFIG_PCI
752
753/* For working around the MosChip frame-index-register bug */
754static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
755
756#else
757
758static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
759{
760 return ehci_readl(ehci, &ehci->regs->frame_index);
761}
762
763#endif
764
765/*-------------------------------------------------------------------------*/
766
750#ifndef DEBUG 767#ifndef DEBUG
751#define STUB_DEBUG_FILES 768#define STUB_DEBUG_FILES
752#endif /* DEBUG */ 769#endif /* DEBUG */