Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Feb 2009 17:40:32 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 157497 for review
Message-ID:  <200902101740.n1AHeWnQ040806@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=157497

Change 157497 by hselasky@hselasky_laptop001 on 2009/02/10 17:39:48

	
	USB WLAN: Fix more races and panics after that
	Andrew Thompson re-ported the WLAN drivers
	from the old USB stack.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#31 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#31 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#33 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zydreg.h#7 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#31 (text+ko) ====

@@ -126,6 +126,7 @@
 static usb2_proc_callback_t rum_amrr_task;
 static usb2_proc_callback_t rum_init_task;
 static usb2_proc_callback_t rum_stop_task;
+static usb2_proc_callback_t rum_flush_task;
 
 static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
 			    const char name[IFNAMSIZ], int unit, int opmode,
@@ -611,9 +612,31 @@
 }
 
 static void
+rum_flush_task(struct usb2_proc_msg *pm)
+{
+	struct rum_task *task = (struct rum_task *)pm;
+	struct rum_softc *sc = task->sc;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+	struct rum_vap *rvp = RUM_VAP(vap);
+
+  	/* callout it stopped */
+	usb2_callout_stop(&rvp->amrr_ch);
+}
+
+static void
 rum_vap_delete(struct ieee80211vap *vap)
 {
 	struct rum_vap *rvp = RUM_VAP(vap);
+	struct rum_softc *sc = rvp->sc;
+
+	RUM_LOCK(sc);
+	/* wait for any pending tasks to complete */
+	rum_queue_command(sc, rum_flush_task,
+	    &sc->sc_synctask[0].hdr,
+	    &sc->sc_synctask[1].hdr);
+	RUM_UNLOCK(sc);
 
 	usb2_callout_drain(&rvp->amrr_ch);
 	ieee80211_amrr_cleanup(&rvp->amrr);
@@ -701,9 +724,16 @@
 
 	ostate = vap->iv_state;
 
+	/* callout it stopped */
+	usb2_callout_stop(&rvp->amrr_ch);
+
 	switch (sc->sc_state) {
 	case IEEE80211_S_INIT:
 		if (ostate == IEEE80211_S_RUN) {
+			/*
+			 * BUG: this code is not executed like it
+			 * should --hps
+			 */
 			/* abort TSF synchronization */
 			tmp = rum_read(sc, RT2573_TXRX_CSR9);
 			rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
@@ -759,8 +789,6 @@
 		ieee80211_state_name[nstate]);
 
 	RUM_LOCK(sc);
-	usb2_callout_stop(&rvp->amrr_ch);
-
 	/* do it in a process context */
 	sc->sc_state = nstate;
 	sc->sc_arg = arg;
@@ -2183,7 +2211,9 @@
 
 	ieee80211_amrr_node_init(&rvp->amrr, &RUM_NODE(ni)->amn, ni);
 
-	usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
+	/* XXX WLAN race --hps */
+	if (sc->sc_state != IEEE80211_S_INIT)
+		usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
 }
 
 static void
@@ -2192,8 +2222,15 @@
 	struct rum_vap *rvp = arg;
 	struct rum_softc *sc = rvp->sc;
 
+	/* XXX WLAN race --hps */
+	if (sc->sc_state == IEEE80211_S_INIT)
+		return;
+
 	rum_queue_command(sc, rum_amrr_task,
 	    &rvp->amrr_task[0].hdr, &rvp->amrr_task[1].hdr);
+
+	/* to avoid sync-issues we need to reset the callout here */
+	usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
 }
 
 static void
@@ -2204,7 +2241,6 @@
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-	struct rum_vap *rvp = RUM_VAP(vap);
 	struct ieee80211_node *ni = vap->iv_bss;
 	int ok, fail;
 
@@ -2215,13 +2251,15 @@
 	    (le32toh(sc->sta[5]) & 0xffff);	/* TX ok w/ retry */
 	fail = (le32toh(sc->sta[5]) >> 16);	/* TX retry-fail count */
 
+	/* XXX WLAN race --hps */
+	if (sc->sc_state == IEEE80211_S_INIT)
+		return;
+
 	ieee80211_amrr_tx_update(&RUM_NODE(ni)->amn,
 	    ok+fail, ok, (le32toh(sc->sta[5]) & 0xffff) + fail);
 	(void) ieee80211_amrr_choose(ni, &RUM_NODE(ni)->amn);
 
 	ifp->if_oerrors += fail;	/* count TX retry-fail as Tx errors */
-
-	usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
 }
 
 /* ARGUSED */
@@ -2388,9 +2426,10 @@
 	task->sc = sc;
 
         /*
-         * Init and stop must be synchronous!
+         * Init, stop and flush must be synchronous!
          */
-        if ((fn == rum_init_task) || (fn == rum_stop_task))
+        if ((fn == rum_init_task) || (fn == rum_stop_task) || 
+	    (fn == rum_flush_task))
                 usb2_proc_mwait(&sc->sc_tq, t0, t1);
 }
 

==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#31 (text+ko) ====

@@ -105,6 +105,7 @@
 static usb2_proc_callback_t ural_amrr_task;
 static usb2_proc_callback_t ural_init_task;
 static usb2_proc_callback_t ural_stop_task;
+static usb2_proc_callback_t ural_flush_task;
 
 static struct ieee80211vap *ural_vap_create(struct ieee80211com *,
 			    const char name[IFNAMSIZ], int unit, int opmode,
@@ -597,9 +598,31 @@
 }
 
 static void
+ural_flush_task(struct usb2_proc_msg *pm)
+{
+	struct ural_task *task = (struct ural_task *)pm;
+	struct ural_softc *sc = task->sc;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+	struct ural_vap *uvp = URAL_VAP(vap);
+
+	/* callout it stopped */
+	usb2_callout_stop(&uvp->amrr_ch);
+}
+
+static void
 ural_vap_delete(struct ieee80211vap *vap)
 {
 	struct ural_vap *uvp = URAL_VAP(vap);
+	struct ural_softc *sc = uvp->sc;
+
+	RAL_LOCK(sc);
+	/* wait for any pending tasks to complete */
+	ural_queue_command(sc, ural_flush_task,
+	    &sc->sc_synctask[0].hdr,
+	    &sc->sc_synctask[1].hdr);
+	RAL_UNLOCK(sc);
 
 	usb2_callout_drain(&uvp->amrr_ch);
 	ieee80211_amrr_cleanup(&uvp->amrr);
@@ -687,9 +710,16 @@
 
 	ostate = vap->iv_state;
 
+	/* callout is stopped */
+	usb2_callout_stop(&uvp->amrr_ch);
+
 	switch (sc->sc_state) {
 	case IEEE80211_S_INIT:
 		if (ostate == IEEE80211_S_RUN) {
+			/*
+			 * BUG: this code is not executed like it
+			 * should --hps
+			 */
 			/* abort TSF synchronization */
 			ural_write(sc, RAL_TXRX_CSR19, 0);
 
@@ -793,8 +823,6 @@
 		ieee80211_state_name[nstate]);
 
 	RAL_LOCK(sc);
-	usb2_callout_stop(&uvp->amrr_ch);
-
 	/* do it in a process context */
 	sc->sc_state = nstate;
 	sc->sc_arg = arg;
@@ -2269,7 +2297,9 @@
 
 	ieee80211_amrr_node_init(&uvp->amrr, &URAL_NODE(ni)->amn, ni);
 
-	usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
+	/* XXX WLAN race --hps */
+	if (sc->sc_state != IEEE80211_S_INIT)
+	    usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
 }
 
 static void
@@ -2278,8 +2308,15 @@
 	struct ural_vap *uvp = arg;
 	struct ural_softc *sc = uvp->sc;
 
+	/* XXX WLAN race --hps */
+	if (sc->sc_state == IEEE80211_S_INIT)
+		return;
+
 	ural_queue_command(sc, ural_amrr_task,
 	    &uvp->amrr_task[0].hdr, &uvp->amrr_task[1].hdr);
+
+	/* to avoid sync-issues we need to reset the callout here */
+	usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
 }
 
 static void
@@ -2290,7 +2327,6 @@
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-	struct ural_vap *uvp = URAL_VAP(vap);
 	struct ieee80211_node *ni = vap->iv_bss;
 	int ok, fail;
 
@@ -2301,13 +2337,15 @@
 	     sc->sta[8];		/* TX ok w/ retry */
 	fail = sc->sta[9];		/* TX retry-fail count */
 
+	/* XXX WLAN race --hps */
+	if (sc->sc_state == IEEE80211_S_INIT)
+		return;
+
 	ieee80211_amrr_tx_update(&URAL_NODE(ni)->amn,
 	    ok+fail, ok, sc->sta[8] + fail);
 	(void) ieee80211_amrr_choose(ni, &URAL_NODE(ni)->amn);
 
 	ifp->if_oerrors += fail;	/* count TX retry-fail as Tx errors */
-
-	usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
 }
 
 static void
@@ -2335,9 +2373,9 @@
 	task->sc = sc;
 
 	/*
-	 * Init and stop must be synchronous!
+	 * Init, stop and flush must be synchronous!
 	 */
-	if ((fn == ural_init_task) || (fn == ural_stop_task))
+	if ((fn == ural_init_task) || (fn == ural_stop_task) ||
+	    (fn == ural_stop_task))
 		usb2_proc_mwait(&sc->sc_tq, t0, t1);
 }
-

==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#33 (text+ko) ====

@@ -91,6 +91,7 @@
 static usb2_proc_callback_t zyd_multitask;
 static usb2_proc_callback_t zyd_init_task;
 static usb2_proc_callback_t zyd_stop_task;
+static usb2_proc_callback_t zyd_flush_task;
 
 static struct ieee80211vap *zyd_vap_create(struct ieee80211com *,
 		    const char name[IFNAMSIZ], int unit, int opmode,
@@ -469,6 +470,7 @@
 	const uint8_t bssid[IEEE80211_ADDR_LEN],
 	const uint8_t mac[IEEE80211_ADDR_LEN])
 {
+	struct zyd_softc *sc = ic->ic_ifp->if_softc;
 	struct zyd_vap *zvp;
 	struct ieee80211vap *vap;
 
@@ -487,6 +489,7 @@
 	zvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = zyd_newstate;
 
+	zvp->sc = sc;
 	ieee80211_amrr_init(&zvp->amrr, vap,
 	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
 	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
@@ -500,10 +503,24 @@
 }
 
 static void
+zyd_flush_task(struct usb2_proc_msg *_pm)
+{
+	/* nothing to do */
+}
+
+static void
 zyd_vap_delete(struct ieee80211vap *vap)
 {
 	struct zyd_vap *zvp = ZYD_VAP(vap);
+	struct zyd_softc *sc = zvp->sc;
 
+	ZYD_LOCK(sc);
+	/* wait for any pending tasks to complete */
+	zyd_queue_command(sc, zyd_flush_task,
+	   &sc->sc_synctask[0].hdr,
+	   &sc->sc_synctask[1].hdr);
+	ZYD_UNLOCK(sc);
+
 	ieee80211_amrr_cleanup(&zvp->amrr);
 	ieee80211_vap_detach(vap);
 	free(zvp, M_80211_VAP);
@@ -3092,7 +3109,8 @@
         /*
          * Init and stop must be synchronous!
          */
-        if ((fn == zyd_init_task) || (fn == zyd_stop_task))
+        if ((fn == zyd_init_task) || (fn == zyd_stop_task) ||
+	    (fn == zyd_flush_task))
                 usb2_proc_mwait(&sc->sc_tq, t0, t1);
 }
 

==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zydreg.h#7 (text+ko) ====

@@ -1247,6 +1247,7 @@
 	struct ieee80211vap	vap;
 	int			(*newstate)(struct ieee80211vap *,
 				    enum ieee80211_state, int);
+	struct zyd_softc	*sc;
 	struct ieee80211_amrr	amrr;
 };
 #define	ZYD_VAP(vap)	((struct zyd_vap *)(vap))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902101740.n1AHeWnQ040806>