Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Use a recursive lock to ensure that only on threa...
details: https://anonhg.NetBSD.org/src/rev/b8c5f60182fe
branches: trunk
changeset: 768371:b8c5f60182fe
user: dyoung <dyoung%NetBSD.org@localhost>
date: Mon Aug 15 18:24:34 2011 +0000
description:
Use a recursive lock to ensure that only on thread is in wi_ioctl() at
one time. It's a recursive lock because sometimes wi_ioctl() recurses
through the network stack (ick).
diffstat:
sys/dev/ic/wi.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/ic/wivar.h | 12 +++++++-
2 files changed, 86 insertions(+), 3 deletions(-)
diffs (166 lines):
diff -r 6bb28ef4101e -r b8c5f60182fe sys/dev/ic/wi.c
--- a/sys/dev/ic/wi.c Mon Aug 15 18:04:59 2011 +0000
+++ b/sys/dev/ic/wi.c Mon Aug 15 18:24:34 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wi.c,v 1.234 2010/11/23 04:33:09 christos Exp $ */
+/* $NetBSD: wi.c,v 1.235 2011/08/15 18:24:34 dyoung Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -99,7 +99,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.234 2010/11/23 04:33:09 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.235 2011/08/15 18:24:34 dyoung Exp $");
#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
@@ -151,6 +151,11 @@
STATIC int wi_media_change(struct ifnet *);
STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
+static void wi_ioctl_init(struct wi_softc *);
+static int wi_ioctl_enter(struct wi_softc *);
+static void wi_ioctl_exit(struct wi_softc *);
+static void wi_ioctl_drain(struct wi_softc *);
+
STATIC struct ieee80211_node *wi_node_alloc(struct ieee80211_node_table *);
STATIC void wi_node_free(struct ieee80211_node *);
@@ -373,6 +378,8 @@
};
int s;
+ wi_ioctl_init(sc);
+
s = splnet();
/* Make sure interrupts are disabled. */
@@ -595,6 +602,7 @@
ieee80211_ifdetach(&sc->sc_ic);
if_detach(ifp);
splx(s);
+ wi_ioctl_drain(sc);
return 0;
}
@@ -1289,6 +1297,67 @@
ieee80211_watchdog(&sc->sc_ic);
}
+static int
+wi_ioctl_enter(struct wi_softc *sc)
+{
+ int rc = 0;
+
+ mutex_enter(&sc->sc_ioctl_mtx);
+ sc->sc_ioctl_nwait++;
+ while (sc->sc_ioctl_lwp != NULL && sc->sc_ioctl_lwp != curlwp) {
+ rc = sc->sc_ioctl_gone
+ ? ENXIO
+ : cv_wait_sig(&sc->sc_ioctl_cv, &sc->sc_ioctl_mtx);
+ if (rc != 0)
+ break;
+ }
+ if (rc == 0) {
+ sc->sc_ioctl_lwp = curlwp;
+ sc->sc_ioctl_depth++;
+ }
+ if (--sc->sc_ioctl_nwait == 0)
+ cv_signal(&sc->sc_ioctl_cv);
+ mutex_exit(&sc->sc_ioctl_mtx);
+ return rc;
+}
+
+static void
+wi_ioctl_exit(struct wi_softc *sc)
+{
+ KASSERT(sc->sc_ioctl_lwp == curlwp);
+ mutex_enter(&sc->sc_ioctl_mtx);
+ if (--sc->sc_ioctl_depth == 0) {
+ sc->sc_ioctl_lwp = NULL;
+ cv_signal(&sc->sc_ioctl_cv);
+ }
+ mutex_exit(&sc->sc_ioctl_mtx);
+}
+
+static void
+wi_ioctl_init(struct wi_softc *sc)
+{
+ mutex_init(&sc->sc_ioctl_mtx, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&sc->sc_ioctl_cv, device_xname(sc->sc_dev));
+}
+
+static void
+wi_ioctl_drain(struct wi_softc *sc)
+{
+ wi_ioctl_enter(sc);
+
+ mutex_enter(&sc->sc_ioctl_mtx);
+ sc->sc_ioctl_gone = true;
+ cv_broadcast(&sc->sc_ioctl_cv);
+ while (sc->sc_ioctl_nwait != 0)
+ cv_wait(&sc->sc_ioctl_cv, &sc->sc_ioctl_mtx);
+ mutex_exit(&sc->sc_ioctl_mtx);
+
+ wi_ioctl_exit(sc);
+
+ mutex_destroy(&sc->sc_ioctl_mtx);
+ cv_destroy(&sc->sc_ioctl_cv);
+}
+
STATIC int
wi_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
@@ -1302,6 +1371,9 @@
s = splnet();
+ if ((error = wi_ioctl_enter(sc)) != 0)
+ return error;
+
switch (cmd) {
case SIOCSIFFLAGS:
if ((error = ifioctl_common(ifp, cmd, data)) != 0)
@@ -1374,6 +1446,7 @@
break;
}
wi_mend_flags(sc, ic->ic_state);
+ wi_ioctl_exit(sc);
splx(s);
return error;
}
diff -r 6bb28ef4101e -r b8c5f60182fe sys/dev/ic/wivar.h
--- a/sys/dev/ic/wivar.h Mon Aug 15 18:04:59 2011 +0000
+++ b/sys/dev/ic/wivar.h Mon Aug 15 18:24:34 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wivar.h,v 1.64 2010/11/23 04:33:09 christos Exp $ */
+/* $NetBSD: wivar.h,v 1.65 2011/08/15 18:24:34 dyoung Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -32,6 +32,10 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/lwp.h>
+
/* Radio capture format for Prism. */
#define WI_RX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -166,6 +170,12 @@
/* number of transmissions pending at each data rate */
u_int8_t sc_txpending[IEEE80211_RATE_MAXSIZE];
struct callout sc_rssadapt_ch;
+ kmutex_t sc_ioctl_mtx;
+ kcondvar_t sc_ioctl_cv;
+ bool sc_ioctl_gone;
+ unsigned int sc_ioctl_nwait;
+ unsigned int sc_ioctl_depth;
+ lwp_t *sc_ioctl_lwp;
};
#define sc_if sc_ec.ec_if
Home |
Main Index |
Thread Index |
Old Index