I happened across a problem that came up with modified OHCI root hub code ... looks like hub probing has misbehaved for a long time, this might affect other configs too.
Does this patch look good to you? If so, please merge. - Dave
Fix the khubd probe logic so that when khubd wakes up, it will actually look at all ports on the new hub. This resolved a root hub enumeration issue. The fix uses a new routine centralizing the logic to make khubd look at a given hub ... two working copies, one (previously) not. Signed-off-by: David Brownell <[EMAIL PROTECTED]> --- 1.141/drivers/usb/core/hub.c Thu Aug 26 09:05:20 2004 +++ edited/drivers/usb/core/hub.c Tue Aug 31 19:49:43 2004 @@ -39,12 +39,13 @@ /* Protect struct usb_device state and children members */ static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED; -/* Wakes up khubd */ +/* khubd's worklist and its lock */ static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; - static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ +/* Wakes up khubd */ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); + static pid_t khubd_pid = 0; /* PID of khubd */ static DECLARE_COMPLETION(khubd_exited); @@ -226,6 +227,19 @@ data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); } +static void kick_khubd(struct usb_hub *hub) +{ + unsigned long flags; + + spin_lock_irqsave(&hub_event_lock, flags); + if (list_empty(&hub->event_list)) { + list_add_tail(&hub->event_list, &hub_event_list); + wake_up(&khubd_wait); + } + spin_unlock_irqrestore(&hub_event_lock, flags); +} + + /* completion function, fires on port status changes and various faults */ static void hub_irq(struct urb *urb, struct pt_regs *regs) { @@ -261,12 +275,7 @@ hub->nerrors = 0; /* Something happened, let khubd figure it out */ - spin_lock(&hub_event_lock); - if (list_empty(&hub->event_list)) { - list_add_tail(&hub->event_list, &hub_event_list); - wake_up(&khubd_wait); - } - spin_unlock(&hub_event_lock); + kick_khubd(hub); resubmit: if (hub->quiescing) @@ -579,6 +588,9 @@ dev_dbg(hub_dev, "%sover-current condition exists\n", (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); + /* scan all ports ASAP on new hubs */ + hub->change_bits[0] = ~0; + /* Start the interrupt endpoint */ pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); @@ -604,7 +616,7 @@ } /* Wake up khubd */ - wake_up(&khubd_wait); + kick_khubd(hub); /* maybe start cycling the hub leds */ if (hub->has_indicators && blinkenlights) { @@ -2813,13 +2825,7 @@ hub = usb_get_intfdata(parent->actconfig->interface[0]); set_bit(port, hub->change_bits); - - spin_lock_irq(&hub_event_lock); - if (list_empty(&hub->event_list)) { - list_add_tail(&hub->event_list, &hub_event_list); - wake_up(&khubd_wait); - } - spin_unlock_irq(&hub_event_lock); + kick_khubd(hub); return -ENODEV; }