NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-arm/60021: USB-only boot: uhub0 attaches but uhub1 never appears, no hotplug events; SD-boot sees hub+umass fine



I will give it a go (build /wUSB_DEBUG), and report.  I also have an RPi3B  (not +), and will try there, too.

LLMs say not waiting long enough for the attach, probably.

On Tue, Aug 4, 2026 at 6:35 AM Taylor R Campbell via gnats <gnats-admin%netbsd.org@localhost> wrote:
The following reply was made to PR port-arm/60021; it has been noted by GNATS.

From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Nick Hudson <nick.hudson%gmx.co.uk@localhost>
Cc: mac%culver.net@localhost, gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: port-arm/60021: USB-only boot: uhub0 attaches but uhub1 never
        appears, no hotplug events; SD-boot sees hub+umass fine
Date: Tue, 4 Aug 2026 13:34:02 +0000

 > Date: Sat, 21 Feb 2026 10:39:41 +0000
 > From: Nick Hudson <nick.hudson%gmx.co.uk@localhost>
 >=20
 > This is almost certainly that autoconf doesn't wait (long enough) for
 > sub-ordintate hubs
 >=20
 > https://nxr.netbsd.org/xref/src/sys/dev/usb/uhub.c#880
 >=20
 >      880     mutex_enter(&sc->sc_lock);
 >      881     sc->sc_explorepending =3D false;
 >      882     for (int i =3D 0; i < sc->sc_statuslen; i++) {
 >      883             if (sc->sc_statuspend[i] !=3D 0) {
 >      884                     memcpy(sc->sc_status, sc->sc_statuspend,
 >      885                         sc->sc_statuslen);
 >      886                     memset(sc->sc_statuspend, 0, sc->sc_statuslen);
 >      887                     usb_needs_explore(sc->sc_hub);
 >      888                     break;
 >      889             }
 >      890     }
 >      891     mutex_exit(&sc->sc_lock);
 >      892     if (sc->sc_first_explore) {
 >      893             config_pending_decr(sc->sc_dev);
 >      894             sc->sc_first_explore =3D false;
 >      895     }

 I don't understand, doesn't it wait for subordinate hubs?  Maybe the
 USB hub just doesn't report the device ready at first?

 Here's a fuller picture of the logic -- note that uhub_explore will
 _synchronously_ attach autoconf drivers for the devices it finds on
 the hub, and then uhub_attach will _also_ config_pending_incr:

     529 usbd_status
     530 uhub_explore(struct usbd_device *dev)
     531 {
 ...
     598        for (port =3D 1; port <=3D hd->bNbrPorts; port++) {
     599                up =3D &dev->ud_hub->uh_ports[port - 1];
 ...
     848                /* Get device info and set its address. */
     849                err =3D usbd_new_device(sc->sc_dev, dev->ud_bus,
     850                          dev->ud_depth + 1, speed, port, up);
 ...
     858                if (err) {
 ...
     872                } else {
 ...
     878                        if (up->up_dev->ud_hub)
     879                                up->up_dev->ud_hub->uh_explore(up->up_dev);
     880                }
     881        }
     882        mutex_enter(&sc->sc_lock);
     883        sc->sc_explorepending =3D false;
     884        for (int i =3D 0; i < sc->sc_statuslen; i++) {
     885                if (sc->sc_statuspend[i] !=3D 0) {
     886                        memcpy(sc->sc_status, sc->sc_statuspend,
     887                            sc->sc_statuslen);
     888                        memset(sc->sc_statuspend, 0, sc->sc_statuslen);
     889                        usb_needs_explore(sc->sc_hub);
     890                        break;
     891                }
     892        }
     893        mutex_exit(&sc->sc_lock);
     894        if (sc->sc_first_explore) {
     895                config_pending_decr(sc->sc_dev);
     896                sc->sc_first_explore =3D false;
     897        }

 https://nxr.netbsd.org/xref/src/sys/dev/usb/uhub.c?r=3D1.163#529

 usbd_new_device synchronously attaches autoconf drivers:

    1394 usbd_status
    1395 usbd_new_device(device_t parent, struct usbd_bus *bus, int depth, i=
 nt speed,
    1396     int port, struct usbd_port *up)
    1397 {
 ...
    1606        if (port =3D=3D 0) { /* root hub */
    1607                KASSERT(addr =3D=3D 1);
    1608                usbd_attach_roothub(parent, dev);
    1609                return USBD_NORMAL_COMPLETION;
    1610        }
    1611=20
    1612        err =3D usbd_probe_and_attach(parent, dev, port, addr);
    1613        if (err) {
    1614                usbd_remove_device(dev, up);
    1615                return err;
    1616        }
    1617=20
    1618        return USBD_NORMAL_COMPLETION;
    1619 }

 https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=3D1.281#1388

    1047 usbd_status
    1048 usbd_attach_roothub(device_t parent, struct usbd_device *dev)
    1049 {
 ...
    1065        dv =3D config_found(parent, &uaa, NULL,
    1066            CFARGS(.iattr =3D "usbroothubif"));

 https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=3D1.281#1047

    1270 usbd_status
    1271 usbd_probe_and_attach(device_t parent, struct usbd_device *dev,
    1272     int port, int addr)
    1273 {
 ...
    1283        err =3D usbd_attachwholedevice(parent, dev, port, 0);
    1284        if (dev->ud_nifaces_claimed || err)
    1285                return err;
 ...
    1290        for (confi =3D 0; confi < dd->bNumConfigurations; confi++) {
 ...
    1305                err =3D usbd_attachinterfaces(parent, dev, port, NULL);
 ...
    1313                if (dev->ud_nifaces_claimed || err)
    1314                        return err;
    1315        }
 ...
    1324        err =3D usbd_attachwholedevice(parent, dev, port, 1);

 https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=3D1.281#1270

    1129 static usbd_status
    1130 usbd_attachwholedevice(device_t parent, struct usbd_device *dev, in=
 t port,
    1131     int usegeneric)
    1132 {
 ...
    1161        dv =3D config_found(parent, &uaa, usbd_print,
    1162                          CFARGS(.submatch =3D config_stdsubmatch,
    1163                                 .iattr =3D "usbdevif",
    1164                                 .locators =3D dlocs));
 ...

 https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=3D1.281#1129

    1177 static usbd_status
    1178 usbd_attachinterfaces(device_t parent, struct usbd_device *dev,
    1179     int port, const int *locators)
    1180 {
 ...
    1242                dv =3D config_found(parent, &uiaa, usbd_ifprint,
    1243                                  CFARGS(.submatch =3D config_stdsubmatch,
    1244                                         .iattr =3D "usbifif",
    1245                                         .locators =3D ilocs));

 uhub is only at one of these (usbdevif or usbifif), but the point is
 the attach happens synchronously for subordinate hubs, before
 uhub_explore gets to config_pending_decr.

 And in uhub_attach, pretty much the first thing it does is
 config_pending_incr -- and it also sets the hub of the USB device to
 be the one it just created, so uhub_attach's call to uh_explore should
 take care of this:

     299 static void
     300 uhub_attach(device_t parent, device_t self, void *aux)
     301 {
 ...
     318        config_pending_incr(self);
 ...
     371        hub =3D kmem_alloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_=
 port),
     372            KM_SLEEP);
     373        dev->ud_hub =3D hub;
     374        dev->ud_hub->uh_hubsoftc =3D sc;
     375        hub->uh_explore =3D uhub_explore;
     376        hub->uh_hubdesc =3D hubdesc;

 https://nxr.netbsd.org/xref/src/sys/dev/usb/uhub.c?r=3D1.163#529

 As noted above, uhub_explore even explores the subordinate hubs
 synchronously too by calling uh_explore!

 So, does the USB device not appear to be connected at the time of the
 initial probe, perhaps?

 Building with USB_DEBUG and enabling usb_debug=3D1 so you can drop into
 ddb and `show kernhist usbhist' might help.



Home | Main Index | Thread Index | Old Index