aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-12 09:48:57 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-12 09:48:57 -0800
commit67f68f977a12657028e866c013d43dd87320d210 (patch)
tree52265863113dc948f4698c5ce560028b7a55c6b8 /drivers/usb/host/xhci-mem.c
parentUSB: core: clean up endpoint-descriptor parsing (diff)
downloadlinux-dev-67f68f977a12657028e866c013d43dd87320d210.tar.xz
linux-dev-67f68f977a12657028e866c013d43dd87320d210.zip
Revert "xhci: Fix memory leak when caching protocol extended capability PSI tables"
This reverts commit fc57313d1017dd6b6f37a94e88daa8df54368ecc. Marek reports that it breaks things: This patch landed in today's linux-next (20200211) and causes NULL pointer dereference during second suspend/resume cycle on Samsung Exynos5422-based (arm 32bit) Odroid XU3lite board: A more complete fix will be added soon. Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Fixes: fc57313d1017 ("xhci: Fix memory leak when caching protocol extended capability PSI tables") Cc: Paul Menzel <pmenzel@molgen.mpg.de> Cc: Sajja Venkateswara Rao <VenkateswaraRao.Sajja@amd.com> Cc: stable <stable@vger.kernel.org> # v4.4+ Cc: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c58
1 files changed, 22 insertions, 36 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index bd5b152df6c0..0e2701649369 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1915,16 +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->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;
@@ -2125,7 +2126,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
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,39 +2160,31 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
/* WTF? "Valid values are ‘1’ to MaxPorts" */
return;
- 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;
+ 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;
- port_cap->psi_uid_count++;
- for (i = 0; i < port_cap->psi_count; i++) {
- port_cap->psi[i] = readl(addr + 4 + i);
+ rhub->psi_uid_count++;
+ for (i = 0; i < rhub->psi_count; i++) {
+ rhub->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(port_cap->psi[i]) !=
- XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
- port_cap->psi_uid_count++;
+ if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
+ XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
+ rhub->psi_uid_count++;
xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
- 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]));
+ 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]));
}
}
/* cache usb2 port capabilities */
@@ -2227,7 +2219,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
continue;
}
hw_port->rhub = rhub;
- hw_port->port_cap = port_cap;
rhub->num_ports++;
}
/* FIXME: Should we disable ports not in the Extended Capabilities? */
@@ -2318,11 +2309,6 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
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) {