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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.