Hi Xenia,
thank you for the patch. I tried to reproduce the error with patched 3.10.9
kernel but it seems the kmemleak is indeed gone. Provided I get only these lines
logged which used to be followed by kmemleak findings I believe the original
fixed:
[15885.206032] usb 4-2.1: reset SuperSpeed USB device number 3 using xhci_hcd
[15885.225856] usb 4-2.1: Parent hub missing LPM exit latency info. Power
management will be impacted.
[15885.228445] xhci_hcd :0b:00.0: xHCI xhci_drop_endpoint called with
disabled ep 8803ff81b1c8
[15885.228453] xhci_hcd :0b:00.0: xHCI xhci_drop_endpoint called with
disabled ep 8803ff81b208
[41990.166310] usb 4-2.1: reset SuperSpeed USB device number 9 using xhci_hcd
[41990.187276] usb 4-2.1: Parent hub missing LPM exit latency info. Power
management will be impacted.
[41990.189285] xhci_hcd :0b:00.0: xHCI xhci_drop_endpoint called with
disabled ep 8803ca0381c8
[41990.189287] xhci_hcd :0b:00.0: xHCI xhci_drop_endpoint called with
disabled ep 8803ca038208
[65622.903882] usb 4-2.2: reset SuperSpeed USB device number 10 using xhci_hcd
[65622.927980] usb 4-2.2: Parent hub missing LPM exit latency info. Power
management will be impacted.
[65622.929986] xhci_hcd :0b:00.0: xHCI xhci_drop_endpoint called with
disabled ep 8803ff81b130
[65622.929989] xhci_hcd :0b:00.0: xHCI xhci_drop_endpoint called with
disabled ep 8803ff81b170
Thank you,
Martin
Xenia Ragiadakou wrote:
> In usb_reset_and_verify_device(), hub_port_init() allocates a new bos
> descriptor to hold the value read by the device. The new bos descriptor
> has to be compared with the old one in order to figure out if device 's
> firmware has changed in which case the device has to be reenumerated.
> In the original code, none of the two descriptors was deallocated leading
> to memory leaks.
>
> This patch compares the old bos descriptor with the new one to detect change
> in firmware and releases the newly allocated bos descriptor to prevent memory
> leak.
>
> Signed-off-by: Xenia Ragiadakou
> ---
>
> Differences from version 2:
>
> - fix identation
> - initialize udev->bos to null so that check fails if bos is uninitialized
> - move bos deallocation inside 'done' and 're_enumerate' paths to ensure
> that the deallocation will be performed even if hub_port_init() fails
> - remove check (!udev->wusb && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201)
> since the checks that follow suffice
>
> drivers/usb/core/hub.c | 23 +--
> 1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 175179e..2455001 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -4939,7 +4939,8 @@ void usb_hub_cleanup(void)
> } /* usb_hub_cleanup() */
>
> static int descriptors_changed(struct usb_device *udev,
> - struct usb_device_descriptor *old_device_descriptor)
> + struct usb_device_descriptor *old_device_descriptor,
> + struct usb_host_bos *old_bos)
> {
> int changed = 0;
> unsignedindex;
> @@ -4953,6 +4954,16 @@ static int descriptors_changed(struct usb_device *udev,
> sizeof(*old_device_descriptor)) != 0)
> return 1;
>
> + if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
> + return 1;
> + if (udev->bos) {
> + len = udev->bos->desc->wTotalLength;
> + if (len != old_bos->desc->wTotalLength)
> + return 1;
> + if (memcmp(udev->bos->desc, old_bos->desc, le16_to_cpu(len)))
> + return 1;
> + }
> +
> /* Since the idVendor, idProduct, and bcdDevice values in the
>* device descriptor haven't changed, we will assume the
>* Manufacturer and Product strings haven't changed either.
> @@ -5049,6 +5060,7 @@ static int usb_reset_and_verify_device(struct
> usb_device *udev)
> struct usb_hub *parent_hub;
> struct usb_hcd *hcd = bus_to_hcd(udev->bus);
> struct usb_device_descriptordescriptor = udev->descriptor;
> + struct usb_host_bos *bos;
> int i, ret = 0;
> int port1 = udev->portnum;
>
> @@ -5066,6 +5078,9 @@ static int usb_reset_and_verify_device(struct
> usb_device *udev)
> }
> parent_hub = usb_hub_to_struct_hub(parent_hdev);
>
> + bos = udev->bos;
> + udev->bos = NULL;
> +
> /* Disable LPM and LTM while we reset the device and reinstall the alt
>* settings. Device-initiated LPM settings, and system exit latency
>* settings are cleared when the device is reset, so we have to set
> @@ -5099,7 +5114,7 @@ static int usb_reset_and_verify_device(struct
> usb_device *udev)
> goto re_enumerate;
>
> /* Device might have changed firmware (DFU or simila