summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2005-03-17 19:41:19 +0000
committeriedowse <iedowse@FreeBSD.org>2005-03-17 19:41:19 +0000
commitc9756266e6b967dfffc064df02a31fe808a203b1 (patch)
treefa7ffb5373ffca8a5c7db6aa4b91f42057b4da22
parent19da85af4a083ce6f05e67a3b9740ca3149f21c9 (diff)
downloadFreeBSD-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.c31
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
OpenPOWER on IntegriCloud