summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2024-02-20 17:19:55 +0100
committerMax Krummenacher <max.krummenacher@toradex.com>2024-02-20 17:19:55 +0100
commit50b3a42d82f07083075f41a4391c6f20bb4aed7b (patch)
tree89a77378daf759a5c2d56dd19e3c5fb44afa6495
parentcdcf46014f5ca1349325c51ae3a49d2a941d5f27 (diff)
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 <max.krummenacher@toradex.com>
-rw-r--r--drivers/usb/core/hub.c173
1 files 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;
}