diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-04-18 15:32:46 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-19 19:06:23 -0700 |
commit | 6d5f89c7b4fa5f8d6dc757982402c032183ffd8d (patch) | |
tree | c2a82aa3eef6370bdd8ccd7f58887b237798683c | |
parent | cae18768acf684b505c928e5cf7ea741fac45b83 (diff) |
USB: EHCI: remove PORT_RWC_BITS when clearing USB_PORT_FEAT_ENABLE
In the ClearPortFeature/USB_PORT_FEAT_ENABLE case, ehci_hub_control()
would read from status_reg, clear PORT_PE, and write the result back to
status_reg. This would clear any bits in PORT_RWC_BITS that were set in
the registers. Fix this by masking these bits off before the write.
Since this masking is common across all ClearPortFeature cases, move it
into a single early location to avoid duplicating it.
Remove the same bugfix from ehci-tegra.c's tegra_ehci_hub_control(), now
that this case is correctly handled by the core.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 17 | ||||
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 13 |
2 files changed, 8 insertions, 22 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 8f57c6e86e8..1e332ac113f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -704,6 +704,7 @@ static int ehci_hub_control ( goto error; wIndex--; temp = ehci_readl(ehci, status_reg); + temp &= ~PORT_RWC_BITS; /* * Even if OWNER is set, so the port is owned by the @@ -717,8 +718,7 @@ static int ehci_hub_control ( ehci_writel(ehci, temp & ~PORT_PE, status_reg); break; case USB_PORT_FEAT_C_ENABLE: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC, - status_reg); + ehci_writel(ehci, temp | PORT_PEC, status_reg); break; case USB_PORT_FEAT_SUSPEND: if (temp & PORT_RESET) @@ -747,7 +747,7 @@ static int ehci_hub_control ( spin_lock_irqsave(&ehci->lock, flags); } /* resume signaling for 20 msec */ - temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + temp &= ~PORT_WAKE_BITS; ehci_writel(ehci, temp | PORT_RESUME, status_reg); ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); @@ -757,9 +757,8 @@ static int ehci_hub_control ( break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) - ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_POWER), - status_reg); + ehci_writel(ehci, temp & ~PORT_POWER, + status_reg); break; case USB_PORT_FEAT_C_CONNECTION: if (ehci->has_lpm) { @@ -767,12 +766,10 @@ static int ehci_hub_control ( temp &= ~PORT_LPM; temp &= ~PORT_DEV_ADDR; } - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, - status_reg); + ehci_writel(ehci, temp | PORT_CSC, status_reg); break; case USB_PORT_FEAT_C_OVER_CURRENT: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC, - status_reg); + ehci_writel(ehci, temp | PORT_OCC, status_reg); break; case USB_PORT_FEAT_C_RESET: /* GetPortStatus clears reset */ diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 4c8bef615ce..9f817680ff0 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -148,18 +148,7 @@ static int tegra_ehci_hub_control( spin_lock_irqsave(&ehci->lock, flags); - /* - * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits - * that are write on clear, by writing back the register read value, so - * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits - */ - if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) { - temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS; - ehci_writel(ehci, temp & ~PORT_PE, status_reg); - goto done; - } - - else if (typeReq == GetPortStatus) { + if (typeReq == GetPortStatus) { temp = ehci_readl(ehci, status_reg); if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { /* Resume completed, re-enable disconnect detection */ |