Module Name: src Committed By: riastradh Date: Thu Mar 3 05:48:37 UTC 2022
Modified Files: src/sys/dev/usb: usbnet.c Log Message: usbnet: Refuse to bring interfaces back up once dying. Make this happen uniformly across all usbnet drivers, not on a per-driver basis. This ensures new activity on the interface can't happen by the time we have stopped existing activity and waited for it to complete. To generate a diff of this commit: cvs rdiff -u -r1.57 -r1.58 src/sys/dev/usb/usbnet.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/usbnet.c diff -u src/sys/dev/usb/usbnet.c:1.57 src/sys/dev/usb/usbnet.c:1.58 --- src/sys/dev/usb/usbnet.c:1.57 Thu Mar 3 05:48:30 2022 +++ src/sys/dev/usb/usbnet.c Thu Mar 3 05:48:37 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: usbnet.c,v 1.57 2022/03/03 05:48:30 riastradh Exp $ */ +/* $NetBSD: usbnet.c,v 1.58 2022/03/03 05:48:37 riastradh Exp $ */ /* * Copyright (c) 2019 Matthew R. Green @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.57 2022/03/03 05:48:30 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.58 2022/03/03 05:48:37 riastradh Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -1289,9 +1289,20 @@ usbnet_if_init(struct ifnet *ifp) { USBNETHIST_FUNC(); USBNETHIST_CALLED(); struct usbnet * const un = ifp->if_softc; + bool dying; KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname); + /* + * Prevent anyone from bringing the interface back up once + * we're detaching. + */ + mutex_enter(&un->un_pri->unp_core_lock); + dying = un->un_pri->unp_dying; + mutex_exit(&un->un_pri->unp_core_lock); + if (dying) + return EIO; + return uno_init(un, ifp); } @@ -1572,10 +1583,18 @@ usbnet_detach(device_t self, int flags) struct ifnet * const ifp = usbnet_ifp(un); struct mii_data * const mii = usbnet_mii(un); + /* + * Prevent new activity. After we stop the interface, it + * cannot be brought back up. + */ mutex_enter(&unp->unp_core_lock); unp->unp_dying = true; mutex_exit(&unp->unp_core_lock); + /* + * If we're still running on the network, stop and wait for all + * asynchronous activity to finish. + */ IFNET_LOCK(ifp); if (ifp->if_flags & IFF_RUNNING) { usbnet_if_stop(ifp, 1);