From 598950e713cbf65c8d992ba6fb0d38c4e1a4b494 Mon Sep 17 00:00:00 2001 From: Yu Wang Date: Mon, 16 Jan 2012 14:09:12 +0800 Subject: [PATCH] ehci/penwell: Do EHCI hardware workaround. 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 Reviewed-on: http://android.intel.com:8080/32125 Reviewed-by: Gross, Mark Reviewed-by: Wu, Hao Reviewed-by: Meng, Zhe Tested-by: Meng, Zhe Reviewed-by: buildbot Tested-by: buildbot --- drivers/usb/host/ehci-sched.c | 5 ++++- drivers/usb/host/pci-quirks.c | 21 +++++++++++++++++++++ drivers/usb/host/pci-quirks.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 6c9fbe3..de39539 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -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; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 73d0394..59ef0aa 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -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); diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b1002a8..8836192 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -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 */ -- 2.7.4