From 50b3a42d82f07083075f41a4391c6f20bb4aed7b Mon Sep 17 00:00:00 2001 From: Max Krummenacher Date: Tue, 20 Feb 2024 17:19:55 +0100 Subject: Revert "USB: core: Unite old scheme and new scheme descriptor reads" This reverts commit 56c49a3328e988c82981f4d098be22695d46fcf3. Downstream NXP and stable have deviated to far, do not pull this in. Signed-off-by: Max Krummenacher --- drivers/usb/core/hub.c | 173 ++++++++++++++++++++++--------------------------- 1 file changed, 79 insertions(+), 94 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index fa8683c448c9..2295d69b4cd2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4666,67 +4666,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 255: - 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. @@ -4751,12 +4690,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; - int maxp0; - struct usb_device_descriptor *buf; - - 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) @@ -4871,6 +4804,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { if (do_new_scheme) { + struct usb_device_descriptor *buf; + int r = 0; + retval = hub_enable_device(udev); if (retval < 0) { dev_err(&udev->dev, @@ -4879,8 +4815,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); +#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 */ @@ -4891,13 +4871,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 } /* @@ -4943,17 +4924,19 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, break; } - /* !do_new_scheme || wusb */ - 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; + retval = 0; + delay = udev->parent->hub_delay; udev->hub_delay = min_t(u32, delay, USB_TP_TRANSMISSION_DELAY_MAX); @@ -4970,10 +4953,27 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, if (retval) goto fail; - if (maxp0 == 0xff || udev->speed >= USB_SPEED_SUPER) + /* + * 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; + goto fail; + } + + if (udev->descriptor.bMaxPacketSize0 == 0xff || + udev->speed >= USB_SPEED_SUPER) i = 512; else - i = maxp0; + 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)) { @@ -4999,20 +4999,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; } - /* - * 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; - goto fail; - } - usb_detect_quirks(udev); if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { @@ -5033,7 +5019,6 @@ fail: hub_port_disable(hub, port1, 0); update_devnum(udev, devnum); /* for disconnect processing */ } - kfree(buf); return retval; } -- cgit v1.2.3