| From 885e7a6e3263fabfc9e5c0a39fad276d9ed4c798 Mon Sep 17 00:00:00 2001 |
| From: Roger Quadros <rogerq@ti.com> |
| Date: Fri, 7 Apr 2017 17:57:12 +0300 |
| Subject: [PATCH] usb: xhci: bInterval quirk for TI TUSB73x0 |
| |
| commit 69307ccb9ad7ccb653e332de68effdeaaab6907d upstream. |
| |
| As per [1] issue #4, |
| "The periodic EP scheduler always tries to schedule the EPs |
| that have large intervals (interval equal to or greater than |
| 128 microframes) into different microframes. So it maintains |
| an internal counter and increments for each large interval |
| EP added. When the counter is greater than 128, the scheduler |
| rejects the new EP. So when the hub re-enumerated 128 times, |
| it triggers this condition." |
| |
| This results in Bandwidth error when devices with periodic |
| endpoints (ISO/INT) having bInterval > 7 are plugged and |
| unplugged several times on a TUSB73x0 XHCI host. |
| |
| Workaround this issue by limiting the bInterval to 7 |
| (i.e. interval to 6) for High-speed or faster periodic endpoints. |
| |
| [1] - http://www.ti.com/lit/er/sllz076/sllz076.pdf |
| |
| Cc: stable <stable@vger.kernel.org> |
| Signed-off-by: Roger Quadros <rogerq@ti.com> |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c |
| index 7064892ff4a6..87848ce95b6f 100644 |
| --- a/drivers/usb/host/xhci-mem.c |
| +++ b/drivers/usb/host/xhci-mem.c |
| @@ -1494,6 +1494,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, |
| */ |
| max_esit_payload = xhci_get_max_esit_payload(udev, ep); |
| interval = xhci_get_endpoint_interval(udev, ep); |
| + |
| + /* Periodic endpoint bInterval limit quirk */ |
| + if (usb_endpoint_xfer_int(&ep->desc) || |
| + usb_endpoint_xfer_isoc(&ep->desc)) { |
| + if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) && |
| + udev->speed >= USB_SPEED_HIGH && |
| + interval >= 7) { |
| + interval = 6; |
| + } |
| + } |
| + |
| mult = xhci_get_endpoint_mult(udev, ep); |
| max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); |
| max_burst = xhci_get_endpoint_max_burst(udev, ep); |
| diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c |
| index 954abfd5014d..93f566cb968b 100644 |
| --- a/drivers/usb/host/xhci-pci.c |
| +++ b/drivers/usb/host/xhci-pci.c |
| @@ -199,6 +199,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) |
| pdev->device == 0x1042) |
| xhci->quirks |= XHCI_BROKEN_STREAMS; |
| |
| + if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241) |
| + xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; |
| + |
| if (xhci->quirks & XHCI_RESET_ON_RESUME) |
| xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, |
| "QUIRK: Resetting on resume"); |
| diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h |
| index f97b009ffc40..328fe06752ec 100644 |
| --- a/drivers/usb/host/xhci.h |
| +++ b/drivers/usb/host/xhci.h |
| @@ -1659,6 +1659,7 @@ struct xhci_hcd { |
| #define XHCI_MISSING_CAS (1 << 24) |
| /* For controller with a broken Port Disable implementation */ |
| #define XHCI_BROKEN_PORT_PED (1 << 25) |
| +#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) |
| |
| unsigned int num_active_eps; |
| unsigned int limit_active_eps; |
| -- |
| 2.12.0 |
| |