summaryrefslogtreecommitdiffstats
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/usb/usbhub.c11
-rw-r--r--src/drivers/usb/usbhub.h8
2 files changed, 19 insertions, 0 deletions
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 );
@@ -518,6 +523,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,
.product = 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.