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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel