]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: xhci: Enable the TRB overfetch quirk on VIA VL805
authorMichal Pecio <michal.pecio@gmail.com>
Tue, 25 Feb 2025 09:59:27 +0000 (11:59 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Mar 2025 11:47:45 +0000 (12:47 +0100)
commit c133ec0e5717868c9967fa3df92a55e537b1aead upstream.

Raspberry Pi is a major user of those chips and they discovered a bug -
when the end of a transfer ring segment is reached, up to four TRBs can
be prefetched from the next page even if the segment ends with link TRB
and on page boundary (the chip claims to support standard 4KB pages).

It also appears that if the prefetched TRBs belong to a different ring
whose doorbell is later rung, they may be used without refreshing from
system RAM and the endpoint will stay idle if their cycle bit is stale.

Other users complain about IOMMU faults on x86 systems, unsurprisingly.

Deal with it by using existing quirk which allocates a dummy page after
each transfer ring segment. This was seen to resolve both problems. RPi
came up with a more efficient solution, shortening each segment by four
TRBs, but it complicated the driver and they ditched it for this quirk.

Also rename the quirk and add VL805 device ID macro.

Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
Link: https://github.com/raspberrypi/linux/issues/4685
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=215906
CC: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20250225095927.2512358-2-mathias.nyman@linux.intel.com
[ Michal: merge conflict with white space and an unrelated quirk ]
Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.h

index 8740bd443f1387fe843628875a6494d2e4f6ac1d..5b0e0097832299eee3632beb5bb57e456fefdd16 100644 (file)
@@ -2494,7 +2494,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         * and our use of dma addresses in the trb_address_map radix tree needs
         * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.
         */
-       if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH)
+       if (xhci->quirks & XHCI_TRB_OVERFETCH)
+               /* Buggy HC prefetches beyond segment bounds - allocate dummy space at the end */
                xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
                                TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2);
        else
index f716c848285f38f933d1a8dad2b1619ac6eab3c8..2be84d5e9261daa859044d1f37134c8397373bc6 100644 (file)
@@ -37,6 +37,8 @@
 #define PCI_DEVICE_ID_EJ168            0x7023
 #define PCI_DEVICE_ID_EJ188            0x7052
 
+#define PCI_DEVICE_ID_VIA_VL805                                0x3483
+
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI             0x8c31
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI          0x9c31
 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI       0x9cb1
@@ -296,8 +298,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                        pdev->device == 0x3432)
                xhci->quirks |= XHCI_BROKEN_STREAMS;
 
-       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) {
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
                xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
                xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
        }
 
@@ -347,11 +350,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
 
                if (pdev->device == 0x9202) {
                        xhci->quirks |= XHCI_RESET_ON_RESUME;
-                       xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
+                       xhci->quirks |= XHCI_TRB_OVERFETCH;
                }
 
                if (pdev->device == 0x9203)
-                       xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
+                       xhci->quirks |= XHCI_TRB_OVERFETCH;
        }
 
        /* xHC spec requires PCI devices to support D3hot and D3cold */
index efce7f40dd949a62e2c117fceef444e9fcb3a033..2d2e9c59add62522da38d574586593b9ca8d4d0b 100644 (file)
@@ -1902,7 +1902,7 @@ struct xhci_hcd {
 #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)
 #define XHCI_SUSPEND_RESUME_CLKS       BIT_ULL(43)
 #define XHCI_RESET_TO_DEFAULT  BIT_ULL(44)
-#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45)
+#define XHCI_TRB_OVERFETCH     BIT_ULL(45)
 #define XHCI_ZHAOXIN_HOST      BIT_ULL(46)
 
        unsigned int            num_active_eps;