--- /dev/null
+From 2f31a67f01a8beb22cae754c53522cb61a005750 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 15 Nov 2018 11:38:41 +0200
+Subject: usb: xhci: Prevent bus suspend if a port connect change or polling state is detected
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 2f31a67f01a8beb22cae754c53522cb61a005750 upstream.
+
+USB3 roothub might autosuspend before a plugged USB3 device is detected,
+causing USB3 device enumeration failure.
+
+USB3 devices don't show up as connected and enabled until USB3 link trainig
+completes. On a fast booting platform with a slow USB3 link training the
+link might reach the connected enabled state just as the bus is suspending.
+
+If this device is discovered first time by the xhci_bus_suspend() routine
+it will be put to U3 suspended state like the other ports which failed to
+suspend earlier.
+
+The hub thread will notice the connect change and resume the bus,
+moving the port back to U0
+
+This U0 -> U3 -> U0 transition right after being connected seems to be
+too much for some devices, causing them to first go to SS.Inactive state,
+and finally end up stuck in a polling state with reset asserted
+
+Fix this by failing the bus suspend if a port has a connect change or is
+in a polling state in xhci_bus_suspend().
+
+Don't do any port changes until all ports are checked, buffer all port
+changes and only write them in the end if suspend can proceed
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-hub.c | 60 +++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 46 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -1298,13 +1298,16 @@ int xhci_bus_suspend(struct usb_hcd *hcd
+ __le32 __iomem **port_array;
+ struct xhci_bus_state *bus_state;
+ unsigned long flags;
++ u32 portsc_buf[USB_MAXCHILDREN];
++ bool wake_enabled;
+
+ max_ports = xhci_get_ports(hcd, &port_array);
+ bus_state = &xhci->bus_state[hcd_index(hcd)];
++ wake_enabled = hcd->self.root_hub->do_remote_wakeup;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+
+- if (hcd->self.root_hub->do_remote_wakeup) {
++ if (wake_enabled) {
+ if (bus_state->resuming_ports || /* USB2 */
+ bus_state->port_remote_wakeup) { /* USB3 */
+ spin_unlock_irqrestore(&xhci->lock, flags);
+@@ -1312,26 +1315,36 @@ int xhci_bus_suspend(struct usb_hcd *hcd
+ return -EBUSY;
+ }
+ }
+-
+- port_index = max_ports;
++ /*
++ * Prepare ports for suspend, but don't write anything before all ports
++ * are checked and we know bus suspend can proceed
++ */
+ bus_state->bus_suspended = 0;
++ port_index = max_ports;
+ while (port_index--) {
+- /* suspend the port if the port is not suspended */
+ u32 t1, t2;
+- int slot_id;
+
+ t1 = readl(port_array[port_index]);
+ t2 = xhci_port_state_to_neutral(t1);
++ portsc_buf[port_index] = 0;
+
+- if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
+- xhci_dbg(xhci, "port %d not suspended\n", port_index);
+- slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+- port_index + 1);
+- if (slot_id) {
++ /* Bail out if a USB3 port has a new device in link training */
++ if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) {
++ bus_state->bus_suspended = 0;
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ xhci_dbg(xhci, "Bus suspend bailout, port in polling\n");
++ return -EBUSY;
++ }
++
++ /* suspend ports in U0, or bail out for new connect changes */
++ if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
++ if ((t1 & PORT_CSC) && wake_enabled) {
++ bus_state->bus_suspended = 0;
+ spin_unlock_irqrestore(&xhci->lock, flags);
+- xhci_stop_device(xhci, slot_id, 1);
+- spin_lock_irqsave(&xhci->lock, flags);
++ xhci_dbg(xhci, "Bus suspend bailout, port connect change\n");
++ return -EBUSY;
+ }
++ xhci_dbg(xhci, "port %d not suspended\n", port_index);
+ t2 &= ~PORT_PLS_MASK;
+ t2 |= PORT_LINK_STROBE | XDEV_U3;
+ set_bit(port_index, &bus_state->bus_suspended);
+@@ -1340,7 +1353,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd
+ * including the USB 3.0 roothub, but only if CONFIG_PM
+ * is enabled, so also enable remote wake here.
+ */
+- if (hcd->self.root_hub->do_remote_wakeup) {
++ if (wake_enabled) {
+ if (t1 & PORT_CONNECT) {
+ t2 |= PORT_WKOC_E | PORT_WKDISC_E;
+ t2 &= ~PORT_WKCONN_E;
+@@ -1353,7 +1366,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd
+
+ t1 = xhci_port_state_to_neutral(t1);
+ if (t1 != t2)
+- writel(t2, port_array[port_index]);
++ portsc_buf[port_index] = t2;
++ }
++
++ /* write port settings, stopping and suspending ports if needed */
++ port_index = max_ports;
++ while (port_index--) {
++ if (!portsc_buf[port_index])
++ continue;
++ if (test_bit(port_index, &bus_state->bus_suspended)) {
++ int slot_id;
++
++ slot_id = xhci_find_slot_id_by_port(hcd, xhci,
++ port_index + 1);
++ if (slot_id) {
++ spin_unlock_irqrestore(&xhci->lock, flags);
++ xhci_stop_device(xhci, slot_id, 1);
++ spin_lock_irqsave(&xhci->lock, flags);
++ }
++ }
++ writel(portsc_buf[port_index], port_array[port_index]);
+ }
+ hcd->state = HC_STATE_SUSPENDED;
+ bus_state->next_statechange = jiffies + msecs_to_jiffies(10);