*/
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
{
- int rc = 0;
+ int err;
unsigned int delay = XHCI_MAX_HALT_USEC * 2;
struct usb_hcd *hcd = xhci_to_hcd(xhci);
u32 command;
- u32 res;
+ u32 usbsts;
if (!hcd->state)
return 0;
/* Some chips from Fresco Logic need an extraordinary delay */
delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
- if (xhci_handshake(&xhci->op_regs->status,
- STS_HALT, STS_HALT, delay)) {
- xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
- spin_unlock_irq(&xhci->lock);
- return -ETIMEDOUT;
+ err = xhci_handshake(&xhci->op_regs->status, STS_HALT, STS_HALT, delay);
+ if (err) {
+ xhci_warn(xhci, "Clearing Run/Stop bit failed %d\n", err);
+ goto handshake_error;
}
xhci_clear_command_ring(xhci);
command = readl(&xhci->op_regs->command);
command |= CMD_CSS;
writel(command, &xhci->op_regs->command);
+
+ err = xhci_handshake(&xhci->op_regs->status, STS_SAVE, 0, 20 * USEC_PER_MSEC);
+ usbsts = readl(&xhci->op_regs->status);
xhci->broken_suspend = 0;
- if (xhci_handshake(&xhci->op_regs->status,
- STS_SAVE, 0, 20 * 1000)) {
- /*
- * AMD SNPS xHC 3.0 occasionally does not clear the
- * SSS bit of USBSTS and when driver tries to poll
- * to see if the xHC clears BIT(8) which never happens
- * and driver assumes that controller is not responding
- * and times out. To workaround this, its good to check
- * if SRE and HCE bits are not set (as per xhci
- * Section 5.4.2) and bypass the timeout.
- */
- res = readl(&xhci->op_regs->status);
- if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) &&
- (((res & STS_SRE) == 0) &&
- ((res & STS_HCE) == 0))) {
- xhci->broken_suspend = 1;
- } else {
- xhci_warn(xhci, "WARN: xHC save state timeout\n");
- spin_unlock_irq(&xhci->lock);
- return -ETIMEDOUT;
+ if (err) {
+ /*
+ * AMD SNPS xHC 3.0 occasionally does not clear the
+ * SSS bit of USBSTS and when driver tries to poll
+ * to see if the xHC clears BIT(8) which never happens
+ * and driver assumes that controller is not responding
+ * and times out. To workaround this, its good to check
+ * if SRE and HCE bits are not set (as per xhci
+ * Section 5.4.2) and bypass the timeout.
+ */
+ if (!(xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND)) {
+ xhci_warn(xhci, "Controller Save State failed %d\n", err);
+ goto handshake_error;
+ }
+
+ if (usbsts & (STS_SRE | STS_HCE)) {
+ xhci_warn(xhci, "Controller Save State failed, USBSTS 0x%08x\n", usbsts);
+ goto handshake_error;
}
+
+ xhci_dbg(xhci, "SNPS broken suspend, save state unreliable\n");
+ xhci->broken_suspend = 1;
+ } else if (usbsts & STS_SRE) {
+ xhci_warn(xhci, "Suspend Save Error (SRE), USBSTS 0x%08x\n", usbsts);
}
spin_unlock_irq(&xhci->lock);
__func__);
}
- return rc;
+ return 0;
+
+handshake_error:
+ spin_unlock_irq(&xhci->lock);
+ return -ETIMEDOUT;
}
EXPORT_SYMBOL_GPL(xhci_suspend);