Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xhci: workaround CSS timeout on AMD SNPS 3.0 xHC

Occasionally AMD SNPS 3.0 xHC does not respond to
CSS when set, also it does not flag anything on SRE and HCE
to point the internal xHC errors on USBSTS register. This stalls
the entire system wide suspend and there is no point in stalling
just because of xHC CSS is not responding.

To work around this problem, if the xHC does not flag
anything on SRE and HCE, we can skip the CSS
timeout and allow the system to continue the suspend. Once the
system resume happens we can internally reset the controller
using XHCI_RESET_ON_RESUME quirk

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Sandeep Singh <Sandeep.Singh@amd.com>
cc: Nehal Shah <Nehal-bakulchandra.Shah@amd.com>
Cc: <stable@vger.kernel.org>
Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sandeep Singh and committed by
Greg Kroah-Hartman
a7d57abc 704620af

+29 -4
+4
drivers/usb/host/xhci-pci.c
··· 139 139 pdev->device == 0x43bb)) 140 140 xhci->quirks |= XHCI_SUSPEND_DELAY; 141 141 142 + if (pdev->vendor == PCI_VENDOR_ID_AMD && 143 + (pdev->device == 0x15e0 || pdev->device == 0x15e1)) 144 + xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND; 145 + 142 146 if (pdev->vendor == PCI_VENDOR_ID_AMD) 143 147 xhci->quirks |= XHCI_TRUST_TX_LENGTH; 144 148
+22 -4
drivers/usb/host/xhci.c
··· 968 968 unsigned int delay = XHCI_MAX_HALT_USEC; 969 969 struct usb_hcd *hcd = xhci_to_hcd(xhci); 970 970 u32 command; 971 + u32 res; 971 972 972 973 if (!hcd->state) 973 974 return 0; ··· 1022 1021 command = readl(&xhci->op_regs->command); 1023 1022 command |= CMD_CSS; 1024 1023 writel(command, &xhci->op_regs->command); 1024 + xhci->broken_suspend = 0; 1025 1025 if (xhci_handshake(&xhci->op_regs->status, 1026 1026 STS_SAVE, 0, 10 * 1000)) { 1027 - xhci_warn(xhci, "WARN: xHC save state timeout\n"); 1028 - spin_unlock_irq(&xhci->lock); 1029 - return -ETIMEDOUT; 1027 + /* 1028 + * AMD SNPS xHC 3.0 occasionally does not clear the 1029 + * SSS bit of USBSTS and when driver tries to poll 1030 + * to see if the xHC clears BIT(8) which never happens 1031 + * and driver assumes that controller is not responding 1032 + * and times out. To workaround this, its good to check 1033 + * if SRE and HCE bits are not set (as per xhci 1034 + * Section 5.4.2) and bypass the timeout. 1035 + */ 1036 + res = readl(&xhci->op_regs->status); 1037 + if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) && 1038 + (((res & STS_SRE) == 0) && 1039 + ((res & STS_HCE) == 0))) { 1040 + xhci->broken_suspend = 1; 1041 + } else { 1042 + xhci_warn(xhci, "WARN: xHC save state timeout\n"); 1043 + spin_unlock_irq(&xhci->lock); 1044 + return -ETIMEDOUT; 1045 + } 1030 1046 } 1031 1047 spin_unlock_irq(&xhci->lock); 1032 1048 ··· 1096 1078 set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); 1097 1079 1098 1080 spin_lock_irq(&xhci->lock); 1099 - if (xhci->quirks & XHCI_RESET_ON_RESUME) 1081 + if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend) 1100 1082 hibernated = true; 1101 1083 1102 1084 if (!hibernated) {
+3
drivers/usb/host/xhci.h
··· 1850 1850 #define XHCI_ZERO_64B_REGS BIT_ULL(32) 1851 1851 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) 1852 1852 #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) 1853 + #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) 1853 1854 1854 1855 unsigned int num_active_eps; 1855 1856 unsigned int limit_active_eps; ··· 1880 1879 void *dbc; 1881 1880 /* platform-specific data -- must come last */ 1882 1881 unsigned long priv[0] __aligned(sizeof(s64)); 1882 + /* Broken Suspend flag for SNPS Suspend resume issue */ 1883 + u8 broken_suspend; 1883 1884 }; 1884 1885 1885 1886 /* Platform specific overrides to generic XHCI hc_driver ops */