xHCI: Increase the timeout for controller save/restore state operation
authorAndiry Xu <andiry.xu@gmail.com>
Wed, 13 Jun 2012 02:51:57 +0000 (10:51 +0800)
committerSarah Sharp <sarah.a.sharp@linux.intel.com>
Wed, 13 Jun 2012 23:39:38 +0000 (16:39 -0700)
When system software decides to power down the xHC with the intent of
resuming operation at a later time, it will ask xHC to save the internal
state and restore it when resume to correctly recover from a power event.
Two bits are used to enable this operation: Save State and Restore State.

xHCI spec 4.23.2 says software should "Set the Controller Save/Restore
State flag in the USBCMD register and wait for the Save/Restore State
Status flag in the USBSTS register to transition to '0'". However, it does
not define how long software should wait for the SSS/RSS bit to transition
to 0.

Currently the timeout is set to 1ms. There is bug report
(https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1002697)
indicates that the timeout is too short for ASMedia ASM1042 host controller
to save/restore the state successfully. Increase the timeout to 10ms helps to
resolve the issue.

This patch should be backported to stable kernels as old as 2.6.37, that
contain the commit 5535b1d5f8885695c6ded783c692e3c0d0eda8ca "USB: xHCI:
PCI power management implementation"

Signed-off-by: Andiry Xu <andiry.xu@gmail.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: Ming Lei <ming.lei@canonical.com>
Cc: stable@vger.kernel.org
drivers/usb/host/xhci.c

index 1d4958f..a979cd0 100644 (file)
@@ -795,8 +795,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command |= CMD_CSS;
        xhci_writel(xhci, command, &xhci->op_regs->command);
-       if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) {
-               xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n");
+       if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
+               xhci_warn(xhci, "WARN: xHC save state timeout\n");
                spin_unlock_irq(&xhci->lock);
                return -ETIMEDOUT;
        }
@@ -848,8 +848,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                command |= CMD_CRS;
                xhci_writel(xhci, command, &xhci->op_regs->command);
                if (handshake(xhci, &xhci->op_regs->status,
-                             STS_RESTORE, 0, 10*100)) {
-                       xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n");
+                             STS_RESTORE, 0, 10 * 1000)) {
+                       xhci_warn(xhci, "WARN: xHC restore state timeout\n");
                        spin_unlock_irq(&xhci->lock);
                        return -ETIMEDOUT;
                }