Re: port-arm/60021: USB-only boot: uhub0 attaches but uhub1 never appears, no hotplug events; SD-boot sees hub+umass fine
"Taylor R Campbell via gnats" <[email protected]>
| Newsgroups | gmane.os.netbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
The following reply was made to PR port-arm/60021; it has been noted by GNATS. From: Taylor R Campbell <[email protected]> To: Nick Hudson <[email protected]> Cc: [email protected], [email protected], [email protected] 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 <[email protected]> >=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.