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
> Date: Sat, 21 Feb 2026 10:39:41 +0000
> From: Nick Hudson <nick.hudson%gmx.co.uk@localhost>
>
> This is almost certainly that autoconf doesn't wait (long enough) for
> sub-ordintate hubs
>
> https://nxr.netbsd.org/xref/src/sys/dev/usb/uhub.c#880
>
> 880 mutex_enter(&sc->sc_lock);
> 881 sc->sc_explorepending = false;
> 882 for (int i = 0; i < sc->sc_statuslen; i++) {
> 883 if (sc->sc_statuspend[i] != 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 = 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 = 1; port <= hd->bNbrPorts; port++) {
599 up = &dev->ud_hub->uh_ports[port - 1];
...
848 /* Get device info and set its address. */
849 err = 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 = false;
884 for (int i = 0; i < sc->sc_statuslen; i++) {
885 if (sc->sc_statuspend[i] != 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 = false;
897 }
https://nxr.netbsd.org/xref/src/sys/dev/usb/uhub.c?r=1.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, int speed,
1396 int port, struct usbd_port *up)
1397 {
...
1606 if (port == 0) { /* root hub */
1607 KASSERT(addr == 1);
1608 usbd_attach_roothub(parent, dev);
1609 return USBD_NORMAL_COMPLETION;
1610 }
1611
1612 err = usbd_probe_and_attach(parent, dev, port, addr);
1613 if (err) {
1614 usbd_remove_device(dev, up);
1615 return err;
1616 }
1617
1618 return USBD_NORMAL_COMPLETION;
1619 }
https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=1.281#1388
1047 usbd_status
1048 usbd_attach_roothub(device_t parent, struct usbd_device *dev)
1049 {
...
1065 dv = config_found(parent, &uaa, NULL,
1066 CFARGS(.iattr = "usbroothubif"));
https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=1.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 = usbd_attachwholedevice(parent, dev, port, 0);
1284 if (dev->ud_nifaces_claimed || err)
1285 return err;
...
1290 for (confi = 0; confi < dd->bNumConfigurations; confi++) {
...
1305 err = usbd_attachinterfaces(parent, dev, port, NULL);
...
1313 if (dev->ud_nifaces_claimed || err)
1314 return err;
1315 }
...
1324 err = usbd_attachwholedevice(parent, dev, port, 1);
https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=1.281#1270
1129 static usbd_status
1130 usbd_attachwholedevice(device_t parent, struct usbd_device *dev, int port,
1131 int usegeneric)
1132 {
...
1161 dv = config_found(parent, &uaa, usbd_print,
1162 CFARGS(.submatch = config_stdsubmatch,
1163 .iattr = "usbdevif",
1164 .locators = dlocs));
...
https://nxr.netbsd.org/xref/src/sys/dev/usb/usb_subr.c?r=1.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 = config_found(parent, &uiaa, usbd_ifprint,
1243 CFARGS(.submatch = config_stdsubmatch,
1244 .iattr = "usbifif",
1245 .locators = 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 = kmem_alloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
372 KM_SLEEP);
373 dev->ud_hub = hub;
374 dev->ud_hub->uh_hubsoftc = sc;
375 hub->uh_explore = uhub_explore;
376 hub->uh_hubdesc = hubdesc;
https://nxr.netbsd.org/xref/src/sys/dev/usb/uhub.c?r=1.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=1 so you can drop into
ddb and `show kernhist usbhist' might help.
Home |
Main Index |
Thread Index |
Old Index