Am Dienstag, 27. Februar 2007 17:03 schrieb Alan Stern:

> Oliver, I've noticed in the past that khubd tries too hard to enumerate a
> new connection.  The new scheme and the old scheme are both tried twice,
> and each try has two attempts to read the device descriptor, where each 
> attempt can loop twice, each loop with up to three calls to 
> usb_control_msg() and a device reset, with timeouts as long as 1 second.
> 
> In really bad cases this can tie things up for close to a minute.  We
> ought to be able to do better.  Some of the loops should be eliminated and
> some of the timeouts decreased.

Something like this?

        Regards
                Oliver

--- a/drivers/usb/core/hub.c    2007-03-01 11:17:53.000000000 +0100
+++ b/drivers/usb/core/hub.c    2007-03-01 12:13:08.000000000 +0100
@@ -70,6 +70,7 @@
 
        unsigned                has_indicators:1;
        u8                      indicator[USB_MAXCHILDREN];
+       unsigned long           last_failed[USB_MAXCHILDREN];
        struct delayed_work     leds;
 };
 
@@ -2419,7 +2420,7 @@
        struct usb_device *hdev = hub->hdev;
        struct device *hub_dev = hub->intfdev;
        u16 wHubCharacteristics = 
le16_to_cpu(hub->descriptor->wHubCharacteristics);
-       int status, i;
+       int status, i, retries;
  
        dev_dbg (hub_dev,
                "port %d, status %04x, change %04x, %s\n",
@@ -2447,7 +2448,7 @@
                        dev_err (hub_dev,
                                "connect-debounce failed, port %d disabled\n",
                                port1);
-                       goto done;
+                       goto failed;
                }
                portstatus = status;
        }
@@ -2461,7 +2462,7 @@
                        set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
  
                if (portstatus & USB_PORT_STAT_ENABLE)
-                       goto done;
+                       goto failed;
                return;
        }
 
@@ -2478,7 +2479,11 @@
        }
 #endif
 
-       for (i = 0; i < SET_CONFIG_TRIES; i++) {
+       /* we give short shrift if we had a failure within the last 2 hours */
+       retries = hub->last_failed[port1 - 1] &&
+               time_after(hub->last_failed[port1 - 1] + HZ * 60 * 60 * 2, 
jiffies) ?
+               1 : SET_CONFIG_TRIES;
+       for (i = 0; i < retries; i++) {
                struct usb_device *udev;
 
                /* reallocate for each attempt, since references
@@ -2580,6 +2585,7 @@
                if (status)
                        dev_dbg(hub_dev, "%dmA power budget left\n", status);
 
+               hub->last_failed[port1 - 1] = 0; /*all former errors forgiven */
                return;
 
 loop_disable:
@@ -2591,7 +2597,9 @@
                if (status == -ENOTCONN)
                        break;
        }
- 
+
+failed:
+       hub->last_failed[port1 - 1] = jiffies;
 done:
        hub_port_disable(hub, port1, 1);
 }

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to