]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Nov 2018 13:10:59 +0000 (14:10 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Nov 2018 13:10:59 +0000 (14:10 +0100)
added patches:
ib-core-perform-modify-qp-on-real-one.patch
usb-xhci-prevent-bus-suspend-if-a-port-connect-change-or-polling-state-is-detected.patch

queue-4.14/ib-core-perform-modify-qp-on-real-one.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/usb-xhci-prevent-bus-suspend-if-a-port-connect-change-or-polling-state-is-detected.patch [new file with mode: 0644]

diff --git a/queue-4.14/ib-core-perform-modify-qp-on-real-one.patch b/queue-4.14/ib-core-perform-modify-qp-on-real-one.patch
new file mode 100644 (file)
index 0000000..87787e9
--- /dev/null
@@ -0,0 +1,50 @@
+From b2bedfb39541a7e14798d066b6f8685d84c8fcf5 Mon Sep 17 00:00:00 2001
+From: Parav Pandit <parav@mellanox.com>
+Date: Tue, 9 Jan 2018 15:24:50 +0200
+Subject: IB/core: Perform modify QP on real one
+
+From: Parav Pandit <parav@mellanox.com>
+
+commit b2bedfb39541a7e14798d066b6f8685d84c8fcf5 upstream.
+
+Currently qp->port stores the port number whenever IB_QP_PORT
+QP attribute mask is set (during QP state transition to INIT state).
+This port number should be stored for the real QP when XRC target QP
+is used.
+
+Follow the ib_modify_qp() implementation and hide the access to ->real_qp.
+
+Fixes: a512c2fbef9c ("IB/core: Introduce modify QP operation with udata")
+Signed-off-by: Parav Pandit <parav@mellanox.com>
+Reviewed-by: Daniel Jurgens <danielj@mellanox.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/verbs.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -1285,7 +1285,7 @@ EXPORT_SYMBOL(ib_resolve_eth_dmac);
+ /**
+  * ib_modify_qp_with_udata - Modifies the attributes for the specified QP.
+- * @qp: The QP to modify.
++ * @ib_qp: The QP to modify.
+  * @attr: On input, specifies the QP attributes to modify.  On output,
+  *   the current values of selected QP attributes are returned.
+  * @attr_mask: A bit-mask used to specify which attributes of the QP
+@@ -1294,9 +1294,10 @@ EXPORT_SYMBOL(ib_resolve_eth_dmac);
+  *   are being modified.
+  * It returns 0 on success and returns appropriate error code on error.
+  */
+-int ib_modify_qp_with_udata(struct ib_qp *qp, struct ib_qp_attr *attr,
++int ib_modify_qp_with_udata(struct ib_qp *ib_qp, struct ib_qp_attr *attr,
+                           int attr_mask, struct ib_udata *udata)
+ {
++      struct ib_qp *qp = ib_qp->real_qp;
+       int ret;
+       if (attr_mask & IB_QP_AV) {
index 6a230767794079530d6dc6f2a7ae631622ac7920..8606a1956416d387ae7ff33dbdb21ad34ef8641e 100644 (file)
@@ -28,6 +28,8 @@ llc-do-not-use-sk_eat_skb.patch
 mm-don-t-warn-about-large-allocations-for-slab.patch
 mm-memory.c-recheck-page-table-entry-with-page-table-lock-held.patch
 tcp-do-not-release-socket-ownership-in-tcp_close.patch
+ib-core-perform-modify-qp-on-real-one.patch
+usb-xhci-prevent-bus-suspend-if-a-port-connect-change-or-polling-state-is-detected.patch
 drm-ast-change-resolution-may-cause-screen-blurred.patch
 drm-ast-fixed-cursor-may-disappear-sometimes.patch
 drm-ast-remove-existing-framebuffers-before-loading-driver.patch
diff --git a/queue-4.14/usb-xhci-prevent-bus-suspend-if-a-port-connect-change-or-polling-state-is-detected.patch b/queue-4.14/usb-xhci-prevent-bus-suspend-if-a-port-connect-change-or-polling-state-is-detected.patch
new file mode 100644 (file)
index 0000000..2727f6b
--- /dev/null
@@ -0,0 +1,146 @@
+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
+@@ -1481,13 +1481,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);
+@@ -1495,26 +1498,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);
+@@ -1523,7 +1536,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;
+@@ -1543,7 +1556,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);