Hi Stuart,

On 2025-11-25 22:29, Stuart Henderson wrote:
iirc there was something about disabling USB 3 or XHCI handoff
or legacy USB support on these...

Thanks for pointing to these options. I have played with most of them and unfortunately I didn't have a luck. Maybe only one time the `uhub3` was properly detected during BMC reset but that was it.

I have tested a few Linux distros (live-usb-booting) and it seems the Linux kernel handles the BMC reset (not sure if it does some sort of workaround or because of its different "nature").

I spend some time and managed to build a kernel with the following "bad and ugly" patch and the keyboard works after a BMC reset. This was just a proof-of-concept and I'm not an USB-stack expert - but it was fun after all :)

Index: dev/usb/xhci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/xhci.c,v
diff -u -p -r1.136 xhci.c
--- dev/usb/xhci.c      1 Mar 2025 14:43:03 -0000       1.136
+++ dev/usb/xhci.c      25 Nov 2025 21:59:35 -0000
@@ -54,6 +54,42 @@ int xhcidebug = 3;
 #define TRBOFF(r, trb) ((char *)(trb) - (char *)((r)->trbs))
#define DEQPTR(r) ((r).dma.paddr + (sizeof(struct xhci_trb) * (r).index))

+#define XHCI_BMC_PORT          3
+#define XHCI_BMC_DELAY_MS      300
+
+void
+xhci_rh_task(void *arg)
+{
+       struct xhci_softc *sc = arg;
+       struct usbd_xfer *xfer;
+       int s;
+
+       /* Check if the BMC Delay flag was set by the interrupt handler */
+       if (sc->sc_flags & XHCI_BMC_DELAY_ACTIVE) {
+ printf("%s: BMC detected on Port %d - waiting %dms for stability...\n",
+                   DEVNAME(sc), XHCI_BMC_PORT, XHCI_BMC_DELAY_MS);
+
+               usb_delay_ms(&sc->sc_bus, XHCI_BMC_DELAY_MS);
+
+               /* Clear the flag */
+               s = splusb();
+               sc->sc_flags &= ~XHCI_BMC_DELAY_ACTIVE;
+               splx(s);
+       }
+
+       /* Now notify the USB stack that the port status has changed */
+       s = splusb();
+       xfer = sc->sc_intrxfer;
+
+       if (xfer != NULL) {
+               /* The buffer 'p' was populated by xhci_event_port_change */
+               xfer->actlen = xfer->length;
+               xfer->status = USBD_NORMAL_COMPLETION;
+               usb_transfer_complete(xfer);
+       }
+       splx(s);
+}
+
 struct pool *xhcixfer;

 struct xhci_pipe {
@@ -295,6 +331,9 @@ xhci_init(struct xhci_softc *sc)
        uint32_t hcr;
        int npage, error;

+       /* Initialize the generic Root Hub task */
+ usb_init_task(&sc->sc_rh_task, xhci_rh_task, sc, USB_TASK_TYPE_GENERIC);
+
        sc->sc_bus.usbrev = USBREV_3_0;
        sc->sc_bus.methods = &xhci_bus_methods;
        sc->sc_bus.pipe_size = sizeof(struct xhci_pipe);
@@ -1182,6 +1221,7 @@ xhci_event_port_change(struct xhci_softc
        struct usbd_xfer *xfer = sc->sc_intrxfer;
        uint32_t port = XHCI_TRB_PORTID(paddr);
        uint8_t *p;
+       uint32_t portsc;

        if (XHCI_TRB_GET_CODE(status) != XHCI_CODE_SUCCESS) {
                DPRINTF(("%s: failed port status event\n", DEVNAME(sc)));
@@ -1193,14 +1233,19 @@ xhci_event_port_change(struct xhci_softc

        p = KERNADDR(&xfer->dmabuf, 0);
        memset(p, 0, xfer->length);
-
        p[port/8] |= 1 << (port%8);
+
        DPRINTF(("%s: port=%d change=0x%02x\n", DEVNAME(sc), port, *p));

-       xfer->actlen = xfer->length;
-       xfer->status = USBD_NORMAL_COMPLETION;
+       /* Check for BMC Workaround Condition */
+       portsc = XOREAD4(sc, XHCI_PORTSC(port));
+
+       /* If it's the BMC port connecting, flag it for delay */
+ if (port == XHCI_BMC_PORT && (portsc & XHCI_PS_CSC) && (portsc & XHCI_PS_CCS)) {
+               sc->sc_flags |= XHCI_BMC_DELAY_ACTIVE;
+       }

-       usb_transfer_complete(xfer);
+       usb_add_task(xfer->device, &sc->sc_rh_task);
 }

 void
Index: dev/usb/xhcivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/xhcivar.h,v
diff -u -p -r1.17 xhcivar.h
--- dev/usb/xhcivar.h   1 Feb 2025 22:46:34 -0000       1.17
+++ dev/usb/xhcivar.h   25 Nov 2025 21:59:35 -0000
@@ -124,6 +124,8 @@ struct xhci_softc {

        int                      sc_flags;
 #define XHCI_NOCSS              0x01
+#define XHCI_BMC_DELAY_ACTIVE   0x02
+       struct usb_task          sc_rh_task;
 };

 int    xhci_init(struct xhci_softc *);

Reply via email to