1 From c843ba12fdedd07ddd809c84740f4b585839599b Mon Sep 17 00:00:00 2001
2 From: Jonathan Bell <jonathan@raspberrypi.com>
3 Date: Thu, 8 Sep 2022 15:50:15 +0100
4 Subject: [PATCH] usb: xhci: expand mitigations for VLI_SS_BULK_OUT_BUG
7 The VL805 can cause data corruption if a SS Bulk OUT endpoint enters a
8 flow-control condition and there are TRBs in the transfer ring that are
9 not an integral size of wMaxPacket and the endpoint is behind one or more
12 This is frequently the case encountered when FAT32 filesystems are
13 present on mass-storage devices with cluster sizes of 1 sector, and the
14 filesystem is being written to with an aggregate of small files.
16 The initial implementation of this quirk separated TRBs that didn't
17 adhere to this limitation into two - the first a multiple of wMaxPacket
18 and the second the 512-byte remainder - in an attempt to force TD
19 fragments to align with packet boundaries. This reduced the incidence
20 rate of data corruption but did not resolve it.
22 The fix as recommended by VIA is to disable bursts if this sequence of
25 Limit turning off bursts to just USB mass-storage devices by searching
26 the device's configuration for an interface with a class type of
27 USB_CLASS_MASS_STORAGE.
29 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
31 drivers/usb/host/xhci-mem.c | 31 ++++++++++++++++++++++++++++++-
32 1 file changed, 30 insertions(+), 1 deletion(-)
34 --- a/drivers/usb/host/xhci-mem.c
35 +++ b/drivers/usb/host/xhci-mem.c
36 @@ -1437,6 +1437,7 @@ int xhci_endpoint_init(struct xhci_hcd *
37 unsigned int ep_index;
38 struct xhci_ep_ctx *ep_ctx;
39 struct xhci_ring *ep_ring;
40 + struct usb_interface_cache *intfc;
41 unsigned int max_packet;
42 enum xhci_ring_type ring_type;
44 @@ -1446,6 +1447,8 @@ int xhci_endpoint_init(struct xhci_hcd *
46 unsigned int avg_trb_len;
47 unsigned int err_count = 0;
48 + unsigned int is_ums_dev = 0;
51 ep_index = xhci_get_endpoint_index(&ep->desc);
52 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
53 @@ -1477,9 +1480,35 @@ int xhci_endpoint_init(struct xhci_hcd *
55 mult = xhci_get_endpoint_mult(udev, ep);
56 max_packet = usb_endpoint_maxp(&ep->desc);
57 - max_burst = xhci_get_endpoint_max_burst(udev, ep);
58 avg_trb_len = max_esit_payload;
61 + * VL805 errata - Bulk OUT bursts to superspeed mass-storage
62 + * devices behind hub ports can cause data corruption with
63 + * non-wMaxPacket-multiple transfers.
65 + for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
66 + intfc = udev->config->intf_cache[i];
68 + * Slight hack - look at interface altsetting 0, which
69 + * should be the UMS bulk-only interface. If the class
70 + * matches, then we disable out bursts for all OUT
71 + * endpoints because endpoint assignments may change
72 + * between alternate settings.
74 + if (intfc->altsetting[0].desc.bInterfaceClass ==
75 + USB_CLASS_MASS_STORAGE) {
80 + if (xhci->quirks & XHCI_VLI_SS_BULK_OUT_BUG &&
81 + usb_endpoint_is_bulk_out(&ep->desc) && is_ums_dev &&
85 + max_burst = xhci_get_endpoint_max_burst(udev, ep);
87 /* FIXME dig Mult and streams info out of ep companion desc */
89 /* Allow 3 retries for everything but isoc, set CErr = 3 */