Skip to content

Commit a7d57ab

Browse files
Sandeep Singhgregkh
authored andcommitted
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>
1 parent 704620a commit a7d57ab

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

drivers/usb/host/xhci-pci.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
139139
pdev->device == 0x43bb))
140140
xhci->quirks |= XHCI_SUSPEND_DELAY;
141141

142+
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
143+
(pdev->device == 0x15e0 || pdev->device == 0x15e1))
144+
xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
145+
142146
if (pdev->vendor == PCI_VENDOR_ID_AMD)
143147
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
144148

drivers/usb/host/xhci.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
968968
unsigned int delay = XHCI_MAX_HALT_USEC;
969969
struct usb_hcd *hcd = xhci_to_hcd(xhci);
970970
u32 command;
971+
u32 res;
971972

972973
if (!hcd->state)
973974
return 0;
@@ -1021,11 +1022,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
10211022
command = readl(&xhci->op_regs->command);
10221023
command |= CMD_CSS;
10231024
writel(command, &xhci->op_regs->command);
1025+
xhci->broken_suspend = 0;
10241026
if (xhci_handshake(&xhci->op_regs->status,
10251027
STS_SAVE, 0, 10 * 1000)) {
1026-
xhci_warn(xhci, "WARN: xHC save state timeout\n");
1027-
spin_unlock_irq(&xhci->lock);
1028-
return -ETIMEDOUT;
1028+
/*
1029+
* AMD SNPS xHC 3.0 occasionally does not clear the
1030+
* SSS bit of USBSTS and when driver tries to poll
1031+
* to see if the xHC clears BIT(8) which never happens
1032+
* and driver assumes that controller is not responding
1033+
* and times out. To workaround this, its good to check
1034+
* if SRE and HCE bits are not set (as per xhci
1035+
* Section 5.4.2) and bypass the timeout.
1036+
*/
1037+
res = readl(&xhci->op_regs->status);
1038+
if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) &&
1039+
(((res & STS_SRE) == 0) &&
1040+
((res & STS_HCE) == 0))) {
1041+
xhci->broken_suspend = 1;
1042+
} else {
1043+
xhci_warn(xhci, "WARN: xHC save state timeout\n");
1044+
spin_unlock_irq(&xhci->lock);
1045+
return -ETIMEDOUT;
1046+
}
10291047
}
10301048
spin_unlock_irq(&xhci->lock);
10311049

@@ -1078,7 +1096,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
10781096
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
10791097

10801098
spin_lock_irq(&xhci->lock);
1081-
if (xhci->quirks & XHCI_RESET_ON_RESUME)
1099+
if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend)
10821100
hibernated = true;
10831101

10841102
if (!hibernated) {

drivers/usb/host/xhci.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,7 @@ struct xhci_hcd {
18501850
#define XHCI_ZERO_64B_REGS BIT_ULL(32)
18511851
#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
18521852
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
1853+
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
18531854

18541855
unsigned int num_active_eps;
18551856
unsigned int limit_active_eps;
@@ -1879,6 +1880,8 @@ struct xhci_hcd {
18791880
void *dbc;
18801881
/* platform-specific data -- must come last */
18811882
unsigned long priv[0] __aligned(sizeof(s64));
1883+
/* Broken Suspend flag for SNPS Suspend resume issue */
1884+
u8 broken_suspend;
18821885
};
18831886

18841887
/* Platform specific overrides to generic XHCI hc_driver ops */

0 commit comments

Comments
 (0)