aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorElric Fu <elricfu1@gmail.com>2012-03-26 09:16:02 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-04-11 11:28:58 -0400
commitd8aec3dbdfd02627e198e7956ab4aaeba2a349fa (patch)
treede495a5bbd9f0399f3673ee9b00d69543a72630c /drivers/usb/core/hub.c
parentc7713e736526d8c9f6f87716fb90562a8ffaff2c (diff)
USB: fix bug of device descriptor got from superspeed device
When the Seagate Goflex USB3.0 device is attached to VIA xHCI host, sometimes the device will downgrade mode to high speed. By the USB analyzer, I found the device finished the link training process and worked at superspeed mode. But the device descriptor got from the device shows the device works at 2.1. It is very strange and seems like the device controller of Seagate Goflex has a little confusion. The first 8 bytes of device descriptor should be: 12 01 00 03 00 00 00 09 But the first 8 bytes of wrong device descriptor are: 12 01 10 02 00 00 00 40 The wrong device descriptor caused the initialization of mass storage failed. After a while, the device would be recognized as a high speed device and works fine. This patch will warm reset the device to fix the issue after finding the bcdUSB field of device descriptor isn't 0x0300 but the speed mode of device is superspeed. This patch should be backported to kernels as old as 3.2, or ones that contain the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm reset logic". Signed-off-by: Elric Fu <elricfu1@gmail.com> Acked-by: Andiry Xu <Andiry.Xu@amd.com> Acked-by: Sergei Shtylyov <sshtylyov@mvista.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 28664eb7f555..a2aa9d652c67 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,
3163 if (retval) 3163 if (retval)
3164 goto fail; 3164 goto fail;
3165 3165
3166 /*
3167 * Some superspeed devices have finished the link training process
3168 * and attached to a superspeed hub port, but the device descriptor
3169 * got from those devices show they aren't superspeed devices. Warm
3170 * reset the port attached by the devices can fix them.
3171 */
3172 if ((udev->speed == USB_SPEED_SUPER) &&
3173 (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
3174 dev_err(&udev->dev, "got a wrong device descriptor, "
3175 "warm reset device\n");
3176 hub_port_reset(hub, port1, udev,
3177 HUB_BH_RESET_TIME, true);
3178 retval = -EINVAL;
3179 goto fail;
3180 }
3181
3166 if (udev->descriptor.bMaxPacketSize0 == 0xff || 3182 if (udev->descriptor.bMaxPacketSize0 == 0xff ||
3167 udev->speed == USB_SPEED_SUPER) 3183 udev->speed == USB_SPEED_SUPER)
3168 i = 512; 3184 i = 512;