bad3790630772de74828d75190707b508537ddd8
[openwrt/staging/stintel.git] /
1 From ba09ce751542f6f80019433364d46a14ade59dd0 Mon Sep 17 00:00:00 2001
2 From: Jonathan Bell <jonathan@raspberrypi.com>
3 Date: Wed, 16 Feb 2022 14:31:02 +0000
4 Subject: [PATCH] usb: xhci: add a quirk for Superspeed bulk OUT
5 transfers on VL805
6
7 The VL805 has a bug in its internal FIFO space accounting that results
8 in bulk OUT babble if a TRB in a large multi-element TD has a data
9 buffer size that is larger than and not a multiple of wMaxPacketSize for
10 the endpoint. If the downstream USB3.0 link is congested, or latency is
11 increased through an intermediate hub, then the VL805 enters a suspected
12 FIFO overflow condition and transmits repeated, garbled data to the
13 endpoint.
14
15 TDs with TRBs of exact multiples of wMaxPacketSize and smaller than
16 wMaxPacketSize appear to be handled correctly, so split buffers at a
17 1024-byte length boundary and put the remainder in a separate smaller
18 TRB.
19
20 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
21 ---
22 drivers/usb/host/xhci-pci.c | 1 +
23 drivers/usb/host/xhci-ring.c | 21 +++++++++++++++++++--
24 drivers/usb/host/xhci.h | 1 +
25 3 files changed, 21 insertions(+), 2 deletions(-)
26
27 --- a/drivers/usb/host/xhci-pci.c
28 +++ b/drivers/usb/host/xhci-pci.c
29 @@ -298,6 +298,7 @@ static void xhci_pci_quirks(struct devic
30 xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
31 xhci->quirks |= XHCI_AVOID_DQ_ON_LINK;
32 xhci->quirks |= XHCI_VLI_TRB_CACHE_BUG;
33 + xhci->quirks |= XHCI_VLI_SS_BULK_OUT_BUG;
34 }
35
36 if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
37 --- a/drivers/usb/host/xhci-ring.c
38 +++ b/drivers/usb/host/xhci-ring.c
39 @@ -3578,14 +3578,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
40 unsigned int num_trbs;
41 unsigned int start_cycle, num_sgs = 0;
42 unsigned int enqd_len, block_len, trb_buff_len, full_len;
43 - int sent_len, ret;
44 - u32 field, length_field, remainder;
45 + int sent_len, ret, vli_quirk = 0;
46 + u32 field, length_field, remainder, maxpacket;
47 u64 addr, send_addr;
48
49 ring = xhci_urb_to_transfer_ring(xhci, urb);
50 if (!ring)
51 return -EINVAL;
52
53 + maxpacket = usb_endpoint_maxp(&urb->ep->desc);
54 full_len = urb->transfer_buffer_length;
55 /* If we have scatter/gather list, we use it. */
56 if (urb->num_sgs && !(urb->transfer_flags & URB_DMA_MAP_SINGLE)) {
57 @@ -3622,6 +3623,17 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
58 start_cycle = ring->cycle_state;
59 send_addr = addr;
60
61 + if (xhci->quirks & XHCI_VLI_SS_BULK_OUT_BUG &&
62 + !usb_urb_dir_in(urb) && urb->dev->speed >= USB_SPEED_SUPER) {
63 + /*
64 + * VL805 - superspeed bulk OUT traffic can cause
65 + * an internal fifo overflow if the TRB buffer is larger
66 + * than wMaxPacket and the length is not an integer
67 + * multiple of wMaxPacket.
68 + */
69 + vli_quirk = 1;
70 + }
71 +
72 /* Queue the TRBs, even if they are zero-length */
73 for (enqd_len = 0; first_trb || enqd_len < full_len;
74 enqd_len += trb_buff_len) {
75 @@ -3634,6 +3646,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
76 if (enqd_len + trb_buff_len > full_len)
77 trb_buff_len = full_len - enqd_len;
78
79 + if (vli_quirk && trb_buff_len > maxpacket) {
80 + /* SS bulk wMaxPacket is 1024B */
81 + remainder = trb_buff_len & (maxpacket - 1);
82 + trb_buff_len -= remainder;
83 + }
84 /* Don't change the cycle bit of the first TRB until later */
85 if (first_trb) {
86 first_trb = false;
87 --- a/drivers/usb/host/xhci.h
88 +++ b/drivers/usb/host/xhci.h
89 @@ -1902,6 +1902,7 @@ struct xhci_hcd {
90 #define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
91 #define XHCI_AVOID_DQ_ON_LINK BIT_ULL(45)
92 #define XHCI_VLI_TRB_CACHE_BUG BIT_ULL(46)
93 +#define XHCI_VLI_SS_BULK_OUT_BUG BIT_ULL(47)
94
95 unsigned int num_active_eps;
96 unsigned int limit_active_eps;