From: Oliver Neukum <oneu...@suse.de>

I have a device that times out if enumerated after being
switched on while connected. Increasing timeouts or retries
doesn't help. The device needs an additional reset.

Signed-off-by: Oliver Neukum <oli...@neukum.org>
---
 drivers/usb/core/hub.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3489bf1..cf992de 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4005,6 +4005,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device 
*udev, int port1,
        enum usb_device_speed   oldspeed = udev->speed;
        const char              *speed;
        int                     devnum = udev->devnum;
+       bool                    second_reset = false;
 
        /* root hub ports have a slightly longer reset period
         * (from USB 2.0 spec, section 7.1.7.5)
@@ -4136,6 +4137,20 @@ hub_port_init (struct usb_hub *hub, struct usb_device 
*udev, int port1,
                                        USB_DT_DEVICE << 8, 0,
                                        buf, GET_DESCRIPTOR_BUFSIZE,
                                        initial_descriptor_timeout);
+
+                               /*
+                                * Some devices time out if they are powered on
+                                * when already connected. They need a second
+                                * reset.
+                                */
+                               if (r == -ETIMEDOUT && !second_reset) {
+                                       retval = hub_port_reset(hub, port1, 
udev, delay, false);
+                                       second_reset = true;
+                                       if (retval < 0)
+                                               dev_err(&udev->dev,
+                                                       "recovery from timeout 
failed, error %d\n",
+                                                       retval);
+                               }
                                switch (buf->bMaxPacketSize0) {
                                case 8: case 16: case 32: case 64: case 255:
                                        if (buf->bDescriptorType ==
-- 
1.8.4.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to