Greg:

Here's another "cleanup" type patch, most of which was written by David
Brownell.  It causes the hub driver to retry a couple of different types
of transfers if they timeout (which seems to help with some flakey
devices), and it adds some error checking for the ep0 maxpacket value sent
by the device.

Alan Stern



Sent-by: David Brownell <[EMAIL PROTECTED]>
Signed-off-by: Alan Stern <[EMAIL PROTECTED]>

===== drivers/usb/core/hub.c 1.214 vs edited =====
--- 1.214/drivers/usb/core/hub.c        2004-11-15 12:27:16 -05:00
+++ edited/drivers/usb/core/hub.c       2004-11-22 09:27:55 -05:00
@@ -240,15 +240,24 @@
                schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
 }
 
+/* use a short timeout for hub/port status fetches */
+#define        USB_STS_TIMEOUT         1
+#define        USB_STS_RETRIES         5
+
 /*
  * USB 2.0 spec Section 11.24.2.6
  */
 static int get_hub_status(struct usb_device *hdev,
                struct usb_hub_status *data)
 {
-       return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
-               USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
-               data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT);
+       int i, status = -ETIMEDOUT;
+
+       for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
+               status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+                       USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+                       data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+       }
+       return status;
 }
 
 /*
@@ -257,9 +266,14 @@
 static int get_port_status(struct usb_device *hdev, int port,
                struct usb_port_status *data)
 {
-       return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
-               USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
-               data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT);
+       int i, status = -ETIMEDOUT;
+
+       for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
+               status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+                       USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
+                       data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+       }
+       return status;
 }
 
 static void kick_khubd(struct usb_hub *hub)
@@ -2161,6 +2175,7 @@
        for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
                if (USE_NEW_SCHEME(retry_counter)) {
                        struct usb_device_descriptor *buf;
+                       int r = 0;
 
 #define GET_DESCRIPTOR_BUFSIZE 64
                        buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
@@ -2174,13 +2189,20 @@
                         * so that recalcitrant full-speed devices with
                         * 8- or 16-byte ep0-maxpackets won't slow things
                         * down tremendously by NAKing the unexpectedly
-                        * early status stage.
+                        * early status stage.  Also, retry on length 0
+                        * or stall; some devices are flakey.
                         */
-                       j = usb_control_msg(udev, usb_rcvaddr0pipe(),
+                       for (j = 0; j < 3; ++j) {
+                               r = usb_control_msg(udev, usb_rcvaddr0pipe(),
                                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                                        USB_DT_DEVICE << 8, 0,
                                        buf, GET_DESCRIPTOR_BUFSIZE,
                                        (i ? HZ * USB_CTRL_GET_TIMEOUT : HZ));
+                               if (r == 0 || r == -EPIPE)
+                                       continue;
+                               if (r < 0)
+                                       break;
+                       }
                        udev->descriptor.bMaxPacketSize0 =
                                        buf->bMaxPacketSize0;
                        kfree(buf);
@@ -2197,7 +2219,7 @@
                        if (udev->descriptor.bMaxPacketSize0 == 0) {
                                dev_err(&udev->dev, "device descriptor "
                                                "read/%s, error %d\n",
-                                               "64", j);
+                                               "64", r);
                                retval = -EMSGSIZE;
                                continue;
                        }
@@ -2240,9 +2262,14 @@
        if (retval)
                goto fail;
 
-       /* Should we verify that the value is valid? */
        i = udev->descriptor.bMaxPacketSize0;
        if (udev->epmaxpacketin[0] != i) {
+               if (udev->speed != USB_SPEED_FULL ||
+                               !(i == 8 || i == 16 || i == 32 || i == 64)) {
+                       dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
+                       retval = -EMSGSIZE;
+                       goto fail;
+               }
                dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
                usb_disable_endpoint(udev, 0 + USB_DIR_IN);
                usb_disable_endpoint(udev, 0 + USB_DIR_OUT);



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now. 
http://productguide.itmanagersjournal.com/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to