]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: xhci: quirk for data loss in ISOC transfers
authorRaju Rangoju <Raju.Rangoju@amd.com>
Fri, 27 Jun 2025 14:41:19 +0000 (17:41 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Jul 2025 16:32:10 +0000 (18:32 +0200)
[ Upstream commit cbc889ab0122366f6cdbe3c28d477c683ebcebc2 ]

During the High-Speed Isochronous Audio transfers, xHCI
controller on certain AMD platforms experiences momentary data
loss. This results in Missed Service Errors (MSE) being
generated by the xHCI.

The root cause of the MSE is attributed to the ISOC OUT endpoint
being omitted from scheduling. This can happen when an IN
endpoint with a 64ms service interval either is pre-scheduled
prior to the ISOC OUT endpoint or the interval of the ISOC OUT
endpoint is shorter than that of the IN endpoint. Consequently,
the OUT service is neglected when an IN endpoint with a service
interval exceeding 32ms is scheduled concurrently (every 64ms in
this scenario).

This issue is particularly seen on certain older AMD platforms.
To mitigate this problem, it is recommended to adjust the service
interval of the IN endpoint to not exceed 32ms (interval 8). This
adjustment ensures that the OUT endpoint will not be bypassed,
even if a smaller interval value is utilized.

Cc: stable <stable@kernel.org>
Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20250627144127.3889714-2-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.h

index 09e7eabdb73f4f139dcc2d9213b13fdde2803e81..537a0bc0f5e1c573c41ad1289ffd792015d3fda4 100644 (file)
@@ -1453,6 +1453,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        /* Periodic endpoint bInterval limit quirk */
        if (usb_endpoint_xfer_int(&ep->desc) ||
            usb_endpoint_xfer_isoc(&ep->desc)) {
+               if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_9) &&
+                   interval >= 9) {
+                       interval = 8;
+               }
                if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) &&
                    udev->speed >= USB_SPEED_HIGH &&
                    interval >= 7) {
index 30b2188a3cf8a8a18a595b3e14bf7f823067eac0..7ad6d13d65ee949bb35d7a05b95a962914dda0b4 100644 (file)
 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI                0x51ed
 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_PCH_XHCI      0x54ed
 
+#define PCI_DEVICE_ID_AMD_ARIEL_TYPEC_XHCI             0x13ed
+#define PCI_DEVICE_ID_AMD_ARIEL_TYPEA_XHCI             0x13ee
+#define PCI_DEVICE_ID_AMD_STARSHIP_XHCI                        0x148c
+#define PCI_DEVICE_ID_AMD_FIREFLIGHT_15D4_XHCI         0x15d4
+#define PCI_DEVICE_ID_AMD_FIREFLIGHT_15D5_XHCI         0x15d5
+#define PCI_DEVICE_ID_AMD_RAVEN_15E0_XHCI              0x15e0
+#define PCI_DEVICE_ID_AMD_RAVEN_15E1_XHCI              0x15e1
+#define PCI_DEVICE_ID_AMD_RAVEN2_XHCI                  0x15e5
 #define PCI_DEVICE_ID_AMD_RENOIR_XHCI                  0x1639
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4                        0x43b9
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_3                        0x43ba
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_2                        0x43bb
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_1                        0x43bc
 
+#define PCI_DEVICE_ID_ATI_NAVI10_7316_XHCI             0x7316
+
 #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI                        0x1042
 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI               0x1142
 #define PCI_DEVICE_ID_ASMEDIA_1142_XHCI                        0x1242
@@ -167,6 +177,21 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_NEC)
                xhci->quirks |= XHCI_NEC_HOST;
 
+       if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+           (pdev->device == PCI_DEVICE_ID_AMD_ARIEL_TYPEC_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_ARIEL_TYPEA_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_STARSHIP_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_FIREFLIGHT_15D4_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_FIREFLIGHT_15D5_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_RAVEN_15E0_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_RAVEN_15E1_XHCI ||
+            pdev->device == PCI_DEVICE_ID_AMD_RAVEN2_XHCI))
+               xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_9;
+
+       if (pdev->vendor == PCI_VENDOR_ID_ATI &&
+           pdev->device == PCI_DEVICE_ID_ATI_NAVI10_7316_XHCI)
+               xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_9;
+
        if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96)
                xhci->quirks |= XHCI_AMD_0x96_HOST;
 
index 542a4b7fd7ce4d89664db5102a04a23702bc4c6b..fd095ff9fc8b91ef7276ba2e630edefb3b63bc15 100644 (file)
@@ -1663,6 +1663,7 @@ struct xhci_hcd {
 #define XHCI_ZHAOXIN_HOST      BIT_ULL(46)
 #define XHCI_WRITE_64_HI_LO    BIT_ULL(47)
 #define XHCI_CDNS_SCTX_QUIRK   BIT_ULL(48)
+#define XHCI_LIMIT_ENDPOINT_INTERVAL_9 BIT_ULL(49)
 
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;