diff --git a/buildroot-external/board/raspberrypi/patches/linux/0005-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch b/buildroot-external/board/raspberrypi/patches/linux/0005-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch deleted file mode 100644 index 0a9221b3a40..00000000000 --- a/buildroot-external/board/raspberrypi/patches/linux/0005-Revert-USB-core-changes-causing-issues-with-Z-Wave.m.patch +++ /dev/null @@ -1,650 +0,0 @@ -From f9037c133775498d0ff2f035a957ce4f294e4e81 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 12b6dfeaf658c..d895f6ebbc400 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -958,7 +958,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; - -@@ -970,16 +969,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 1ba3feb5e1900..ef1d63537a9b7 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4742,67 +4742,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. -@@ -4812,17 +4751,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); -@@ -4834,13 +4766,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) -@@ -4873,31 +4798,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); -@@ -4917,24 +4842,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? -@@ -4958,6 +4881,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, -@@ -4966,14 +4892,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 */ -@@ -4984,13 +4948,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) { -@@ -5031,21 +4996,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, -@@ -5064,62 +5026,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; - } - -@@ -5145,7 +5093,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; - } - -@@ -5226,7 +5173,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; -@@ -5237,8 +5184,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)) -@@ -5415,7 +5362,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; - -@@ -5562,8 +5509,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)); -@@ -5590,20 +5538,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 && -@@ -6060,7 +6011,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; -@@ -6096,7 +6047,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; - } -@@ -6108,6 +6059,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 077dfe48d01c1..0d2bfc909019b 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 60363153fc3f3..69ca59841083b 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); 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);