From 1bbda613eb0632724a615dd16890f9f6a0046ed1 Mon Sep 17 00:00:00 2001 From: Ian Dowse Date: Tue, 23 May 2006 01:27:23 +0000 Subject: [PATCH] When usb_event_thread() first starts, wait significantly longer before starting exploring (4 seconds), and extend the wait period if new USB buses are attached while waiting. This works around a problem seen when there is more than one EHCI controller in the system and you kldload usb.ko after the system has booted. The problem is that usb.ko contains 3 separate PCI drivers which get initialised one by one (uhci, ohci, ehci), and when each driver is initialised, all PCI buses are re-probed after just the addition of that driver. This means that there can be a significant delay between the attaching of a companion controller and the subsequent EHCI attach, so it is possible for the companion controller's USB 1.x bus to be scanned before the EHCI driver gets a chance to check if there is really a USB 2.x device connected. --- sys/dev/usb/usb.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index dc89d9f532e..959d8661fa8 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -403,6 +403,7 @@ usb_rem_task(usbd_device_handle dev, struct usb_task *task) void usb_event_thread(void *arg) { + static int newthread_wchan; struct usb_softc *sc = arg; #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 @@ -414,12 +415,20 @@ usb_event_thread(void *arg) /* * In case this controller is a companion controller to an * EHCI controller we need to wait until the EHCI controller - * has grabbed the port. - * XXX It would be nicer to do this with a tsleep(), but I don't - * know how to synchronize the creation of the threads so it - * will work. + * has grabbed the port. What we do here is wait until no new + * USB threads have been created in a while. XXX we actually + * just want to wait for the PCI slot to be fully scanned. + * + * Note that when you `kldload usb' it actually attaches the + * devices in order that the drivers appear in the kld, not the + * normal PCI order, since the addition of each driver within + * usb.ko (ohci, ehci etc.) causes a separate PCI bus re-scan. */ - usb_delay_ms(sc->sc_bus, 500); + wakeup(&newthread_wchan); + for (;;) { + if (tsleep(&newthread_wchan , PWAIT, "usbets", hz * 4) != 0) + break; + } /* Make sure first discover does something. */ sc->sc_bus->needs_explore = 1;