diff options
author | iedowse <iedowse@FreeBSD.org> | 2005-03-17 19:41:19 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2005-03-17 19:41:19 +0000 |
commit | c9756266e6b967dfffc064df02a31fe808a203b1 (patch) | |
tree | fa7ffb5373ffca8a5c7db6aa4b91f42057b4da22 | |
parent | 19da85af4a083ce6f05e67a3b9740ca3149f21c9 (diff) | |
download | FreeBSD-src-c9756266e6b967dfffc064df02a31fe808a203b1.zip FreeBSD-src-c9756266e6b967dfffc064df02a31fe808a203b1.tar.gz |
Defer boot-time exploration of USB busses until all devices in the
system have been attached, but no later. This ensures that we do
not explore ohci or uhci busses before the companion echi controller
has been initialised, so it should fix the problem of multi-speed
USB devices getting attached as USB 1 devices first and then
re-attached as USB 2.
Some further changes are needed on architectures that do not currently
allow hooks to be inserted before configure_final() - alpha, ia64,
powerpc and sparc64. On these architectures the exploration will
now be delayed until the usb kthread runs.
-rw-r--r-- | sys/dev/usb/usb.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index d10eb4a..84420d7 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -130,6 +130,7 @@ struct usb_softc { USBBASEDEVICE sc_dev; /* base device */ #ifdef __FreeBSD__ struct cdev *sc_usbdev; /* /dev/usbN device */ + TAILQ_ENTRY(usb_softc) sc_coldexplist; /* cold needs-explore list */ #endif usbd_bus_handle sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ @@ -178,6 +179,9 @@ Static struct proc *usb_task_thread_proc = NULL; Static struct cdev *usb_dev; /* The /dev/usb device. */ Static int usb_ndevs; /* Number of /dev/usbN devices. */ Static int usb_taskcreated; /* USB task thread exists. */ +/* Busses to explore at the end of boot-time device configuration. */ +Static TAILQ_HEAD(, usb_softc) usb_coldexplist = + TAILQ_HEAD_INITIALIZER(usb_coldexplist); #endif #define USB_MAX_EVENTS 100 @@ -298,11 +302,12 @@ USB_ATTACH(usb) */ #if defined(__FreeBSD__) if (cold) + TAILQ_INSERT_TAIL(&usb_coldexplist, sc, sc_coldexplist); #else if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1)) -#endif dev->hub->explore(sc->sc_bus->root_hub); #endif +#endif } else { printf("%s: root hub problem, error=%d\n", USBDEVNAME(sc->sc_dev), err); @@ -947,7 +952,31 @@ usb_child_detached(device_t self, device_t child) sc->sc_port.device = NULL; } +/* Explore all USB busses at the end of device configuration. */ +Static void +usb_cold_explore(void *arg) +{ + struct usb_softc *sc; + + /* XXX, on some archs this is called too late. */ + if (!cold) { + printf("usb_cold_explore: skipping because !cold\n"); + return; + } + + while (!TAILQ_EMPTY(&usb_coldexplist)) { + sc = TAILQ_FIRST(&usb_coldexplist); + TAILQ_REMOVE(&usb_coldexplist, sc, sc_coldexplist); + + sc->sc_bus->use_polling++; + sc->sc_port.device->hub->explore(sc->sc_bus->root_hub); + sc->sc_bus->use_polling--; + } +} + DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0); DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0); DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, 0, 0); +SYSINIT(usb_cold_explore, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, + usb_cold_explore, NULL); #endif |