diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 28664eb7f555..ec6c97dadbe4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1667,7 +1667,6 @@ void usb_disconnect(struct usb_device **pdev) | |||
1667 | { | 1667 | { |
1668 | struct usb_device *udev = *pdev; | 1668 | struct usb_device *udev = *pdev; |
1669 | int i; | 1669 | int i; |
1670 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | ||
1671 | 1670 | ||
1672 | /* mark the device as inactive, so any further urb submissions for | 1671 | /* mark the device as inactive, so any further urb submissions for |
1673 | * this device (and any of its children) will fail immediately. | 1672 | * this device (and any of its children) will fail immediately. |
@@ -1690,9 +1689,7 @@ void usb_disconnect(struct usb_device **pdev) | |||
1690 | * so that the hardware is now fully quiesced. | 1689 | * so that the hardware is now fully quiesced. |
1691 | */ | 1690 | */ |
1692 | dev_dbg (&udev->dev, "unregistering device\n"); | 1691 | dev_dbg (&udev->dev, "unregistering device\n"); |
1693 | mutex_lock(hcd->bandwidth_mutex); | ||
1694 | usb_disable_device(udev, 0); | 1692 | usb_disable_device(udev, 0); |
1695 | mutex_unlock(hcd->bandwidth_mutex); | ||
1696 | usb_hcd_synchronize_unlinks(udev); | 1693 | usb_hcd_synchronize_unlinks(udev); |
1697 | 1694 | ||
1698 | usb_remove_ep_devs(&udev->ep0); | 1695 | usb_remove_ep_devs(&udev->ep0); |
@@ -3163,6 +3160,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
3163 | if (retval) | 3160 | if (retval) |
3164 | goto fail; | 3161 | goto fail; |
3165 | 3162 | ||
3163 | /* | ||
3164 | * Some superspeed devices have finished the link training process | ||
3165 | * and attached to a superspeed hub port, but the device descriptor | ||
3166 | * got from those devices show they aren't superspeed devices. Warm | ||
3167 | * reset the port attached by the devices can fix them. | ||
3168 | */ | ||
3169 | if ((udev->speed == USB_SPEED_SUPER) && | ||
3170 | (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { | ||
3171 | dev_err(&udev->dev, "got a wrong device descriptor, " | ||
3172 | "warm reset device\n"); | ||
3173 | hub_port_reset(hub, port1, udev, | ||
3174 | HUB_BH_RESET_TIME, true); | ||
3175 | retval = -EINVAL; | ||
3176 | goto fail; | ||
3177 | } | ||
3178 | |||
3166 | if (udev->descriptor.bMaxPacketSize0 == 0xff || | 3179 | if (udev->descriptor.bMaxPacketSize0 == 0xff || |
3167 | udev->speed == USB_SPEED_SUPER) | 3180 | udev->speed == USB_SPEED_SUPER) |
3168 | i = 512; | 3181 | i = 512; |