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



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