On Mon, 28 Oct 2013, Prasad Koya wrote:

> Hi
> 
> I tried resetting usb device when it gets ETIMEDOUT during get
> descriptor. On second retry, I don't see timeout. Please see this
> patch:
> 
> Index: linux-3.4/drivers/usb/core/hub.c
> ===================================================================
> --- linux-3.4.orig/drivers/usb/core/hub.c
> +++ linux-3.4/drivers/usb/core/hub.c
> @@ -3213,6 +3213,14 @@ hub_port_init (struct usb_hub *hub, stru
>   r = -EPROTO;
>   break;
>   }
> +
> +                                if (r == -ETIMEDOUT) {
> + r = usb_reset_device(hdev);
> + if (r) {
> + dev_dbg(&udev->dev, "failed to reset usb %d\n", r);
> + }
> + }
> +
>   if (r == 0)
>   break;
>   }

The patch has been whitespace-damaged.  Besides, what is the point of 
calling usb_reset_device()?  You might as well just break out of the 
loop, because just after the end of the loop there is a call to 
hub_port_reset().

In addition, you run the risk of infinite recursion since
usb_reset_device() calls usb_reset_and_verify_device(), which calls
hub_port_init().

Finally, the patch is wrong because it never does carry out the 
Get-Device-Descriptor(64) request.  That means it won't work with a 
full-speed device if the ep0 maxpacket size is smaller than 64.

What you could do instead is this:

Index: usb-3.12/drivers/usb/core/hub.c
===================================================================
--- usb-3.12.orig/drivers/usb/core/hub.c
+++ usb-3.12/drivers/usb/core/hub.c
@@ -4106,11 +4106,12 @@ hub_port_init (struct usb_hub *hub, stru
                                                r = -EPROTO;
                                        break;
                                }
-                               if (r == 0)
+                               if (r == 0) {
+                                       udev->descriptor.bMaxPacketSize0 =
+                                                       buf->bMaxPacketSize0;
                                        break;
+                               }
                        }
-                       udev->descriptor.bMaxPacketSize0 =
-                                       buf->bMaxPacketSize0;
                        kfree(buf);
 
                        retval = hub_port_reset(hub, port1, udev, delay, false);
@@ -4126,8 +4127,15 @@ hub_port_init (struct usb_hub *hub, stru
                                if (r != -ENODEV)
                                        dev_err(&udev->dev, "device descriptor 
read/64, error %d\n",
                                                        r);
-                               retval = -EMSGSIZE;
-                               continue;
+
+                               /*
+                                * For every speed except full speed, the
+                                * ep0 maxpacket size is already known.
+                                */
+                               if (udev->speed == USB_SPEED_FULL) {
+                                       retval = -EMSGSIZE;
+                                       continue;
+                               }
                        }
 #undef GET_DESCRIPTOR_BUFSIZE
                }

Alan Stern

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

Reply via email to