diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2012-04-23 21:54:36 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-23 23:05:44 +0400 |
commit | 3d9545cc375d117554a9b35dfddadf9189c62775 (patch) | |
tree | b01707d2e0901665f20bae0f0c5a0930af69651a /drivers/usb/host/ehci-hcd.c | |
parent | 09091a4d5f2dd378dcf71de50b48cdacc58a8ac0 (diff) | |
download | linux-3d9545cc375d117554a9b35dfddadf9189c62775.tar.xz |
EHCI: maintain the ehci->command value properly
The ehci-hcd driver is a little haphazard about keeping track of the
state of the USBCMD register. The ehci->command field is supposed to
hold the register's value (apart from a few special bits) at all
times, but it isn't maintained properly.
This patch (as1543) cleans up the situation. It keeps ehci->command
up-to-date, and uses that value rather than reading the register from
the hardware whenever possible.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a87c0573c860..de1e689d3df0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -226,8 +226,13 @@ static int ehci_halt (struct ehci_hcd *ehci) if ((temp & STS_HALT) != 0) return 0; + /* + * This routine gets called during probe before ehci->command + * has been initialized, so we can't rely on its value. + */ + ehci->command &= ~CMD_RUN; temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~CMD_RUN; + temp &= ~(CMD_RUN | CMD_IAAD); ehci_writel(ehci, temp, &ehci->regs->command); return handshake (ehci, &ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); @@ -347,6 +352,7 @@ static int ehci_reset (struct ehci_hcd *ehci) if (ehci->debug) dbgp_external_startup(); + ehci->command = ehci_readl(ehci, &ehci->regs->command); ehci->port_c_suspend = ehci->suspended_ports = ehci->resuming_ports = 0; return retval; @@ -363,16 +369,14 @@ static void ehci_quiesce (struct ehci_hcd *ehci) #endif /* wait for any schedule enables/disables to take effect */ - temp = ehci_readl(ehci, &ehci->regs->command) << 10; - temp &= STS_ASS | STS_PSS; + temp = (ehci->command << 10) & (STS_ASS | STS_PSS); if (handshake_on_error_set_halt(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125)) return; /* then disable anything that's still active */ - temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); - ehci_writel(ehci, temp, &ehci->regs->command); + ehci->command &= ~(CMD_ASE | CMD_PSE); + ehci_writel(ehci, ehci->command, &ehci->regs->command); /* hardware can take 16 microframes to turn off ... */ handshake_on_error_set_halt(ehci, &ehci->regs->status, |