summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2006-05-23 01:27:23 +0000
committeriedowse <iedowse@FreeBSD.org>2006-05-23 01:27:23 +0000
commit3f97a0eb09ef262ac23c2e56f0f4867a6cbd3250 (patch)
treeb2fba9a28410ec736cb7109d8c5c2da37754c7e4
parent30977bc35b2c6606b2b36368fa48f92b5f7dab3a (diff)
downloadFreeBSD-src-3f97a0eb09ef262ac23c2e56f0f4867a6cbd3250.zip
FreeBSD-src-3f97a0eb09ef262ac23c2e56f0f4867a6cbd3250.tar.gz
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.
-rw-r--r--sys/dev/usb/usb.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index dc89d9f..959d866 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;
OpenPOWER on IntegriCloud