aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci-hub.c
diff options
context:
space:
mode:
authorGary S. Robertson <gary.robertson@linaro.org>2015-09-09 17:04:13 -0500
committerGary S. Robertson <gary.robertson@linaro.org>2015-09-09 17:04:13 -0500
commit48ffd0d5e7b2fb6e7d47344320dbeeaf15d6fd5a (patch)
tree835283be489a3ea03d0f10ca8dbb00ad55a3cd20 /drivers/usb/host/xhci-hub.c
parentaa3ff8e7ce15d756e49141d9aa3f1d9151cda1ca (diff)
parentd9e292d3ea94ab21f028108527a908e415e856ef (diff)
Merge tag 'lsk-v4.1-15.08-rt' of http://git.linaro.org/kernel/linux-linaro-stable into linux-linaro-lng-v4.1-rtlinux-lng-preempt-rt-4.1.5-2015.09
LSK RT 15.08 v4.1
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r--drivers/usb/host/xhci-hub.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0827d7c96527..ee07ba41c8db 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -484,10 +484,13 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
u32 pls = status_reg & PORT_PLS_MASK;
/* resume state is a xHCI internal state.
- * Do not report it to usb core.
+ * Do not report it to usb core, instead, pretend to be U3,
+ * thus usb core knows it's not ready for transfer
*/
- if (pls == XDEV_RESUME)
+ if (pls == XDEV_RESUME) {
+ *status |= USB_SS_PORT_LS_U3;
return;
+ }
/* When the CAS bit is set then warm reset
* should be performed on port
@@ -588,7 +591,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
status |= USB_PORT_STAT_C_RESET << 16;
/* USB3.0 only */
if (hcd->speed == HCD_USB3) {
- if ((raw_port_status & PORT_PLC))
+ /* Port link change with port in resume state should not be
+ * reported to usbcore, as this is an internal state to be
+ * handled by xhci driver. Reporting PLC to usbcore may
+ * cause usbcore clearing PLC first and port change event
+ * irq won't be generated.
+ */
+ if ((raw_port_status & PORT_PLC) &&
+ (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME)
status |= USB_PORT_STAT_C_LINK_STATE << 16;
if ((raw_port_status & PORT_WRC))
status |= USB_PORT_STAT_C_BH_RESET << 16;
@@ -1120,10 +1130,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
spin_lock_irqsave(&xhci->lock, flags);
if (hcd->self.root_hub->do_remote_wakeup) {
- if (bus_state->resuming_ports) {
+ if (bus_state->resuming_ports || /* USB2 */
+ bus_state->port_remote_wakeup) { /* USB3 */
spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "suspend failed because "
- "a port is resuming\n");
+ xhci_dbg(xhci, "suspend failed because a port is resuming\n");
return -EBUSY;
}
}