diff --git a/sys/bus/u4b/net/if_ipheth.c b/sys/bus/u4b/net/if_ipheth.c --- a/sys/bus/u4b/net/if_ipheth.c +++ b/sys/bus/u4b/net/if_ipheth.c @@ -232,13 +232,13 @@ uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM); if (error) { device_printf(dev, "Cannot set alternate setting\n"); - goto detach; + goto detach_usb; } error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no, sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_lock); if (error) { device_printf(dev, "Cannot setup USB transfers\n"); - goto detach; + goto detach_usb; } ue->ue_sc = sc; ue->ue_dev = dev; @@ -249,18 +249,27 @@ error = ipheth_get_mac_addr(sc); if (error) { device_printf(dev, "Cannot get MAC address\n"); - goto detach; + goto detach_usb; } error = uether_ifattach(ue); if (error) { device_printf(dev, "could not attach interface\n"); - goto detach; + goto detach_usb; } return (0); /* success */ -detach: - ipheth_detach(dev); + /* + * Pre-uether_ifattach() failure paths: the usb_ether was never + * attached, so ipheth_detach() / uether_ifdetach() must not run. + * On the first two branches ue_lock is still NULL (lockmgr through + * NULL, Fatal trap 12) and on the latter two the embedded ifnet was + * never ether_ifattach()ed. Only unsetup the USB transfers and + * destroy the lock. + */ +detach_usb: + usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER); + lockuninit(&sc->sc_lock); return (ENXIO); /* failure */ } diff --git a/sys/bus/u4b/net/usb_ethernet.c b/sys/bus/u4b/net/usb_ethernet.c --- a/sys/bus/u4b/net/usb_ethernet.c +++ b/sys/bus/u4b/net/usb_ethernet.c @@ -269,6 +269,15 @@ { struct ifnet *ifp; + /* + * Never-attached guard (DF-5334 class): when uether_ifattach() + * never ran there is no taskqueue to drain and no ifnet to + * detach. ue_lock is NULL on the driver attach-failure paths + * that jump to detach before ue field initialisation. + */ + if (ue->ue_lock == NULL) + return; + /* wait for any post attach or other command to complete */ usb_proc_drain(&ue->ue_tq);