Refactor the code to clear the port change bits in the port status register. All port status change bits are write one to clear. Remove a redundant port status read that was supposed to unblock any posted writes. We read the port after the write to get the updated status for debugging, so the port read after that is unnecessary. Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> --- drivers/usb/host/xhci-hub.c | 47 +++++++++++++++++++++++++++++------------- 1 files changed, 32 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index eac5b53..5850e8b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -129,6 +129,36 @@ static u32 xhci_port_state_to_neutral(u32 state) return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); } +static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, + u16 wIndex, u32 __iomem *addr, u32 port_status) +{ + char *port_change_bit; + u32 status; + + switch (wValue) { + case USB_PORT_FEAT_C_RESET: + status = PORT_RC; + port_change_bit = "reset"; + break; + case USB_PORT_FEAT_C_CONNECTION: + status = PORT_CSC; + port_change_bit = "connect"; + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + status = PORT_OCC; + port_change_bit = "over-current"; + break; + default: + /* Should never happen */ + return; + } + /* Change bits are all write 1 to clear */ + xhci_writel(xhci, port_status | status, addr); + port_status = xhci_readl(xhci, addr); + xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n", + port_change_bit, wIndex, port_status); +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -138,7 +168,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u32 temp, status; int retval = 0; u32 __iomem *addr; - char *port_change_bit; ports = HCS_MAX_PORTS(xhci->hcs_params1); @@ -229,26 +258,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_port_state_to_neutral(temp); switch (wValue) { case USB_PORT_FEAT_C_RESET: - status = PORT_RC; - port_change_bit = "reset"; - break; case USB_PORT_FEAT_C_CONNECTION: - status = PORT_CSC; - port_change_bit = "connect"; - break; case USB_PORT_FEAT_C_OVER_CURRENT: - status = PORT_OCC; - port_change_bit = "over-current"; + xhci_clear_port_change_bit(xhci, wValue, wIndex, + addr, temp); break; default: goto error; } - /* Change bits are all write 1 to clear */ - xhci_writel(xhci, temp | status, addr); - temp = xhci_readl(xhci, addr); - xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n", - port_change_bit, wIndex, temp); - temp = xhci_readl(xhci, addr); /* unblock any posted writes */ break; default: error: -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html