diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 16 | 
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 28664eb7f55..a2aa9d652c6 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;  |