summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorZhuang Jin Can <jin.can.zhuang@intel.com>2015-07-21 17:20:29 +0300
committerSasha Levin <sasha.levin@oracle.com>2015-08-27 13:25:48 -0400
commit7684040671e323842fb19d24de64318c58009af1 (patch)
treedaa58e72070a617189944e28603549c54981598f /drivers
parentad418404a7c6ec68f3c7c71d45577e49f7b01b04 (diff)
xhci: prevent bus_suspend if SS port resuming in phase 1
[ Upstream commit fac4271d1126c45ceaceb7f4a336317b771eb121 ] When the link is just waken, it's in Resume state, and driver sets PLS to U0. This refers to Phase 1. Phase 2 refers to when the link has completed the transition from Resume state to U0. With the fix of xhci: report U3 when link is in resume state, it also exposes an issue that usb3 roothub and controller can suspend right after phase 1, and this causes a hard hang in controller. To fix the issue, we need to prevent usb3 bus suspend if any port is resuming in phase 1. [merge separate USB2 and USB3 port resume checking to one -Mathias] Cc: <stable@vger.kernel.org> Signed-off-by: Zhuang Jin Can <jin.can.zhuang@intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-hub.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 7ff97c39c8b4..f24bdf3a422e 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