summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2014-01-31 11:26:25 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-22 13:32:28 -0800
commitd6472e8a66fb882548361ddbf96de6db00f3c2b3 (patch)
tree3d2f077cc19591036d8748f1dcac4514ba9ede87
parentf72d5bdddc617fba8057cc898cb146efac588c34 (diff)
xhci 1.0: Limit arbitrarily-aligned scatter gather.
commit 247bf557273dd775505fb9240d2d152f4f20d304 upstream. xHCI 1.0 hosts have a set of requirements on how to align transfer buffers on the endpoint rings called "TD fragment" rules. When the ax88179_178a driver added support for scatter gather in 3.12, with commit 804fad45411b48233b48003e33a78f290d227c8 "USBNET: ax88179_178a: enable tso if usb host supports sg dma", it broke the device under xHCI 1.0 hosts. Under certain network loads, the device would see an unexpected short packet from the host, which would cause the device to stop sending ethernet packets, even through USB packets would still be sent. Commit 35773dac5f86 "usb: xhci: Link TRB must not occur within a USB payload burst" attempted to fix this. It was a quick hack to partially implement the TD fragment rules. However, it caused regressions in the usb-storage layer and userspace USB drivers using libusb. The patches to attempt to fix this are too far reaching into the USB core, and we really need to implement the TD fragment rules correctly in the xHCI driver, instead of continuing to wallpaper over the issues. Disable arbitrarily-aligned scatter-gather in the xHCI driver for 1.0 hosts. Only the ax88179_178a driver checks the no_sg_constraint flag, so don't set it for 1.0 hosts. This should not impact usb-storage or usbfs behavior, since they pass down max packet sized aligned sg-list entries (512 for USB 2.0 and 1024 for USB 3.0). Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Tested-by: Mark Lord <mlord@pobox.com> Cc: David Laight <David.Laight@ACULAB.COM> Cc: Bjørn Mork <bjorn@mork.no> Cc: Freddy Xin <freddy@asix.com.tw> Cc: Ming Lei <ming.lei@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/xhci.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1dceec25223e..b8f2ed60e76c 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4730,9 +4730,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
/* Limit the block layer scatter-gather lists to half a segment. */
hcd->self.sg_tablesize = TRBS_PER_SEGMENT / 2;
- /* support to build packet from discontinuous buffers */
- hcd->self.no_sg_constraint = 1;
-
/* XHCI controllers don't stop the ep queue on short packets :| */
hcd->self.no_stop_on_short = 1;
@@ -4757,6 +4754,14 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
/* xHCI private pointer was set in xhci_pci_probe for the second
* registered roothub.
*/
+ xhci = hcd_to_xhci(hcd);
+ /*
+ * Support arbitrarily aligned sg-list entries on hosts without
+ * TD fragment rules (which are currently unsupported).
+ */
+ if (xhci->hci_version < 0x100)
+ hcd->self.no_sg_constraint = 1;
+
return 0;
}
@@ -4783,6 +4788,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
if (xhci->hci_version > 0x96)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
+ if (xhci->hci_version < 0x100)
+ hcd->self.no_sg_constraint = 1;
+
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)