diff options
| author | riastradh <riastradh@NetBSD.org> | 2022-03-03 05:48:37 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2022-03-03 05:48:37 +0000 |
| commit | 3aaa99d2bb70021ce0af7619833ef66846b60385 (patch) | |
| tree | 350043ebfe2e233b6bacf726dda07307a625adfa /sys/dev/usb | |
| parent | 4c188117032f207aadbc9a677381121329e2a741 (diff) | |
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.
Diffstat (limited to 'sys/dev/usb')
| -rw-r--r-- | sys/dev/usb/usbnet.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/sys/dev/usb/usbnet.c b/sys/dev/usb/usbnet.c index 2445652db2f..f8652dadcaa 100644 --- a/sys/dev/usb/usbnet.c +++ b/sys/dev/usb/usbnet.c @@ -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); |
