Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140978365
D28136.id83306.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D28136.id83306.diff
View Options
diff --git a/sys/dev/usb/net/if_usie.c b/sys/dev/usb/net/if_usie.c
--- a/sys/dev/usb/net/if_usie.c
+++ b/sys/dev/usb/net/if_usie.c
@@ -483,6 +483,7 @@
usbd_transfer_unsetup(sc->sc_if_xfer, USIE_IF_N_XFER);
bpfdetach(sc->sc_ifp);
if_detach(sc->sc_ifp);
+ if_slow_drain(sc->sc_ifp);
if_free(sc->sc_ifp);
sc->sc_ifp = NULL;
}
diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c
--- a/sys/dev/usb/net/uhso.c
+++ b/sys/dev/usb/net/uhso.c
@@ -693,8 +693,9 @@
uhso_if_stop(sc);
bpfdetach(sc->sc_ifp);
if_detach(sc->sc_ifp);
- if_free(sc->sc_ifp);
mtx_unlock(&sc->sc_mtx);
+ if_slow_drain(sc->sc_ifp);
+ if_free(sc->sc_ifp);
usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
}
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -292,6 +292,7 @@
/* free unit */
free_unr(ueunit, ue->ue_unit);
if (ue->ue_ifp != NULL) {
+ if_slow_drain(ue->ue_ifp);
if_free(ue->ue_ifp);
ue->ue_ifp = NULL;
}
@@ -311,6 +312,9 @@
ifp = ue->ue_ifp;
if (ifp != NULL) {
+ /* drain all IOCTLs */
+ if_slow_drain(ifp);
+
/* we are not running any more */
UE_LOCK(ue);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -232,6 +232,7 @@
USB_BUS_UNLOCK(ubus);
bpfdetach(ifp);
if_detach(ifp);
+ if_slow_drain(ifp);
if_free(ifp);
ifc_free_unit(ifc, unit);
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -645,6 +645,8 @@
ifq_init(&ifp->if_snd, ifp);
refcount_init(&ifp->if_refcount, 1); /* Index reference. */
+ refcount_init(&ifp->if_slowref, 1);
+
for (int i = 0; i < IFCOUNTERS; i++)
ifp->if_counters[i] = counter_u64_alloc(M_WAITOK);
ifp->if_get_counter = if_get_counter_default;
@@ -753,6 +755,32 @@
NET_EPOCH_CALL(if_destroy, &ifp->if_epoch_ctx);
}
+/*
+ * Keep track of slow path configuration events.
+ * Returns true on success and false on failure.
+ */
+bool
+if_slow_ref(struct ifnet *ifp)
+{
+ return (refcount_acquire_if_not_zero(&ifp->if_slowref));
+}
+
+void
+if_slow_drain(struct ifnet *ifp)
+{
+ if (refcount_release(&ifp->if_slowref))
+ return;
+
+ while (refcount_load(&ifp->if_slowref) != 0)
+ pause("W", hz);
+}
+
+void
+if_slow_unref(struct ifnet *ifp)
+{
+ (void) refcount_release(&ifp->if_slowref);
+}
+
void
ifq_init(struct ifaltq *ifq, struct ifnet *ifp)
{
@@ -2459,8 +2487,8 @@
/*
* Hardware specific interface ioctls.
*/
-int
-ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
+static inline int
+ifhwioctl_sub(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
{
struct ifreq *ifr;
int error = 0, do_ifup = 0;
@@ -2887,6 +2915,19 @@
return (error);
}
+int
+ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
+{
+ int error;
+
+ if (if_slow_ref(ifp) == false)
+ return (ENXIO);
+ error = ifhwioctl_sub(cmd, ifp, data, td);
+ if_slow_unref(ifp);
+ return (error);
+}
+
+
#ifdef COMPAT_FREEBSD32
struct ifconf32 {
int32_t ifc_len;
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -313,6 +313,7 @@
void *if_linkmib; /* link-type-specific MIB data */
size_t if_linkmiblen; /* length of above data */
u_int if_refcount; /* reference count */
+ u_int if_slowref; /* reference count (slow path) */
/* These fields are shared with struct if_data. */
uint8_t if_type; /* ethernet, tokenring, etc */
@@ -660,6 +661,9 @@
int if_printf(struct ifnet *, const char *, ...) __printflike(2, 3);
void if_ref(struct ifnet *);
void if_rele(struct ifnet *);
+bool if_slow_ref(struct ifnet *) __result_use_check;
+void if_slow_drain(struct ifnet *);
+void if_slow_unref(struct ifnet *);
int if_setlladdr(struct ifnet *, const u_char *, int);
int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, uint32_t, int);
void if_up(struct ifnet *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 31, 8:34 AM (4 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27406729
Default Alt Text
D28136.id83306.diff (3 KB)
Attached To
Mode
D28136: Make sure user-space calls are drained when detaching network interfaces.
Attached
Detach File
Event Timeline
Log In to Comment