The usb(4) driver allows to enumerate the bus early during boot by
setting its driver flags to 0x1 in UKC. This mechanism can enable a USB
console keyboard early during autoconf(9), which can come in handy at
times. This needs USB polling mode to work, which is a bit broken. Here
is my attempt to fix it for xhci(4) controllers.

According to the xHCI specification section 4.2 "Host Controller
Initalization", the host controller must be fully initialized before
descending into device enumeration. Then xhci(4) sends command TRBs to
open new pipes during enumeration. They wait for completion using
tsleep(). This is bad when in polling mode at boot. And finally, the
behavior should be the same on resume as it is at boot. Therefore also
enumerate USB devices during resume when the flag is set.

I am specifically looking for tests on xhci controllers with usb(4)
flags set to 1 in UKC.

So long,


 - Christian


diff --git a/sys/arch/armv7/marvell/mvxhci.c b/sys/arch/armv7/marvell/mvxhci.c
index 38a636fd123..2137f68b816 100644
--- a/sys/arch/armv7/marvell/mvxhci.c
+++ b/sys/arch/armv7/marvell/mvxhci.c
@@ -155,12 +155,12 @@ mvxhci_attach(struct device *parent, struct device *self, 
void *aux)
                goto disestablish_ret;
        }
 
-       /* Attach usb device. */
-       config_found(self, &sc->sc.sc_bus, usbctlprint);
-
        /* Now that the stack is ready, config' the HC and enable interrupts. */
        xhci_config(&sc->sc);
 
+       /* Attach usb device. */
+       config_found(self, &sc->sc.sc_bus, usbctlprint);
+
        return;
 
 disestablish_ret:
diff --git a/sys/dev/acpi/xhci_acpi.c b/sys/dev/acpi/xhci_acpi.c
index 95e69cee896..d762f69a00e 100644
--- a/sys/dev/acpi/xhci_acpi.c
+++ b/sys/dev/acpi/xhci_acpi.c
@@ -112,12 +112,12 @@ xhci_acpi_attach(struct device *parent, struct device 
*self, void *aux)
                goto disestablish_ret;
        }
 
-       /* Attach usb device. */
-       config_found(self, &sc->sc.sc_bus, usbctlprint);
-
        /* Now that the stack is ready, config' the HC and enable interrupts. */
        xhci_config(&sc->sc);
 
+       /* Attach usb device. */
+       config_found(self, &sc->sc.sc_bus, usbctlprint);
+
        return;
 
 disestablish_ret:
diff --git a/sys/dev/fdt/xhci_fdt.c b/sys/dev/fdt/xhci_fdt.c
index 38c976a6b24..84e00bdadc5 100644
--- a/sys/dev/fdt/xhci_fdt.c
+++ b/sys/dev/fdt/xhci_fdt.c
@@ -116,12 +116,12 @@ xhci_fdt_attach(struct device *parent, struct device 
*self, void *aux)
                goto disestablish_ret;
        }
 
-       /* Attach usb device. */
-       config_found(self, &sc->sc.sc_bus, usbctlprint);
-
        /* Now that the stack is ready, config' the HC and enable interrupts. */
        xhci_config(&sc->sc);
 
+       /* Attach usb device. */
+       config_found(self, &sc->sc.sc_bus, usbctlprint);
+
        return;
 
 disestablish_ret:
diff --git a/sys/dev/pci/xhci_pci.c b/sys/dev/pci/xhci_pci.c
index fa3271b0d30..0b46083b705 100644
--- a/sys/dev/pci/xhci_pci.c
+++ b/sys/dev/pci/xhci_pci.c
@@ -195,12 +195,12 @@ xhci_pci_attach(struct device *parent, struct device 
*self, void *aux)
        if (PCI_VENDOR(psc->sc_id) == PCI_VENDOR_INTEL)
                xhci_pci_port_route(psc);
 
-       /* Attach usb device. */
-       config_found(self, &psc->sc.sc_bus, usbctlprint);
-
        /* Now that the stack is ready, config' the HC and enable interrupts. */
        xhci_config(&psc->sc);
 
+       /* Attach usb device. */
+       config_found(self, &psc->sc.sc_bus, usbctlprint);
+
        return;
 
 disestablish_ret:
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index b8943882d0a..f9aff94bfee 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -911,8 +911,19 @@ usb_activate(struct device *self, int act)
                 * hub transfers do not need to sleep.
                 */
                sc->sc_bus->use_polling++;
-               if (!usb_attach_roothub(sc))
+               if (!usb_attach_roothub(sc)) {
+                       struct usbd_device *dev = sc->sc_bus->root_hub;
+#if 1
+                       /*
+                        * Turning this code off will delay attachment of USB 
devices
+                        * until the USB task thread is running, which means 
that
+                        * the keyboard will not work until after resume.
+                        */
+                       if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1))
+                               dev->hub->explore(sc->sc_bus->root_hub);
+#endif
                        usb_needs_explore(sc->sc_bus->root_hub, 0);
+               }
                sc->sc_bus->use_polling--;
                break;
        default:
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index e6f4a802dd7..d8e870cac4e 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1896,7 +1896,21 @@ xhci_command_submit(struct xhci_softc *sc, struct 
xhci_trb *trb0, int timeout)
        s = splusb();
        sc->sc_cmd_trb = trb;
        XDWRITE4(sc, XHCI_DOORBELL(0), 0);
-       error = tsleep_nsec(&sc->sc_cmd_trb, PZERO, "xhcicmd", timeout);
+       if (sc->sc_bus.use_polling) {
+               int timo;
+
+               for (timo = timeout; timo >= 0; timo--) {
+                       usb_delay_ms(&sc->sc_bus, 1);
+                       xhci_poll(&sc->sc_bus);
+                       if (sc->sc_cmd_trb == NULL)
+                               break;
+               }
+
+               if (timo < 0)
+                       error = ETIMEDOUT;
+       } else {
+               error = tsleep_nsec(&sc->sc_cmd_trb, PZERO, "xhcicmd", timeout);
+       }
        if (error) {
 #ifdef XHCI_DEBUG
                printf("%s: tsleep() = %d\n", __func__, error);

Reply via email to