]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Feb 2020 08:52:52 +0000 (09:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Feb 2020 08:52:52 +0000 (09:52 +0100)
added patches:
xhci-fix-memory-leak-when-caching-protocol-extended-capability-psi-tables-take-2.patch
xhci-fix-runtime-pm-enabling-for-quirky-intel-hosts.patch
xhci-force-maximum-packet-size-for-full-speed-bulk-devices-to-valid-range.patch

queue-4.19/series
queue-4.19/xhci-fix-memory-leak-when-caching-protocol-extended-capability-psi-tables-take-2.patch [new file with mode: 0644]
queue-4.19/xhci-fix-runtime-pm-enabling-for-quirky-intel-hosts.patch [new file with mode: 0644]
queue-4.19/xhci-force-maximum-packet-size-for-full-speed-bulk-devices-to-valid-range.patch [new file with mode: 0644]

index 4589c6cb4babe8997d20f3a1b3b15c2ee4241a47..6c6c26f819c7fedb26c782edb28bd57ae5828c66 100644 (file)
@@ -16,3 +16,6 @@ vt-selection-close-sel_buffer-race.patch
 vt-vt_ioctl-fix-race-in-vt_resizex.patch
 staging-android-ashmem-disallow-ashmem-memory-from-being-remapped.patch
 staging-vt6656-fix-sign-of-rx_dbm-to-bb_pre_ed_rssi.patch
+xhci-force-maximum-packet-size-for-full-speed-bulk-devices-to-valid-range.patch
+xhci-fix-runtime-pm-enabling-for-quirky-intel-hosts.patch
+xhci-fix-memory-leak-when-caching-protocol-extended-capability-psi-tables-take-2.patch
diff --git a/queue-4.19/xhci-fix-memory-leak-when-caching-protocol-extended-capability-psi-tables-take-2.patch b/queue-4.19/xhci-fix-memory-leak-when-caching-protocol-extended-capability-psi-tables-take-2.patch
new file mode 100644 (file)
index 0000000..ab840cb
--- /dev/null
@@ -0,0 +1,266 @@
+From cf0ee7c60c89641f6e4d1d3c7867fe32b9e30300 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Tue, 11 Feb 2020 17:01:58 +0200
+Subject: xhci: Fix memory leak when caching protocol extended capability PSI tables - take 2
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit cf0ee7c60c89641f6e4d1d3c7867fe32b9e30300 upstream.
+
+xhci driver assumed that xHC controllers have at most one custom
+supported speed table (PSI) for all usb 3.x ports.
+Memory was allocated for one PSI table under the xhci hub structure.
+
+Turns out this is not the case, some controllers have a separate
+"supported protocol capability" entry with a PSI table for each port.
+This means each usb3 roothub port can in theory support different custom
+speeds.
+
+To solve this, cache all supported protocol capabilities with their PSI
+tables in an array, and add pointers to the xhci port structure so that
+every port points to its capability entry in the array.
+
+When creating the SuperSpeedPlus USB Device Capability BOS descriptor
+for the xhci USB 3.1 roothub we for now will use only data from the
+first USB 3.1 capable protocol capability entry in the array.
+This could be improved later, this patch focuses resolving
+the memory leak.
+
+Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Reported-by: Sajja Venkateswara Rao <VenkateswaraRao.Sajja@amd.com>
+Fixes: 47189098f8be ("xhci: parse xhci protocol speed ID list for usb 3.1 usage")
+Cc: stable <stable@vger.kernel.org> # v4.4+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Link: https://lore.kernel.org/r/20200211150158.14475-1-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-hub.c |   25 ++++++++++++------
+ drivers/usb/host/xhci-mem.c |   61 +++++++++++++++++++++++++++-----------------
+ drivers/usb/host/xhci.h     |   16 +++++++++--
+ 3 files changed, 68 insertions(+), 34 deletions(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -55,6 +55,7 @@ static u8 usb_bos_descriptor [] = {
+ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
+                                    u16 wLength)
+ {
++      struct xhci_port_cap *port_cap = NULL;
+       int i, ssa_count;
+       u32 temp;
+       u16 desc_size, ssp_cap_size, ssa_size = 0;
+@@ -64,16 +65,24 @@ static int xhci_create_usb3_bos_desc(str
+       ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size;
+       /* does xhci support USB 3.1 Enhanced SuperSpeed */
+-      if (xhci->usb3_rhub.min_rev >= 0x01) {
++      for (i = 0; i < xhci->num_port_caps; i++) {
++              if (xhci->port_caps[i].maj_rev == 0x03 &&
++                  xhci->port_caps[i].min_rev >= 0x01) {
++                      usb3_1 = true;
++                      port_cap = &xhci->port_caps[i];
++                      break;
++              }
++      }
++
++      if (usb3_1) {
+               /* does xhci provide a PSI table for SSA speed attributes? */
+-              if (xhci->usb3_rhub.psi_count) {
++              if (port_cap->psi_count) {
+                       /* two SSA entries for each unique PSI ID, RX and TX */
+-                      ssa_count = xhci->usb3_rhub.psi_uid_count * 2;
++                      ssa_count = port_cap->psi_uid_count * 2;
+                       ssa_size = ssa_count * sizeof(u32);
+                       ssp_cap_size -= 16; /* skip copying the default SSA */
+               }
+               desc_size += ssp_cap_size;
+-              usb3_1 = true;
+       }
+       memcpy(buf, &usb_bos_descriptor, min(desc_size, wLength));
+@@ -99,7 +108,7 @@ static int xhci_create_usb3_bos_desc(str
+       }
+       /* If PSI table exists, add the custom speed attributes from it */
+-      if (usb3_1 && xhci->usb3_rhub.psi_count) {
++      if (usb3_1 && port_cap->psi_count) {
+               u32 ssp_cap_base, bm_attrib, psi, psi_mant, psi_exp;
+               int offset;
+@@ -111,7 +120,7 @@ static int xhci_create_usb3_bos_desc(str
+               /* attribute count SSAC bits 4:0 and ID count SSIC bits 8:5 */
+               bm_attrib = (ssa_count - 1) & 0x1f;
+-              bm_attrib |= (xhci->usb3_rhub.psi_uid_count - 1) << 5;
++              bm_attrib |= (port_cap->psi_uid_count - 1) << 5;
+               put_unaligned_le32(bm_attrib, &buf[ssp_cap_base + 4]);
+               if (wLength < desc_size + ssa_size)
+@@ -124,8 +133,8 @@ static int xhci_create_usb3_bos_desc(str
+                * USB 3.1 requires two SSA entries (RX and TX) for every link
+                */
+               offset = desc_size;
+-              for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
+-                      psi = xhci->usb3_rhub.psi[i];
++              for (i = 0; i < port_cap->psi_count; i++) {
++                      psi = port_cap->psi[i];
+                       psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
+                       psi_exp = XHCI_EXT_PORT_PSIE(psi);
+                       psi_mant = XHCI_EXT_PORT_PSIM(psi);
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1915,17 +1915,17 @@ no_bw:
+       xhci->usb3_rhub.num_ports = 0;
+       xhci->num_active_eps = 0;
+       kfree(xhci->usb2_rhub.ports);
+-      kfree(xhci->usb2_rhub.psi);
+       kfree(xhci->usb3_rhub.ports);
+-      kfree(xhci->usb3_rhub.psi);
+       kfree(xhci->hw_ports);
+       kfree(xhci->rh_bw);
+       kfree(xhci->ext_caps);
++      for (i = 0; i < xhci->num_port_caps; i++)
++              kfree(xhci->port_caps[i].psi);
++      kfree(xhci->port_caps);
++      xhci->num_port_caps = 0;
+       xhci->usb2_rhub.ports = NULL;
+-      xhci->usb2_rhub.psi = NULL;
+       xhci->usb3_rhub.ports = NULL;
+-      xhci->usb3_rhub.psi = NULL;
+       xhci->hw_ports = NULL;
+       xhci->rh_bw = NULL;
+       xhci->ext_caps = NULL;
+@@ -2126,6 +2126,7 @@ static void xhci_add_in_port(struct xhci
+       u8 major_revision, minor_revision;
+       struct xhci_hub *rhub;
+       struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
++      struct xhci_port_cap *port_cap;
+       temp = readl(addr);
+       major_revision = XHCI_EXT_PORT_MAJOR(temp);
+@@ -2160,31 +2161,39 @@ static void xhci_add_in_port(struct xhci
+               /* WTF? "Valid values are ‘1’ to MaxPorts" */
+               return;
+-      rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
+-      if (rhub->psi_count) {
+-              rhub->psi = kcalloc_node(rhub->psi_count, sizeof(*rhub->psi),
+-                                  GFP_KERNEL, dev_to_node(dev));
+-              if (!rhub->psi)
+-                      rhub->psi_count = 0;
+-
+-              rhub->psi_uid_count++;
+-              for (i = 0; i < rhub->psi_count; i++) {
+-                      rhub->psi[i] = readl(addr + 4 + i);
++      port_cap = &xhci->port_caps[xhci->num_port_caps++];
++      if (xhci->num_port_caps > max_caps)
++              return;
++
++      port_cap->maj_rev = major_revision;
++      port_cap->min_rev = minor_revision;
++      port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp);
++
++      if (port_cap->psi_count) {
++              port_cap->psi = kcalloc_node(port_cap->psi_count,
++                                           sizeof(*port_cap->psi),
++                                           GFP_KERNEL, dev_to_node(dev));
++              if (!port_cap->psi)
++                      port_cap->psi_count = 0;
++
++              port_cap->psi_uid_count++;
++              for (i = 0; i < port_cap->psi_count; i++) {
++                      port_cap->psi[i] = readl(addr + 4 + i);
+                       /* count unique ID values, two consecutive entries can
+                        * have the same ID if link is assymetric
+                        */
+-                      if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
+-                                XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
+-                              rhub->psi_uid_count++;
++                      if (i && (XHCI_EXT_PORT_PSIV(port_cap->psi[i]) !=
++                                XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
++                              port_cap->psi_uid_count++;
+                       xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
+-                                XHCI_EXT_PORT_PSIV(rhub->psi[i]),
+-                                XHCI_EXT_PORT_PSIE(rhub->psi[i]),
+-                                XHCI_EXT_PORT_PLT(rhub->psi[i]),
+-                                XHCI_EXT_PORT_PFD(rhub->psi[i]),
+-                                XHCI_EXT_PORT_LP(rhub->psi[i]),
+-                                XHCI_EXT_PORT_PSIM(rhub->psi[i]));
++                                XHCI_EXT_PORT_PSIV(port_cap->psi[i]),
++                                XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
++                                XHCI_EXT_PORT_PLT(port_cap->psi[i]),
++                                XHCI_EXT_PORT_PFD(port_cap->psi[i]),
++                                XHCI_EXT_PORT_LP(port_cap->psi[i]),
++                                XHCI_EXT_PORT_PSIM(port_cap->psi[i]));
+               }
+       }
+       /* cache usb2 port capabilities */
+@@ -2231,6 +2240,7 @@ static void xhci_add_in_port(struct xhci
+                       continue;
+               }
+               hw_port->rhub = rhub;
++              hw_port->port_cap = port_cap;
+               rhub->num_ports++;
+       }
+       /* FIXME: Should we disable ports not in the Extended Capabilities? */
+@@ -2321,6 +2331,11 @@ static int xhci_setup_port_arrays(struct
+       if (!xhci->ext_caps)
+               return -ENOMEM;
++      xhci->port_caps = kcalloc_node(cap_count, sizeof(*xhci->port_caps),
++                              flags, dev_to_node(dev));
++      if (!xhci->port_caps)
++              return -ENOMEM;
++
+       offset = cap_start;
+       while (offset) {
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1704,11 +1704,21 @@ static inline unsigned int hcd_index(str
+       else
+               return 1;
+ }
++
++struct xhci_port_cap {
++      u32                     *psi;   /* array of protocol speed ID entries */
++      u8                      psi_count;
++      u8                      psi_uid_count;
++      u8                      maj_rev;
++      u8                      min_rev;
++};
++
+ struct xhci_port {
+       __le32 __iomem          *addr;
+       int                     hw_portnum;
+       int                     hcd_portnum;
+       struct xhci_hub         *rhub;
++      struct xhci_port_cap    *port_cap;
+ };
+ struct xhci_hub {
+@@ -1718,9 +1728,6 @@ struct xhci_hub {
+       /* supported prococol extended capabiliy values */
+       u8                      maj_rev;
+       u8                      min_rev;
+-      u32                     *psi;   /* array of protocol speed ID entries */
+-      u8                      psi_count;
+-      u8                      psi_uid_count;
+ };
+ /* There is one xhci_hcd structure per controller */
+@@ -1882,6 +1889,9 @@ struct xhci_hcd {
+       /* cached usb2 extened protocol capabilites */
+       u32                     *ext_caps;
+       unsigned int            num_ext_caps;
++      /* cached extended protocol port capabilities */
++      struct xhci_port_cap    *port_caps;
++      unsigned int            num_port_caps;
+       /* Compliance Mode Recovery Data */
+       struct timer_list       comp_mode_recovery_timer;
+       u32                     port_status_u0;
diff --git a/queue-4.19/xhci-fix-runtime-pm-enabling-for-quirky-intel-hosts.patch b/queue-4.19/xhci-fix-runtime-pm-enabling-for-quirky-intel-hosts.patch
new file mode 100644 (file)
index 0000000..7468572
--- /dev/null
@@ -0,0 +1,55 @@
+From 024d411e9c5d49eb96c825af52a3ce2682895676 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Mon, 10 Feb 2020 15:45:52 +0200
+Subject: xhci: fix runtime pm enabling for quirky Intel hosts
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 024d411e9c5d49eb96c825af52a3ce2682895676 upstream.
+
+Intel hosts that need the XHCI_PME_STUCK_QUIRK flag should enable
+runtime pm by calling xhci_pme_acpi_rtd3_enable() before
+usb_hcd_pci_probe() calls pci_dev_run_wake().
+Otherwise usage count for the device won't be decreased, and runtime
+suspend is prevented.
+
+usb_hcd_pci_probe() only decreases the usage count if device can
+generate run-time wake-up events, i.e. when pci_dev_run_wake()
+returns true.
+
+This issue was exposed by pci_dev_run_wake() change in
+commit 8feaec33b986 ("PCI / PM: Always check PME wakeup capability for
+runtime wakeup support")
+and should be backported to kernels with that change
+
+Cc: <stable@vger.kernel.org> # 4.13+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20200210134553.9144-4-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -283,6 +283,9 @@ static int xhci_pci_setup(struct usb_hcd
+       if (!usb_hcd_is_primary_hcd(hcd))
+               return 0;
++      if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
++              xhci_pme_acpi_rtd3_enable(pdev);
++
+       xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
+       /* Find any debug ports */
+@@ -340,9 +343,6 @@ static int xhci_pci_probe(struct pci_dev
+                       HCC_MAX_PSA(xhci->hcc_params) >= 4)
+               xhci->shared_hcd->can_do_streams = 1;
+-      if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+-              xhci_pme_acpi_rtd3_enable(dev);
+-
+       /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
+       pm_runtime_put_noidle(&dev->dev);
diff --git a/queue-4.19/xhci-force-maximum-packet-size-for-full-speed-bulk-devices-to-valid-range.patch b/queue-4.19/xhci-force-maximum-packet-size-for-full-speed-bulk-devices-to-valid-range.patch
new file mode 100644 (file)
index 0000000..342cc4c
--- /dev/null
@@ -0,0 +1,51 @@
+From f148b9f402ef002b57bcff3964d45abc8ffb6c3f Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Mon, 10 Feb 2020 15:45:50 +0200
+Subject: xhci: Force Maximum Packet size for Full-speed bulk devices to valid range.
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit f148b9f402ef002b57bcff3964d45abc8ffb6c3f upstream.
+
+A Full-speed bulk USB audio device (DJ-Tech CTRL) with a invalid Maximum
+Packet Size of 4 causes a xHC "Parameter Error" at enumeration.
+
+This is because valid Maximum packet sizes for Full-speed bulk endpoints
+are 8, 16, 32 and 64 bytes. Hosts are not required to support other values
+than these. See usb 2 specs section 5.8.3 for details.
+
+The device starts working after forcing the maximum packet size to 8.
+This is most likely the case with other devices as well, so force the
+maximum packet size to a valid range.
+
+Cc: stable@vger.kernel.org
+Reported-by: Rene D Obermueller <cmdrrdo@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20200210134553.9144-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-mem.c |   12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1475,9 +1475,15 @@ int xhci_endpoint_init(struct xhci_hcd *
+       /* Allow 3 retries for everything but isoc, set CErr = 3 */
+       if (!usb_endpoint_xfer_isoc(&ep->desc))
+               err_count = 3;
+-      /* Some devices get this wrong */
+-      if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
+-              max_packet = 512;
++      /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */
++      if (usb_endpoint_xfer_bulk(&ep->desc)) {
++              if (udev->speed == USB_SPEED_HIGH)
++                      max_packet = 512;
++              if (udev->speed == USB_SPEED_FULL) {
++                      max_packet = rounddown_pow_of_two(max_packet);
++                      max_packet = clamp_val(max_packet, 8, 64);
++              }
++      }
+       /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
+       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
+               avg_trb_len = 8;