usb: xhci: quirk for data loss in ISOC transfers
Subsystems (3)
PATCH 1/1 usb: xhci: quirk for data loss in ISOC transfers
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 either when an IN endpoint with a 64ms service interval is pre-scheduled prior to the ISOC OUT endpoint or when 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 exceed 32ms (interval 8). This adjustment ensures that the OUT endpoint will not be bypassed, even if a smaller interval value is utilized.
--- drivers/usb/host/xhci-mem.c | 5 +++++ drivers/usb/host/xhci-pci.c | 14 ++++++++++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 20 insertions(+)
drivers/usb/host/xhci-mem.c +5 -0
@@ -1426,6 +1426,11 @@ 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 ) && +usb_endpoint_xfer_int (&ep->desc) && + interval >=9 ) { + interval =8 ; + }if ((xhci->quirks &XHCI_LIMIT_ENDPOINT_INTERVAL_7 ) && udev->speed >=USB_SPEED_HIGH && interval >=7 ) {
drivers/usb/host/xhci-pci.c +14 -0
@@ -284,6 +284,20 @@ 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 ==0x13ed || + pdev->device ==0x13ee || + pdev->device ==0x148c || + pdev->device ==0x15d4 || + pdev->device ==0x15d5 || + pdev->device ==0x15e0 || + pdev->device ==0x15e1 || + pdev->device ==0x15e5 )) + xhci->quirks |=XHCI_LIMIT_ENDPOINT_INTERVAL_9 ; + +if (pdev->vendor ==PCI_VENDOR_ID_ATI && pdev->device ==0x7316 ) + xhci->quirks |=XHCI_LIMIT_ENDPOINT_INTERVAL_9 ; +if (pdev->vendor ==PCI_VENDOR_ID_AMD && xhci->hci_version ==0x96 ) xhci->quirks |= XHCI_AMD_0x96_HOST;
drivers/usb/host/xhci.h +1 -0
@@ -1624,6 +1624,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;
Signature · 1 line
2.34.1
Greg KH
maintainerQuoted 14 lines · Raju Rangoju
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 either when an IN endpoint with a 64ms service interval is pre-scheduled prior to the ISOC OUT endpoint or when 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).
Quoted 8 lines
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 exceed 32ms (interval 8). This adjustment ensures that the OUT endpoint will not be bypassed, even if a smaller interval value is utilized.
Signed-off-by Raju Rangoju <[email protected]>
What commit id does this fix? Should it go to stable kernels, and if so, how far back?
thanks,
greg k-h
Greg KH
maintainerQuoted 51 lines · Raju Rangoju
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 either when an IN endpoint with a 64ms service interval is pre-scheduled prior to the ISOC OUT endpoint or when 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 exceed 32ms (interval 8). This adjustment ensures that the OUT endpoint will not be bypassed, even if a smaller interval value is utilized.
Signed-off-by Raju Rangoju <[email protected]>--- drivers/usb/host/xhci-mem.c | 5 +++++ drivers/usb/host/xhci-pci.c | 14 ++++++++++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 20 insertions(+)drivers/usb/host/xhci-mem.c +5
-0@@ -1426,6 +1426,11 @@ 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 ) && +usb_endpoint_xfer_int (&ep->desc) && + interval >=9 ) { + interval =8 ; + }if ((xhci->quirks &XHCI_LIMIT_ENDPOINT_INTERVAL_7 ) && udev->speed >=USB_SPEED_HIGH && interval >=7 ) {drivers/usb/host/xhci-pci.c +0
-0@@ -284,6 +284,20 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)if (pdev->vendor ==PCI_VENDOR_ID_NEC ) xhci->quirks |=XHCI_NEC_HOST ;
drivers/usb/host/xhci-pci.c static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) · line 295
Quoted 10 lines
drivers/usb/host/xhci-pci.c +9
-0+if (pdev->vendor ==PCI_VENDOR_ID_AMD && + (pdev->device ==0x13ed || + pdev->device ==0x13ee || + pdev->device ==0x148c || + pdev->device ==0x15d4 || + pdev->device ==0x15d5 || + pdev->device ==0x15e0 || + pdev->device ==0x15e1 || + pdev->device ==0x15e5 ))
Any need/want to name these pci devices with something we can refer to other than a hex value?
thanks,
greg k-h
Quoted 53 lines · Greg KH
Quoted 52 lines · Raju Rangoju
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 either when an IN endpoint with a 64ms service interval is pre-scheduled prior to the ISOC OUT endpoint or when 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 exceed 32ms (interval 8). This adjustment ensures that the OUT endpoint will not be bypassed, even if a smaller interval value is utilized.
Signed-off-by Raju Rangoju <[email protected]>--- drivers/usb/host/xhci-mem.c | 5 +++++ drivers/usb/host/xhci-pci.c | 14 ++++++++++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 20 insertions(+)drivers/usb/host/xhci-mem.c +5
-0@@ -1426,6 +1426,11 @@ 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 ) && +usb_endpoint_xfer_int (&ep->desc) && + interval >=9 ) { + interval =8 ; + }if ((xhci->quirks &XHCI_LIMIT_ENDPOINT_INTERVAL_7 ) && udev->speed >=USB_SPEED_HIGH && interval >=7 ) {drivers/usb/host/xhci-pci.c +0
-0@@ -284,6 +284,20 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)if (pdev->vendor ==PCI_VENDOR_ID_NEC ) xhci->quirks |=XHCI_NEC_HOST ;
Quoted 12 lines
drivers/usb/host/xhci-pci.c static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) · line 295
Quoted 9 lines
drivers/usb/host/xhci-pci.c +9
-0+if (pdev->vendor ==PCI_VENDOR_ID_AMD && + (pdev->device ==0x13ed || + pdev->device ==0x13ee || + pdev->device ==0x148c || + pdev->device ==0x15d4 || + pdev->device ==0x15d5 || + pdev->device ==0x15e0 || + pdev->device ==0x15e1 || + pdev->device ==0x15e5 ))Any need/want to name these pci devices with something we can refer to other than a hex value?
Certainly, I'll try to see if device names can be used instead.
Quoted 4 lines
thanks,
greg k-h
Quoted 14 lines · Raju Rangoju
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 either when an IN endpoint with a 64ms service interval is pre-scheduled prior to the ISOC OUT endpoint or when 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).
Quoted 3 lines
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 exceed 32ms (interval 8). This
Do you mean "not to exceed 32 ms"?
Quoted 16 lines
adjustment ensures that the OUT endpoint will not be bypassed, even if a smaller interval value is utilized.
Signed-off-by Raju Rangoju <[email protected]>--- drivers/usb/host/xhci-mem.c | 5 +++++ drivers/usb/host/xhci-pci.c | 14 ++++++++++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 20 insertions(+)drivers/usb/host/xhci-mem.c +0
-0
drivers/usb/host/xhci-mem.c int xhci_endpoint_init(struct xhci_hcd *xhci, · line 1433
Quoted 8 lines
drivers/usb/host/xhci-mem.c +5
-0@@ -1426,6 +1426,11 @@ 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 ) && +usb_endpoint_xfer_int (&ep->desc) && + interval >=9 ) { + interval =8 ; + }
This change ensures that the interval is <= 32 ms.
Alan Stern
Quoted 32 lines · Alan Stern
Quoted 14 lines · Raju Rangoju
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 either when an IN endpoint with a 64ms service interval is pre-scheduled prior to the ISOC OUT endpoint or when 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).
Quoted 3 lines
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 exceed 32ms (interval 8). This
Do you mean "not to exceed 32 ms"?
Quoted 11 lines
adjustment ensures that the OUT endpoint will not be bypassed, even if a smaller interval value is utilized.
Signed-off-by Raju Rangoju <[email protected]>--- drivers/usb/host/xhci-mem.c | 5 +++++ drivers/usb/host/xhci-pci.c | 14 ++++++++++++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 20 insertions(+)
Quoted 15 lines
drivers/usb/host/xhci-mem.c int xhci_endpoint_init(struct xhci_hcd *xhci, · line 1433
Quoted 13 lines
drivers/usb/host/xhci-mem.c +5
-0@@ -1426,6 +1426,11 @@ 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 ) && +usb_endpoint_xfer_int (&ep->desc) && + interval >=9 ) { + interval =8 ; + }This change ensures that the interval is <= 32 ms.
That's correct, thanks for pointing it out. I'll take care of this in V2.
Quoted 2 lines
Alan Stern