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