Browse Source

[usb] Allow additional settling time for out-of-spec hubs

Some hubs (e.g. the Avocent Corp. Virtual Hub on a Lenovo x3550
Integrated Management Module) have been observed to require more than
the standard 200ms for ports to stabilise, with the result that
devices appear to disconnect and immediately reconnect during the
initial bus enumeration.

Work around this problem by allowing specific hubs an extra 500ms of
settling time.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
53ba5936b5
2 changed files with 19 additions and 0 deletions
  1. 11
    0
      src/drivers/usb/usbhub.c
  2. 8
    0
      src/drivers/usb/usbhub.h

+ 11
- 0
src/drivers/usb/usbhub.c View File

@@ -155,6 +155,10 @@ static int hub_open ( struct usb_hub *hub ) {
155 155
 	/* Refill interrupt ring */
156 156
 	hub_refill ( hubdev );
157 157
 
158
+	/* Delay to allow ports to stabilise on out-of-spec hubs */
159
+	if ( hubdev->flags & USB_HUB_SLOW_START )
160
+		mdelay ( USB_HUB_SLOW_START_DELAY_MS );
161
+
158 162
 	return 0;
159 163
 
160 164
 	usb_endpoint_close ( &hubdev->intr );
@@ -410,6 +414,7 @@ static int hub_probe ( struct usb_function *func,
410 414
 	hubdev->usb = usb;
411 415
 	hubdev->features =
412 416
 		( enhanced ? USB_HUB_FEATURES_ENHANCED : USB_HUB_FEATURES );
417
+	hubdev->flags = func->id->driver_data;
413 418
 	usb_endpoint_init ( &hubdev->intr, usb, &usb_hub_intr_operations );
414 419
 	usb_refill_init ( &hubdev->intr, 0, USB_HUB_INTR_FILL );
415 420
 	process_init_stopped ( &hubdev->refill, &hub_refill_desc, NULL );
@@ -517,6 +522,12 @@ static void hub_remove ( struct usb_function *func ) {
517 522
 
518 523
 /** USB hub device IDs */
519 524
 static struct usb_device_id hub_ids[] = {
525
+	{
526
+		.name = "avocent-hub",
527
+		.vendor = 0x0624,
528
+		.product = 0x0248,
529
+		.driver_data = USB_HUB_SLOW_START,
530
+	},
520 531
 	{
521 532
 		.name = "hub",
522 533
 		.vendor = USB_ANY_ID,

+ 8
- 0
src/drivers/usb/usbhub.h View File

@@ -257,6 +257,8 @@ struct usb_hub_device {
257 257
 	struct usb_hub *hub;
258 258
 	/** Features */
259 259
 	unsigned int features;
260
+	/** Flags */
261
+	unsigned int flags;
260 262
 
261 263
 	/** Interrupt endpoint */
262 264
 	struct usb_endpoint intr;
@@ -264,6 +266,12 @@ struct usb_hub_device {
264 266
 	struct process refill;
265 267
 };
266 268
 
269
+/** Hub requires additional settling delay */
270
+#define USB_HUB_SLOW_START 0x0001
271
+
272
+/** Additional setting delay for out-of-spec hubs */
273
+#define USB_HUB_SLOW_START_DELAY_MS 500
274
+
267 275
 /** Interrupt ring fill level
268 276
  *
269 277
  * This is a policy decision.

Loading…
Cancel
Save