From 247bf557273dd775505fb9240d2d152f4f20d304 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:26:25 -0800 Subject: [PATCH 1/4] xhci 1.0: Limit arbitrarily-aligned scatter gather. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Tested-by: Mark Lord Cc: David Laight Cc: Bjørn Mork Cc: Freddy Xin Cc: Ming Lei Cc: stable@vger.kernel.org # 3.12 --- drivers/usb/host/xhci.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3712359d18ba..86a2e834fdff 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4733,9 +4733,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; @@ -4760,6 +4757,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; } @@ -4788,6 +4793,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) From 1386ff75797a187df324062fb4e929152392da88 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:45:02 -0800 Subject: [PATCH 2/4] Revert "xhci: Set scatter-gather limit to avoid failed block writes." This reverts commit f2d9b991c549f159dc9ae81f77d8206c790cbfee. We are ripping out commit 35773dac5f862cb1c82ea151eba3e2f6de51ec3e "usb: xhci: Link TRB must not occur within a USB payload burst" because it's a hack that caused regressions in the usb-storage and userspace USB drivers that use usbfs and libusb. This commit attempted to fix the issues with that patch. Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org #3.12 --- drivers/usb/host/xhci.c | 4 ++-- drivers/usb/host/xhci.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 86a2e834fdff..6fe577d46fa2 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4730,8 +4730,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) struct device *dev = hcd->self.controller; int retval; - /* Limit the block layer scatter-gather lists to half a segment. */ - hcd->self.sg_tablesize = TRBS_PER_SEGMENT / 2; + /* Accept arbitrarily long scatter-gather lists */ + hcd->self.sg_tablesize = ~0; /* XHCI controllers don't stop the ep queue on short packets :| */ hcd->self.no_stop_on_short = 1; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9154fd6cf24c..58ed9d088e63 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1268,7 +1268,7 @@ union xhci_trb { * since the command ring is 64-byte aligned. * It must also be greater than 16. */ -#define TRBS_PER_SEGMENT 256 +#define TRBS_PER_SEGMENT 64 /* Allow two commands + a link TRB, along with any reserved command TRBs */ #define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) #define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) From 9cf00d91708221ff2d8a11143315f7ebab8d5da8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:51:59 -0800 Subject: [PATCH 3/4] Revert "xhci: Avoid infinite loop when sg urb requires too many trbs" This reverts commit d6c9ea9069af684358efedcaf2f2f687f51c58ee. We are ripping out commit 35773dac5f862cb1c82ea151eba3e2f6de51ec3e "usb: xhci: Link TRB must not occur within a USB payload burst" because it's a hack that caused regressions in the usb-storage and userspace USB drivers that use usbfs and libusb. This commit attempted to fix the issues with that patch. Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org # 3.12 --- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 909b32a4412f..0272450a1667 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3002,7 +3002,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, if (num_trbs >= TRBS_PER_SEGMENT) { xhci_err(xhci, "Too many fragments %d, max %d\n", num_trbs, TRBS_PER_SEGMENT - 1); - return -EINVAL; + return -ENOMEM; } nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) | From 3d4b81eda2211f32886e2978daf6f39885042fc4 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 31 Jan 2014 11:52:57 -0800 Subject: [PATCH 4/4] Revert "usb: xhci: Link TRB must not occur within a USB payload burst" This reverts commit 35773dac5f862cb1c82ea151eba3e2f6de51ec3e. It's a hack that caused regressions in the usb-storage and userspace USB drivers that use usbfs and libusb. Commit 70cabb7d992f "xhci 1.0: Limit arbitrarily-aligned scatter gather." should fix the issues seen with the ax88179_178a driver on xHCI 1.0 hosts, without causing regressions. Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org # 3.12 --- drivers/usb/host/xhci-ring.c | 54 ++---------------------------------- include/linux/usb.h | 2 -- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0272450a1667..0ed64eb68e48 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2967,58 +2967,8 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } while (1) { - if (room_on_ring(xhci, ep_ring, num_trbs)) { - union xhci_trb *trb = ep_ring->enqueue; - unsigned int usable = ep_ring->enq_seg->trbs + - TRBS_PER_SEGMENT - 1 - trb; - u32 nop_cmd; - - /* - * Section 4.11.7.1 TD Fragments states that a link - * TRB must only occur at the boundary between - * data bursts (eg 512 bytes for 480M). - * While it is possible to split a large fragment - * we don't know the size yet. - * Simplest solution is to fill the trb before the - * LINK with nop commands. - */ - if (num_trbs == 1 || num_trbs <= usable || usable == 0) - break; - - if (ep_ring->type != TYPE_BULK) - /* - * While isoc transfers might have a buffer that - * crosses a 64k boundary it is unlikely. - * Since we can't add NOPs without generating - * gaps in the traffic just hope it never - * happens at the end of the ring. - * This could be fixed by writing a LINK TRB - * instead of the first NOP - however the - * TRB_TYPE_LINK_LE32() calls would all need - * changing to check the ring length. - */ - break; - - if (num_trbs >= TRBS_PER_SEGMENT) { - xhci_err(xhci, "Too many fragments %d, max %d\n", - num_trbs, TRBS_PER_SEGMENT - 1); - return -ENOMEM; - } - - nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) | - ep_ring->cycle_state); - ep_ring->num_trbs_free -= usable; - do { - trb->generic.field[0] = 0; - trb->generic.field[1] = 0; - trb->generic.field[2] = 0; - trb->generic.field[3] = nop_cmd; - trb++; - } while (--usable); - ep_ring->enqueue = trb; - if (room_on_ring(xhci, ep_ring, num_trbs)) - break; - } + if (room_on_ring(xhci, ep_ring, num_trbs)) + break; if (ep_ring == xhci->cmd_ring) { xhci_err(xhci, "Do not support expand command ring\n"); diff --git a/include/linux/usb.h b/include/linux/usb.h index c716da18c668..7f6eb859873e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1265,8 +1265,6 @@ typedef void (*usb_complete_t)(struct urb *); * @sg: scatter gather buffer list, the buffer size of each element in * the list (except the last) must be divisible by the endpoint's * max packet size if no_sg_constraint isn't set in 'struct usb_bus' - * (FIXME: scatter-gather under xHCI is broken for periodic transfers. - * Do not use urb->sg for interrupt endpoints for now, only bulk.) * @num_mapped_sgs: (internal) number of mapped sg entries * @num_sgs: number of entries in the sg list * @transfer_buffer_length: How big is transfer_buffer. The transfer may