diff --git a/src/drivers/usb/usbhub.c b/src/drivers/usb/usbhub.c index a3e7bc00c..7095fc31b 100644 --- a/src/drivers/usb/usbhub.c +++ b/src/drivers/usb/usbhub.c @@ -155,6 +155,10 @@ static int hub_open ( struct usb_hub *hub ) { /* Refill interrupt ring */ hub_refill ( hubdev ); + /* Delay to allow ports to stabilise on out-of-spec hubs */ + if ( hubdev->flags & USB_HUB_SLOW_START ) + mdelay ( USB_HUB_SLOW_START_DELAY_MS ); + return 0; usb_endpoint_close ( &hubdev->intr ); @@ -410,6 +414,7 @@ static int hub_probe ( struct usb_function *func, hubdev->usb = usb; hubdev->features = ( enhanced ? USB_HUB_FEATURES_ENHANCED : USB_HUB_FEATURES ); + hubdev->flags = func->id->driver_data; usb_endpoint_init ( &hubdev->intr, usb, &usb_hub_intr_operations ); usb_refill_init ( &hubdev->intr, 0, USB_HUB_INTR_FILL ); process_init_stopped ( &hubdev->refill, &hub_refill_desc, NULL ); @@ -517,6 +522,12 @@ static void hub_remove ( struct usb_function *func ) { /** USB hub device IDs */ static struct usb_device_id hub_ids[] = { + { + .name = "avocent-hub", + .vendor = 0x0624, + .product = 0x0248, + .driver_data = USB_HUB_SLOW_START, + }, { .name = "hub", .vendor = USB_ANY_ID, diff --git a/src/drivers/usb/usbhub.h b/src/drivers/usb/usbhub.h index d7d8f9610..a5f123acc 100644 --- a/src/drivers/usb/usbhub.h +++ b/src/drivers/usb/usbhub.h @@ -257,6 +257,8 @@ struct usb_hub_device { struct usb_hub *hub; /** Features */ unsigned int features; + /** Flags */ + unsigned int flags; /** Interrupt endpoint */ struct usb_endpoint intr; @@ -264,6 +266,12 @@ struct usb_hub_device { struct process refill; }; +/** Hub requires additional settling delay */ +#define USB_HUB_SLOW_START 0x0001 + +/** Additional setting delay for out-of-spec hubs */ +#define USB_HUB_SLOW_START_DELAY_MS 500 + /** Interrupt ring fill level * * This is a policy decision.