[PATCH 2/3] USB: hub: handle -ETIMEDOUT during enumeration

2014-02-27 Thread oliver
From: Oliver Neukum 

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 
---
 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;
+   boolsecond_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


Re: [PATCH 2/3] USB: hub: handle -ETIMEDOUT during enumeration

2014-02-27 Thread Alan Stern
On Thu, 27 Feb 2014 oli...@neukum.org wrote:

> From: Oliver Neukum 
> 
> 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 
> ---
>  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;
> + boolsecond_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