BETA2 panic

Adrian Chadd adrian at freebsd.org
Thu Sep 8 04:35:47 UTC 2011


Hi,

Please try this patch.

I bet what's happening is:

* transition is going from RUN -> ! RUN;
* the state is changed before the swbmiss timer is cancelled;
* the callout gets called in another process context;
* bang!

This patch:

* changes the order of things so the callout is cancelled -before- the
state is changed;
* grabs the ic lock in the swbmiss task just to make sure nothing else
is fiddling with it.

Thanks,


cynthia:head adrian$ svn diff sys/net80211/
Index: sys/net80211/ieee80211_sta.c
===================================================================
--- sys/net80211/ieee80211_sta.c	(revision 225421)
+++ sys/net80211/ieee80211_sta.c	(working copy)
@@ -217,13 +217,14 @@
 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
 	    __func__, ieee80211_state_name[ostate],
 	    ieee80211_state_name[nstate], arg);
+	/* Disable callout before changing state */
+	if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)
+		callout_stop(&vap->iv_swbmiss);
 	vap->iv_state = nstate;			/* state transition */
 	callout_stop(&vap->iv_mgtsend);		/* XXX callout_drain */
 	if (ostate != IEEE80211_S_SCAN)
 		ieee80211_cancel_scan(vap);	/* background scan */
 	ni = vap->iv_bss;			/* NB: no reference held */
-	if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)
-		callout_stop(&vap->iv_swbmiss);
 	switch (nstate) {
 	case IEEE80211_S_INIT:
 		switch (ostate) {
Index: sys/net80211/ieee80211_proto.c
===================================================================
--- sys/net80211/ieee80211_proto.c	(revision 225421)
+++ sys/net80211/ieee80211_proto.c	(working copy)
@@ -1440,6 +1440,12 @@
 	struct ieee80211vap *vap = arg;
 	struct ieee80211com *ic = vap->iv_ic;

+	/*
+	 * Grab comlock; a state transition may be occuring
+	 * in another context.
+	 */
+	IEEE80211_LOCK(ic);
+
 	/* XXX sleep state? */
 	KASSERT(vap->iv_state == IEEE80211_S_RUN,
 	    ("wrong state %d", vap->iv_state));
@@ -1463,6 +1469,8 @@
 		vap->iv_swbmiss_count = 0;
 	callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
 		ieee80211_swbmiss, vap);
+
+	IEEE80211_UNLOCK(ic);
 }


More information about the freebsd-wireless mailing list