diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 08:48:58 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-03 08:48:58 -0800 |
commit | 7f5b09c15ab989ed5ce4adda0be42c1302df70b7 (patch) | |
tree | 9695b00983d1bd077ff91c463abcb136330cf344 /drivers/usb/host/xhci-hub.c | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6 (diff) | |
parent | USB: backlight, appledisplay: fix incomplete registration failure handling (diff) | |
download | linux-dev-7f5b09c15ab989ed5ce4adda0be42c1302df70b7.tar.xz linux-dev-7f5b09c15ab989ed5ce4adda0be42c1302df70b7.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (220 commits)
USB: backlight, appledisplay: fix incomplete registration failure handling
USB: pl2303: remove unnecessary reset of usb_device in urbs
USB: ftdi_sio: remove obsolete check in unthrottle
USB: ftdi_sio: remove unused tx_bytes counter
USB: qcaux: driver for auxiliary serial ports on Qualcomm devices
USB: pl2303: initial TIOCGSERIAL support
USB: option: add Longcheer/Longsung vendor ID
USB: fix I2C API usage in ohci-pnx4008.
USB: usbmon: mask seconds properly in text API
USB: sisusbvga: no unnecessary GFP_ATOMIC
USB: storage: onetouch: unnecessary GFP_ATOMIC
USB: serial: ftdi: add CONTEC vendor and product id
USB: remove references to port->port.count from the serial drivers
USB: tty: Prune uses of tty_request_room in the USB layer
USB: tty: Add a function to insert a string of characters with the same flag
USB: don't read past config->interface[] if usb_control_msg() fails in usb_reset_configuration()
USB: tty: kill request_room for USB ACM class
USB: tty: sort out the request_room handling for whiteheat
USB: storage: fix misplaced parenthesis
USB: vstusb.c: removal of driver for Vernier Software & Technology, Inc., devices and spectrometers
...
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index eac5b53aa9e7..208b805b80eb 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -129,6 +129,50 @@ static u32 xhci_port_state_to_neutral(u32 state) return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); } +static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex, + u32 __iomem *addr, u32 port_status) +{ + /* Write 1 to disable the port */ + xhci_writel(xhci, port_status | PORT_PE, addr); + port_status = xhci_readl(xhci, addr); + xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n", + wIndex, port_status); +} + +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; + case USB_PORT_FEAT_C_ENABLE: + status = PORT_PEC; + port_change_bit = "enable/disable"; + 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 +182,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 +272,18 @@ 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"; + case USB_PORT_FEAT_C_ENABLE: + xhci_clear_port_change_bit(xhci, wValue, wIndex, + addr, temp); + break; + case USB_PORT_FEAT_ENABLE: + xhci_disable_port(xhci, 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: |