On Thu, 27 Feb 2014 oli...@neukum.org wrote:

> 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 ==

You shouldn't need all this stuff.  Just break out of the j loop early 
if r is -ETIMEDOUT.  That is, a few lines below all this, do

-                               if (r == 0)
+                               if (r == 0 || r == -EDTIMEDOUT)
                                        break;

The code that follows already does a reset.

Alan Stern

--
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