diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 28664eb7f5554cfe07f017d9d5e24be65671e85b..a2aa9d652c672c42ca0c6ba68fc0fbfb4907e32f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3163,6 +3163,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, if (retval) 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; + } + if (udev->descriptor.bMaxPacketSize0 == 0xff || udev->speed == USB_SPEED_SUPER) i = 512;