From 0975caca6b4800fbd1fa7004325a6e9740eb7d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= Date: Mon, 3 Feb 2025 16:07:49 +0100 Subject: [PATCH] Remove USB stack patches working around obsoleted Z-Wave devices issues In #3224 we've introduced a patch reverting some changes in the USB stack that was supposed to work around issues with some USB devices. Later discussions revealed these devices are obsoleted by the manufacturer and there is no official way of fixing those in newer Linux kernels. However, carrying the patches makes us diverge from upstream and can eventually trigger other problems not present upstream we'll have to handle. Drop these patches now to be part of the upcoming OS 15 release, rather than needing to drop them later in any of the patch revisions later. --- ...changes-causing-issues-with-Z-Wave.m.patch | 650 ------------------ 1 file changed, 650 deletions(-) delete mode 100644 buildroot-external/patches/linux/6.12.11/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch diff --git a/buildroot-external/patches/linux/6.12.11/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch b/buildroot-external/patches/linux/6.12.11/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch deleted file mode 100644 index 4f41422226c..00000000000 --- a/buildroot-external/patches/linux/6.12.11/0002-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch +++ /dev/null @@ -1,650 +0,0 @@ -From 557c96b3f40753fa22ebfe1cb57de360273a92c3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= -Date: Wed, 6 Mar 2024 13:25:41 +0100 -Subject: [PATCH] Revert USB core changes causing issues with Z-Wave.me UZB - stick -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Workaround for issues described on GH [1] and reported in [2]. - -* Revert "USB: core: Fix oversight in SuperSpeed initialization" - This reverts commit 59cf445754566984fd55af19ba7146c76e6627bc. - -* Revert "USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()" - This reverts commit ff33299ec8bb80cdcc073ad9c506bd79bb2ed20b. - -* Revert "USB: core: Change usb_get_device_descriptor() API" - This reverts commit de28e469da75359a2bb8cd8778b78aa64b1be1f4. - -* Revert "USB: core: Unite old scheme and new scheme descriptor reads" - This reverts commit 85d07c55621676d47d873d2749b88f783cd4d5a1. - -[1] https://github.com/home-assistant/operating-system/issues/2995 -[2] https://lore.kernel.org/linux-usb/1e954652-dfb3-4248-beea-b8a449128ff0@sairon.cz/ - -Signed-off-by: Jan Čermák ---- - drivers/usb/core/hcd.c | 10 +- - drivers/usb/core/hub.c | 336 ++++++++++++++++--------------------- - drivers/usb/core/message.c | 29 ++-- - drivers/usb/core/usb.h | 4 +- - 4 files changed, 166 insertions(+), 213 deletions(-) - -diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index 0b2490347b9fe..ab0826d90cc13 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -956,7 +956,6 @@ static int register_root_hub(struct usb_hcd *hcd) - { - struct device *parent_dev = hcd->self.controller; - struct usb_device *usb_dev = hcd->self.root_hub; -- struct usb_device_descriptor *descr; - const int devnum = 1; - int retval; - -@@ -968,16 +967,13 @@ static int register_root_hub(struct usb_hcd *hcd) - mutex_lock(&usb_bus_idr_lock); - - usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); -- descr = usb_get_device_descriptor(usb_dev); -- if (IS_ERR(descr)) { -- retval = PTR_ERR(descr); -+ retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); -+ if (retval != sizeof usb_dev->descriptor) { - mutex_unlock(&usb_bus_idr_lock); - dev_dbg (parent_dev, "can't read %s device descriptor %d\n", - dev_name(&usb_dev->dev), retval); -- return retval; -+ return (retval < 0) ? retval : -EMSGSIZE; - } -- usb_dev->descriptor = *descr; -- kfree(descr); - - if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { - retval = usb_get_bos_descriptor(usb_dev); -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 21ac9b464696f..0962411898b00 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4776,67 +4776,6 @@ static int hub_enable_device(struct usb_device *udev) - return hcd->driver->enable_device(hcd, udev); - } - --/* -- * Get the bMaxPacketSize0 value during initialization by reading the -- * device's device descriptor. Since we don't already know this value, -- * the transfer is unsafe and it ignores I/O errors, only testing for -- * reasonable received values. -- * -- * For "old scheme" initialization, size will be 8 so we read just the -- * start of the device descriptor, which should work okay regardless of -- * the actual bMaxPacketSize0 value. For "new scheme" initialization, -- * size will be 64 (and buf will point to a sufficiently large buffer), -- * which might not be kosher according to the USB spec but it's what -- * Windows does and what many devices expect. -- * -- * Returns: bMaxPacketSize0 or a negative error code. -- */ --static int get_bMaxPacketSize0(struct usb_device *udev, -- struct usb_device_descriptor *buf, int size, bool first_time) --{ -- int i, rc; -- -- /* -- * Retry on all errors; some devices are flakey. -- * 255 is for WUSB devices, we actually need to use -- * 512 (WUSB1.0[4.8.1]). -- */ -- for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { -- /* Start with invalid values in case the transfer fails */ -- buf->bDescriptorType = buf->bMaxPacketSize0 = 0; -- rc = usb_control_msg(udev, usb_rcvaddr0pipe(), -- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, -- USB_DT_DEVICE << 8, 0, -- buf, size, -- initial_descriptor_timeout); -- switch (buf->bMaxPacketSize0) { -- case 8: case 16: case 32: case 64: case 9: -- if (buf->bDescriptorType == USB_DT_DEVICE) { -- rc = buf->bMaxPacketSize0; -- break; -- } -- fallthrough; -- default: -- if (rc >= 0) -- rc = -EPROTO; -- break; -- } -- -- /* -- * Some devices time out if they are powered on -- * when already connected. They need a second -- * reset, so return early. But only on the first -- * attempt, lest we get into a time-out/reset loop. -- */ -- if (rc > 0 || (rc == -ETIMEDOUT && first_time && -- udev->speed > USB_SPEED_FULL)) -- break; -- } -- return rc; --} -- --#define GET_DESCRIPTOR_BUFSIZE 64 -- - /* Reset device, (re)assign address, get device descriptor. - * Device connection must be stable, no more debouncing needed. - * Returns device in USB_STATE_ADDRESS, except on error. -@@ -4846,17 +4785,10 @@ static int get_bMaxPacketSize0(struct usb_device *udev, - * the port lock. For a newly detected device that is not accessible - * through any global pointers, it's not necessary to lock the device, - * but it is still necessary to lock the port. -- * -- * For a newly detected device, @dev_descr must be NULL. The device -- * descriptor retrieved from the device will then be stored in -- * @udev->descriptor. For an already existing device, @dev_descr -- * must be non-NULL. The device descriptor will be stored there, -- * not in @udev->descriptor, because descriptors for registered -- * devices are meant to be immutable. - */ - static int - hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, -- int retry_counter, struct usb_device_descriptor *dev_descr) -+ int retry_counter) - { - struct usb_device *hdev = hub->hdev; - struct usb_hcd *hcd = bus_to_hcd(hdev->bus); -@@ -4868,13 +4800,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - int devnum = udev->devnum; - const char *driver_name; - bool do_new_scheme; -- const bool initial = !dev_descr; -- int maxp0; -- struct usb_device_descriptor *buf, *descr; -- -- buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); -- if (!buf) -- return -ENOMEM; - - /* root hub ports have a slightly longer reset period - * (from USB 2.0 spec, section 7.1.7.5) -@@ -4907,31 +4832,31 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - } - oldspeed = udev->speed; - -- if (initial) { -- /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... -- * it's fixed size except for full speed devices. -+ /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... -+ * it's fixed size except for full speed devices. -+ * For Wireless USB devices, ep0 max packet is always 512 (tho -+ * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. -+ */ -+ switch (udev->speed) { -+ case USB_SPEED_SUPER_PLUS: -+ case USB_SPEED_SUPER: -+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); -+ break; -+ case USB_SPEED_HIGH: /* fixed at 64 */ -+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); -+ break; -+ case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ -+ /* to determine the ep0 maxpacket size, try to read -+ * the device descriptor to get bMaxPacketSize0 and -+ * then correct our initial guess. - */ -- switch (udev->speed) { -- case USB_SPEED_SUPER_PLUS: -- case USB_SPEED_SUPER: -- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); -- break; -- case USB_SPEED_HIGH: /* fixed at 64 */ -- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); -- break; -- case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ -- /* to determine the ep0 maxpacket size, try to read -- * the device descriptor to get bMaxPacketSize0 and -- * then correct our initial guess. -- */ -- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); -- break; -- case USB_SPEED_LOW: /* fixed at 8 */ -- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); -- break; -- default: -- goto fail; -- } -+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); -+ break; -+ case USB_SPEED_LOW: /* fixed at 8 */ -+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); -+ break; -+ default: -+ goto fail; - } - - speed = usb_speed_string(udev->speed); -@@ -4951,24 +4876,22 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - if (udev->speed < USB_SPEED_SUPER) - dev_info(&udev->dev, - "%s %s USB device number %d using %s\n", -- (initial ? "new" : "reset"), speed, -+ (udev->config) ? "reset" : "new", speed, - devnum, driver_name); - -- if (initial) { -- /* Set up TT records, if needed */ -- if (hdev->tt) { -- udev->tt = hdev->tt; -- udev->ttport = hdev->ttport; -- } else if (udev->speed != USB_SPEED_HIGH -- && hdev->speed == USB_SPEED_HIGH) { -- if (!hub->tt.hub) { -- dev_err(&udev->dev, "parent hub has no TT\n"); -- retval = -EINVAL; -- goto fail; -- } -- udev->tt = &hub->tt; -- udev->ttport = port1; -+ /* Set up TT records, if needed */ -+ if (hdev->tt) { -+ udev->tt = hdev->tt; -+ udev->ttport = hdev->ttport; -+ } else if (udev->speed != USB_SPEED_HIGH -+ && hdev->speed == USB_SPEED_HIGH) { -+ if (!hub->tt.hub) { -+ dev_err(&udev->dev, "parent hub has no TT\n"); -+ retval = -EINVAL; -+ goto fail; - } -+ udev->tt = &hub->tt; -+ udev->ttport = port1; - } - - /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? -@@ -4992,6 +4915,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - } - - if (do_new_scheme) { -+ struct usb_device_descriptor *buf; -+ int r = 0; -+ - retval = hub_enable_device(udev); - if (retval < 0) { - dev_err(&udev->dev, -@@ -5000,14 +4926,52 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - goto fail; - } - -- maxp0 = get_bMaxPacketSize0(udev, buf, -- GET_DESCRIPTOR_BUFSIZE, retries == 0); -- if (maxp0 > 0 && !initial && -- maxp0 != udev->descriptor.bMaxPacketSize0) { -- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n"); -- retval = -ENODEV; -- goto fail; -+#define GET_DESCRIPTOR_BUFSIZE 64 -+ buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); -+ if (!buf) { -+ retval = -ENOMEM; -+ continue; -+ } -+ -+ /* Retry on all errors; some devices are flakey. -+ * 255 is for WUSB devices, we actually need to use -+ * 512 (WUSB1.0[4.8.1]). -+ */ -+ for (operations = 0; operations < GET_MAXPACKET0_TRIES; -+ ++operations) { -+ buf->bMaxPacketSize0 = 0; -+ r = usb_control_msg(udev, usb_rcvaddr0pipe(), -+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, -+ USB_DT_DEVICE << 8, 0, -+ buf, GET_DESCRIPTOR_BUFSIZE, -+ initial_descriptor_timeout); -+ switch (buf->bMaxPacketSize0) { -+ case 8: case 16: case 32: case 64: case 255: -+ if (buf->bDescriptorType == -+ USB_DT_DEVICE) { -+ r = 0; -+ break; -+ } -+ fallthrough; -+ default: -+ if (r == 0) -+ r = -EPROTO; -+ break; -+ } -+ /* -+ * Some devices time out if they are powered on -+ * when already connected. They need a second -+ * reset. But only on the first attempt, -+ * lest we get into a time out/reset loop -+ */ -+ if (r == 0 || (r == -ETIMEDOUT && -+ retries == 0 && -+ udev->speed > USB_SPEED_FULL)) -+ break; - } -+ udev->descriptor.bMaxPacketSize0 = -+ buf->bMaxPacketSize0; -+ kfree(buf); - - retval = hub_port_reset(hub, port1, udev, delay, false); - if (retval < 0) /* error or disconnect */ -@@ -5018,13 +4982,14 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - retval = -ENODEV; - goto fail; - } -- if (maxp0 < 0) { -- if (maxp0 != -ENODEV) -+ if (r) { -+ if (r != -ENODEV) - dev_err(&udev->dev, "device descriptor read/64, error %d\n", -- maxp0); -- retval = maxp0; -+ r); -+ retval = -EMSGSIZE; - continue; - } -+#undef GET_DESCRIPTOR_BUFSIZE - } - - for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) { -@@ -5065,21 +5030,18 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - if (do_new_scheme) - break; - -- maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0); -- if (maxp0 < 0) { -- retval = maxp0; -+ retval = usb_get_device_descriptor(udev, 8); -+ if (retval < 8) { - if (retval != -ENODEV) - dev_err(&udev->dev, - "device descriptor read/8, error %d\n", - retval); -+ if (retval >= 0) -+ retval = -EMSGSIZE; - } else { - u32 delay; - -- if (!initial && maxp0 != udev->descriptor.bMaxPacketSize0) { -- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n"); -- retval = -ENODEV; -- goto fail; -- } -+ retval = 0; - - delay = udev->parent->hub_delay; - udev->hub_delay = min_t(u32, delay, -@@ -5098,62 +5060,48 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - goto fail; - - /* -- * Check the ep0 maxpacket guess and correct it if necessary. -- * maxp0 is the value stored in the device descriptor; -- * i is the value it encodes (logarithmic for SuperSpeed or greater). -+ * Some superspeed devices have finished the link training process -+ * and attached to a superspeed hub port, but the device descriptor -+ * got from those devices show they aren't superspeed devices. Warm -+ * reset the port attached by the devices can fix them. - */ -- i = maxp0; -- if (udev->speed >= USB_SPEED_SUPER) { -- if (maxp0 <= 16) -- i = 1 << maxp0; -- else -- i = 0; /* Invalid */ -- } -- if (usb_endpoint_maxp(&udev->ep0.desc) == i) { -- ; /* Initial ep0 maxpacket guess is right */ -- } else if (((udev->speed == USB_SPEED_FULL || -- udev->speed == USB_SPEED_HIGH) && -- (i == 8 || i == 16 || i == 32 || i == 64)) || -- (udev->speed >= USB_SPEED_SUPER && i > 0)) { -- /* Initial guess is wrong; use the descriptor's value */ -+ if ((udev->speed >= USB_SPEED_SUPER) && -+ (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { -+ dev_err(&udev->dev, "got a wrong device descriptor, " -+ "warm reset device\n"); -+ hub_port_reset(hub, port1, udev, -+ HUB_BH_RESET_TIME, true); -+ retval = -EINVAL; -+ goto fail; -+ } -+ -+ if (udev->descriptor.bMaxPacketSize0 == 0xff || -+ udev->speed >= USB_SPEED_SUPER) -+ i = 512; -+ else -+ i = udev->descriptor.bMaxPacketSize0; -+ if (usb_endpoint_maxp(&udev->ep0.desc) != i) { -+ if (udev->speed == USB_SPEED_LOW || -+ !(i == 8 || i == 16 || i == 32 || i == 64)) { -+ dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); -+ retval = -EMSGSIZE; -+ goto fail; -+ } - if (udev->speed == USB_SPEED_FULL) - dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); - else - dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i); - udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i); - usb_ep0_reinit(udev); -- } else { -- /* Initial guess is wrong and descriptor's value is invalid */ -- dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", maxp0); -- retval = -EMSGSIZE; -- goto fail; - } - -- descr = usb_get_device_descriptor(udev); -- if (IS_ERR(descr)) { -- retval = PTR_ERR(descr); -+ retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); -+ if (retval < (signed)sizeof(udev->descriptor)) { - if (retval != -ENODEV) - dev_err(&udev->dev, "device descriptor read/all, error %d\n", - retval); -- goto fail; -- } -- if (initial) -- udev->descriptor = *descr; -- else -- *dev_descr = *descr; -- kfree(descr); -- -- /* -- * Some superspeed devices have finished the link training process -- * and attached to a superspeed hub port, but the device descriptor -- * got from those devices show they aren't superspeed devices. Warm -- * reset the port attached by the devices can fix them. -- */ -- if ((udev->speed >= USB_SPEED_SUPER) && -- (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { -- dev_err(&udev->dev, "got a wrong device descriptor, warm reset device\n"); -- hub_port_reset(hub, port1, udev, HUB_BH_RESET_TIME, true); -- retval = -EINVAL; -+ if (retval >= 0) -+ retval = -ENOMSG; - goto fail; - } - -@@ -5179,7 +5127,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - hub_port_disable(hub, port1, 0); - update_devnum(udev, devnum); /* for disconnect processing */ - } -- kfree(buf); - return retval; - } - -@@ -5260,7 +5207,7 @@ hub_power_remaining(struct usb_hub *hub) - - - static int descriptors_changed(struct usb_device *udev, -- struct usb_device_descriptor *new_device_descriptor, -+ struct usb_device_descriptor *old_device_descriptor, - struct usb_host_bos *old_bos) - { - int changed = 0; -@@ -5271,8 +5218,8 @@ static int descriptors_changed(struct usb_device *udev, - int length; - char *buf; - -- if (memcmp(&udev->descriptor, new_device_descriptor, -- sizeof(*new_device_descriptor)) != 0) -+ if (memcmp(&udev->descriptor, old_device_descriptor, -+ sizeof(*old_device_descriptor)) != 0) - return 1; - - if ((old_bos && !udev->bos) || (!old_bos && udev->bos)) -@@ -5449,7 +5396,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - } - - /* reset (non-USB 3.0 devices) and get descriptor */ -- status = hub_port_init(hub, udev, port1, i, NULL); -+ status = hub_port_init(hub, udev, port1, i); - if (status < 0) - goto loop; - -@@ -5596,8 +5543,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, - { - struct usb_port *port_dev = hub->ports[port1 - 1]; - struct usb_device *udev = port_dev->child; -- struct usb_device_descriptor *descr; -+ struct usb_device_descriptor descriptor; - int status = -ENODEV; -+ int retval; - - dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus, - portchange, portspeed(hub, portstatus)); -@@ -5624,20 +5572,23 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, - * changed device descriptors before resuscitating the - * device. - */ -- descr = usb_get_device_descriptor(udev); -- if (IS_ERR(descr)) { -+ descriptor = udev->descriptor; -+ retval = usb_get_device_descriptor(udev, -+ sizeof(udev->descriptor)); -+ if (retval < 0) { - dev_dbg(&udev->dev, -- "can't read device descriptor %ld\n", -- PTR_ERR(descr)); -+ "can't read device descriptor %d\n", -+ retval); - } else { -- if (descriptors_changed(udev, descr, -+ if (descriptors_changed(udev, &descriptor, - udev->bos)) { - dev_dbg(&udev->dev, - "device descriptor has changed\n"); -+ /* for disconnect() calls */ -+ udev->descriptor = descriptor; - } else { - status = 0; /* Nothing to do */ - } -- kfree(descr); - } - #ifdef CONFIG_PM - } else if (udev->state == USB_STATE_SUSPENDED && -@@ -6094,7 +6045,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) - struct usb_device *parent_hdev = udev->parent; - struct usb_hub *parent_hub; - struct usb_hcd *hcd = bus_to_hcd(udev->bus); -- struct usb_device_descriptor descriptor; -+ struct usb_device_descriptor descriptor = udev->descriptor; - struct usb_host_bos *bos; - int i, j, ret = 0; - int port1 = udev->portnum; -@@ -6130,7 +6081,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) - /* ep0 maxpacket size may change; let the HCD know about it. - * Other endpoints will be handled by re-enumeration. */ - usb_ep0_reinit(udev); -- ret = hub_port_init(parent_hub, udev, port1, i, &descriptor); -+ ret = hub_port_init(parent_hub, udev, port1, i); - if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) - break; - } -@@ -6142,6 +6093,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) - /* Device might have changed firmware (DFU or similar) */ - if (descriptors_changed(udev, &descriptor, bos)) { - dev_info(&udev->dev, "device firmware changed\n"); -+ udev->descriptor = descriptor; /* for disconnect() calls */ - goto re_enumerate; - } - -diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index d2b2787be4092..8bc0168e3af56 100644 ---- a/drivers/usb/core/message.c -+++ b/drivers/usb/core/message.c -@@ -1041,35 +1041,40 @@ char *usb_cache_string(struct usb_device *udev, int index) - EXPORT_SYMBOL_GPL(usb_cache_string); - - /* -- * usb_get_device_descriptor - read the device descriptor -- * @udev: the device whose device descriptor should be read -+ * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) -+ * @dev: the device whose device descriptor is being updated -+ * @size: how much of the descriptor to read - * - * Context: task context, might sleep. - * -+ * Updates the copy of the device descriptor stored in the device structure, -+ * which dedicates space for this purpose. -+ * - * Not exported, only for use by the core. If drivers really want to read - * the device descriptor directly, they can call usb_get_descriptor() with - * type = USB_DT_DEVICE and index = 0. - * -- * Returns: a pointer to a dynamically allocated usb_device_descriptor -- * structure (which the caller must deallocate), or an ERR_PTR value. -+ * This call is synchronous, and may not be used in an interrupt context. -+ * -+ * Return: The number of bytes received on success, or else the status code -+ * returned by the underlying usb_control_msg() call. - */ --struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev) -+int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) - { - struct usb_device_descriptor *desc; - int ret; - -+ if (size > sizeof(*desc)) -+ return -EINVAL; - desc = kmalloc(sizeof(*desc), GFP_NOIO); - if (!desc) -- return ERR_PTR(-ENOMEM); -- -- ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc)); -- if (ret == sizeof(*desc)) -- return desc; -+ return -ENOMEM; - -+ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); - if (ret >= 0) -- ret = -EMSGSIZE; -+ memcpy(&dev->descriptor, desc, size); - kfree(desc); -- return ERR_PTR(ret); -+ return ret; - } - - /* -diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h -index b8324ea05b20f..82fcef57ce3a9 100644 ---- a/drivers/usb/core/usb.h -+++ b/drivers/usb/core/usb.h -@@ -43,8 +43,8 @@ extern bool usb_endpoint_is_ignored(struct usb_device *udev, - struct usb_endpoint_descriptor *epd); - extern int usb_remove_device(struct usb_device *udev); - --extern struct usb_device_descriptor *usb_get_device_descriptor( -- struct usb_device *udev); -+extern int usb_get_device_descriptor(struct usb_device *dev, -+ unsigned int size); - extern int usb_set_isoch_delay(struct usb_device *dev); - extern int usb_get_bos_descriptor(struct usb_device *dev); - extern void usb_release_bos_descriptor(struct usb_device *dev);