aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/xhci-pci.c4
-rw-r--r--drivers/usb/host/xhci.c26
-rw-r--r--drivers/usb/host/xhci.h3
3 files changed, 29 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index a9515265db4d..a9ec7051f286 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
139 pdev->device == 0x43bb)) 139 pdev->device == 0x43bb))
140 xhci->quirks |= XHCI_SUSPEND_DELAY; 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 if (pdev->vendor == PCI_VENDOR_ID_AMD) 146 if (pdev->vendor == PCI_VENDOR_ID_AMD)
143 xhci->quirks |= XHCI_TRUST_TX_LENGTH; 147 xhci->quirks |= XHCI_TRUST_TX_LENGTH;
144 148
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c928dbbff881..c20b85e28d81 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -968,6 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
968 unsigned int delay = XHCI_MAX_HALT_USEC; 968 unsigned int delay = XHCI_MAX_HALT_USEC;
969 struct usb_hcd *hcd = xhci_to_hcd(xhci); 969 struct usb_hcd *hcd = xhci_to_hcd(xhci);
970 u32 command; 970 u32 command;
971 u32 res;
971 972
972 if (!hcd->state) 973 if (!hcd->state)
973 return 0; 974 return 0;
@@ -1021,11 +1022,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
1021 command = readl(&xhci->op_regs->command); 1022 command = readl(&xhci->op_regs->command);
1022 command |= CMD_CSS; 1023 command |= CMD_CSS;
1023 writel(command, &xhci->op_regs->command); 1024 writel(command, &xhci->op_regs->command);
1025 xhci->broken_suspend = 0;
1024 if (xhci_handshake(&xhci->op_regs->status, 1026 if (xhci_handshake(&xhci->op_regs->status,
1025 STS_SAVE, 0, 10 * 1000)) { 1027 STS_SAVE, 0, 10 * 1000)) {
1026 xhci_warn(xhci, "WARN: xHC save state timeout\n"); 1028 /*
1027 spin_unlock_irq(&xhci->lock); 1029 * AMD SNPS xHC 3.0 occasionally does not clear the
1028 return -ETIMEDOUT; 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 }
1029 } 1047 }
1030 spin_unlock_irq(&xhci->lock); 1048 spin_unlock_irq(&xhci->lock);
1031 1049
@@ -1078,7 +1096,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
1078 set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); 1096 set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
1079 1097
1080 spin_lock_irq(&xhci->lock); 1098 spin_lock_irq(&xhci->lock);
1081 if (xhci->quirks & XHCI_RESET_ON_RESUME) 1099 if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend)
1082 hibernated = true; 1100 hibernated = true;
1083 1101
1084 if (!hibernated) { 1102 if (!hibernated) {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 260b259b72bc..c3515bad5dbb 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1850,6 +1850,7 @@ struct xhci_hcd {
1850#define XHCI_ZERO_64B_REGS BIT_ULL(32) 1850#define XHCI_ZERO_64B_REGS BIT_ULL(32)
1851#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) 1851#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
1852#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) 1852#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
1853#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
1853 1854
1854 unsigned int num_active_eps; 1855 unsigned int num_active_eps;
1855 unsigned int limit_active_eps; 1856 unsigned int limit_active_eps;
@@ -1879,6 +1880,8 @@ struct xhci_hcd {
1879 void *dbc; 1880 void *dbc;
1880 /* platform-specific data -- must come last */ 1881 /* platform-specific data -- must come last */
1881 unsigned long priv[0] __aligned(sizeof(s64)); 1882 unsigned long priv[0] __aligned(sizeof(s64));
1883 /* Broken Suspend flag for SNPS Suspend resume issue */
1884 u8 broken_suspend;
1882}; 1885};
1883 1886
1884/* Platform specific overrides to generic XHCI hc_driver ops */ 1887/* Platform specific overrides to generic XHCI hc_driver ops */