ehci/penwell: Do EHCI hardware workaround.
authorYu Wang <yu.y.wang@intel.com>
Mon, 16 Jan 2012 06:09:12 +0000 (14:09 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 8 Feb 2012 13:13:50 +0000 (05:13 -0800)
BZ: 18046

Sometimes, the mouse and keyboard will auto disconnect during using. And
after disconnect 60 seconds, host auto re-enum the device.

Rootcause:
On Intel Medfield platform, EHCI hardware update FRINDEX register before
update completed QH's ACTIVE flag. This behavior caused EHCI driver
can't find the completed QH in some cases. So EHCI would not send the
QH which is already completed. It need to SW to re-submit QH. But EHCI
driver lost it, then class driver would not resubmit URB forever.

Change-Id: Ic492e162b001d3cdaf1d098f9366c625e0ad10de
Signed-off-by: Yu Wang <yu.y.wang@intel.com>
Reviewed-on: http://android.intel.com:8080/32125
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Reviewed-by: Wu, Hao <hao.wu@intel.com>
Reviewed-by: Meng, Zhe <zhe.meng@intel.com>
Tested-by: Meng, Zhe <zhe.meng@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/usb/host/ehci-sched.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/pci-quirks.h

index 6c9fbe3..de39539 100644 (file)
@@ -2460,8 +2460,11 @@ restart:
                        ehci->next_uframe = now_uframe;
                        now = ehci_readl(ehci, &ehci->regs->frame_index) &
                                        (mod - 1);
-                       if (now_uframe == now)
+                       if (now_uframe == now) {
+                               quirk_usb_periodic_hw_bug_workaround(
+                               &ehci->next_uframe, ehci->periodic_size);
                                break;
+                       }
 
                        /* rescan the rest of this frame, then ... */
                        clock = now;
index 73d0394..59ef0aa 100644 (file)
@@ -888,3 +888,24 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
                quirk_usb_handoff_xhci(pdev);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
+
+/**
+ * This quirk is a hardware workaround. On Intel Medfield platform,
+ * EHCI hardware update FRINDEX register before update completed
+ * QH's active flag. This behavior cause EHCI driver can't find the
+ * completed QH which need to handle.
+ *
+ * Let EHCI driver to roll back 160 uframes to check the completed QH.
+ */
+void quirk_usb_periodic_hw_bug_workaround(int *next_uframe, int periodic_size)
+{
+#ifdef CONFIG_USB_PENWELL_OTG
+#define ROLLBACK_UFRAME 160
+       if (*next_uframe < ROLLBACK_UFRAME)
+               *next_uframe = (periodic_size << 3)
+                       - (ROLLBACK_UFRAME - *next_uframe);
+       else
+               *next_uframe -= ROLLBACK_UFRAME;
+#endif
+}
+EXPORT_SYMBOL_GPL(quirk_usb_periodic_hw_bug_workaround);
index b1002a8..8836192 100644 (file)
@@ -15,5 +15,6 @@ static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
 static inline void usb_amd_dev_put(void) {}
 #endif  /* CONFIG_PCI */
+void quirk_usb_periodic_hw_bug_workaround(int *next_uframe, int periodic_size);
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */