FAILED: patch "[PATCH] xhci: Fix memory leak when caching protocol extended" failed to apply to 4.9-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From cf0ee7c60c89641f6e4d1d3c7867fe32b9e30300 Mon Sep 17 00:00:00 2001
From: Mathias Nyman <[email protected]>
Date: Tue, 11 Feb 2020 17:01:58 +0200
Subject: [PATCH] xhci: Fix memory leak when caching protocol extended
capability PSI tables - take 2
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.
drivers/usb/host/xhci-hub.c +17 -8
@@ -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(struct xhci_hcd *xhci, char *buf, 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(struct xhci_hcd *xhci, char *buf, }/* 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(struct xhci_hcd *xhci, char *buf,/* 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(struct xhci_hcd *xhci, char *buf,* 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);
drivers/usb/host/xhci-mem.c +37 -22
103 lines not on this page · raw message
drivers/usb/host/xhci.h +11 -3
@@ -1702,12 +1702,20 @@ struct xhci_bus_state {* Intel Lynx Point LP xHCI host. */ #define XHCI_MAX_REXIT_TIMEOUT_MS 20 +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 {
@@ -1719,9 +1727,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 */
@@ -1880,6 +1885,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;