PERFORCE change 180844 for review

Hans Petter Selasky hselasky at FreeBSD.org
Mon Jul 12 20:00:12 UTC 2010


http://p4web.freebsd.org/@@180844?ac=10

Change 180844 by hselasky at hselasky_laptop001 on 2010/07/12 19:59:47

	
	USB WLAN:
		- fix races by doing proper refcounting

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/wlan/if_rum.c#29 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#14 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_uath.c#22 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_upgt.c#22 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_ural.c#23 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_urtw.c#16 edit
.. //depot/projects/usb/src/sys/dev/usb/wlan/if_zyd.c#29 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_rum.c#29 (text+ko) ====

@@ -709,9 +709,6 @@
 
 	IEEE80211_UNLOCK(ic);
 
-	/* XXX temporary workaround for race in IEEE802.11 layer */
-	usb_pause_mtx(NULL, hz / 16);
-
 	RUM_LOCK(sc);
 	usb_callout_stop(&rvp->ratectl_ch);
 
@@ -725,7 +722,7 @@
 		break;
 
 	case IEEE80211_S_RUN:
-		ni = vap->iv_bss;
+		ni = ieee80211_ref_node(vap->iv_bss);
 
 		if (vap->iv_opmode != IEEE80211_M_MONITOR) {
 			rum_update_slot(ic->ic_ifp);
@@ -749,6 +746,8 @@
 		tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
 		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
 			rum_ratectl_start(sc, ni);
+
+		ieee80211_free_node(ni);
 		break;
 	default:
 		break;
@@ -2229,7 +2228,7 @@
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 	struct rum_softc *sc = ifp->if_softc;
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	int ok, fail;
 	int sum, retrycnt;
 
@@ -2243,8 +2242,10 @@
 	sum = ok+fail;
 	retrycnt = (le32toh(sc->sta[5]) & 0xffff) + fail;
 
+	ni = ieee80211_ref_node(vap->iv_bss);
 	ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
 	(void) ieee80211_ratectl_rate(ni, NULL, 0);
+	ieee80211_free_node(ni);
 
 	ifp->if_oerrors += fail;	/* count TX retry-fail as Tx errors */
 

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#14 (text+ko) ====

@@ -1694,7 +1694,6 @@
 	struct ieee80211com *ic = vap->iv_ic;
 	const struct ieee80211_txparam *tp;
 	struct run_softc *sc = ic->ic_ifp->if_softc;
-	struct run_node	*rn = (void *)vap->iv_bss;
 	uint8_t rate, ridx;
 	int error;
 
@@ -1708,13 +1707,20 @@
 
 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
 	if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
+		struct ieee80211_node *ni;
+		struct run_node	*rn;
+
 		rate = ic->ic_sup_rates[ic->ic_curmode].
 		    rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL;
 		for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
 			if (rt2860_rates[ridx].rate == rate)
 				break;
+
+		ni = ieee80211_ref_node(vap->iv_bss);
+		rn = (void *)ni;
 		rn->fix_ridx = ridx;
 		DPRINTF("rate=%d, fix_ridx=%d\n", rate, rn->fix_ridx);
+		ieee80211_free_node(ni);
 	}
 
 #if 0
@@ -1782,7 +1788,8 @@
 
 
 	case IEEE80211_S_RUN:
-		ni = vap->iv_bss;
+		ni = ieee80211_ref_node(vap->iv_bss);
+
 		if(!(sc->runbmap & bid)){
 			if(sc->running++)
 				restart_ratectl = 1;
@@ -1837,6 +1844,7 @@
 		    (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ?
 		     RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ));
 
+		ieee80211_free_node(ni);
 		break;
 	default:
 		DPRINTFN(6, "undefined case\n");
@@ -1966,6 +1974,7 @@
 		ni = ieee80211_find_vap_node(&ic->ic_sta, vap, cmdq->mac);
 	else
 		ni = vap->iv_bss;
+
 	associd = (ni != NULL) ? ni->ni_associd : 0;
 
 	/* map net80211 cipher to RT2860 security mode */

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_uath.c#22 (text+ko) ====

@@ -1968,9 +1968,11 @@
 	const struct ieee80211_rateset *rs;
 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	struct uath_cmd_create_connection create;
 
+	ni = ieee80211_ref_node(vap->iv_bss);
+
 	bzero(&create, sizeof create);
 	create.connid = htobe32(connid);
 	create.bssid = htobe32(0);
@@ -1990,6 +1992,8 @@
 	else
 		create.connattr.wlanmode = htobe32(WLAN_MODE_11b);
 
+	ieee80211_free_node(ni);
+
 	return uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create,
 	    sizeof create, 0);
 }
@@ -2017,14 +2021,19 @@
 {
 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	struct uath_cmd_set_associd associd;
 
+	ni = ieee80211_ref_node(vap->iv_bss);
+
 	bzero(&associd, sizeof associd);
 	associd.defaultrateix = htobe32(1);	/* XXX */
 	associd.associd = htobe32(ni->ni_associd);
 	associd.timoffset = htobe32(0x3b);	/* XXX */
 	IEEE80211_ADDR_COPY(associd.bssid, ni->ni_bssid);
+
+	ieee80211_free_node(ni);
+
 	return uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd,
 	    sizeof associd, 0);
 }
@@ -2065,7 +2074,7 @@
 {
 	enum ieee80211_state ostate = vap->iv_state;
 	int error;
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	struct ieee80211com *ic = vap->iv_ic;
 	struct uath_softc *sc = ic->ic_ifp->if_softc;
 	struct uath_vap *uvp = UATH_VAP(vap);
@@ -2076,9 +2085,6 @@
 
 	IEEE80211_UNLOCK(ic);
 
-	/* XXX temporary workaround for race in IEEE802.11 layer */
-	usb_pause_mtx(NULL, hz / 16);
-
 	UATH_LOCK(sc);
 	callout_stop(&sc->stat_ch);
 	callout_stop(&sc->watchdog_ch);
@@ -2095,32 +2101,44 @@
 		break;
 
 	case IEEE80211_S_AUTH:
+		ni = ieee80211_ref_node(vap->iv_bss);
+
 		/* XXX good place?  set RTS threshold  */
 		uath_config(sc, CFG_USER_RTS_THRESHOLD, vap->iv_rtsthreshold);
 		/* XXX bad place  */
 		error = uath_set_keys(sc, vap);
 		if (error != 0) {
+			ieee80211_free_node(ni);
 			device_printf(sc->sc_dev,
 			    "could not set crypto keys, error %d\n", error);
 			break;
 		}
 		if (uath_switch_channel(sc, ni->ni_chan) != 0) {
+			ieee80211_free_node(ni);
 			device_printf(sc->sc_dev, "could not switch channel\n");
 			break;
 		}
 		if (uath_create_connection(sc, UATH_ID_BSS) != 0) {
+			ieee80211_free_node(ni);
 			device_printf(sc->sc_dev,
 			    "could not create connection\n");
 			break;
 		}
+
+		ieee80211_free_node(ni);
 		break;
 
 	case IEEE80211_S_ASSOC:
+		ni = ieee80211_ref_node(vap->iv_bss);
+
 		if (uath_set_rates(sc, &ni->ni_rates) != 0) {
+			ieee80211_free_node(ni);
 			device_printf(sc->sc_dev,
 			    "could not set negotiated rate set\n");
 			break;
 		}
+
+		ieee80211_free_node(ni);
 		break;
 
 	case IEEE80211_S_RUN:
@@ -2130,6 +2148,8 @@
 			break;
 		}
 
+		ni = ieee80211_ref_node(vap->iv_bss);
+
 		/*
 		 * Tx rate is controlled by firmware, report the maximum
 		 * negotiated rate in ifconfig output.
@@ -2137,6 +2157,8 @@
 		ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1];
 
 		if (uath_write_associd(sc) != 0) {
+
+			ieee80211_free_node(ni);
 			device_printf(sc->sc_dev,
 			    "could not write association id\n");
 			break;
@@ -2150,7 +2172,10 @@
 
 		/* start statistics timer */
 		callout_reset(&sc->stat_ch, hz, uath_stat, sc);
+
+		ieee80211_free_node(ni);
 		break;
+
 	default:
 		break;
 	}

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_upgt.c#22 (text+ko) ====

@@ -652,7 +652,7 @@
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	struct upgt_data *data_cmd;
 	struct upgt_lmac_mem *mem;
 	struct upgt_lmac_filter *filter;
@@ -707,6 +707,8 @@
 		filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3);
 		break;
 	case IEEE80211_S_RUN:
+		ni = ieee80211_ref_node(vap->iv_bss);
+
 		/* XXX monitor mode isn't tested yet.  */
 		if (vap->iv_opmode == IEEE80211_M_MONITOR) {
 			filter->type = htole16(UPGT_FILTER_TYPE_MONITOR);
@@ -730,6 +732,8 @@
 			filter->rxhw = htole32(sc->sc_eeprom_hwrx);
 			filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3);
 		}
+
+		ieee80211_free_node(ni);
 		break;
 	default:
 		device_printf(sc->sc_dev,
@@ -1056,9 +1060,6 @@
 
 	IEEE80211_UNLOCK(ic);
 
-	/* XXX temporary workaround for race in IEEE802.11 layer */
-	usb_pause_mtx(NULL, hz / 16);
-
 	UPGT_LOCK(sc);
 	callout_stop(&sc->sc_led_ch);
 	callout_stop(&sc->sc_watchdog_ch);

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_ural.c#23 (text+ko) ====

@@ -695,9 +695,6 @@
 
 	IEEE80211_UNLOCK(ic);
 
-	/* XXX temporary workaround for race in IEEE802.11 layer */
-	usb_pause_mtx(NULL, hz / 16);
-
 	RAL_LOCK(sc);
 	usb_callout_stop(&uvp->ratectl_ch);
 
@@ -713,7 +710,7 @@
 		break;
 
 	case IEEE80211_S_RUN:
-		ni = vap->iv_bss;
+		ni = ieee80211_ref_node(vap->iv_bss);
 
 		if (vap->iv_opmode != IEEE80211_M_MONITOR) {
 			ural_update_slot(ic->ic_ifp);
@@ -729,6 +726,7 @@
 			if (m == NULL) {
 				device_printf(sc->sc_dev,
 				    "could not allocate beacon\n");
+				ieee80211_free_node(ni);
 				RAL_UNLOCK(sc);
 				IEEE80211_LOCK(ic);
 				return (-1);
@@ -737,6 +735,7 @@
 			if (ural_tx_bcn(sc, m, ni) != 0) {
 				device_printf(sc->sc_dev,
 				    "could not send beacon\n");
+				ieee80211_free_node(ni);
 				RAL_UNLOCK(sc);
 				IEEE80211_LOCK(ic);
 				return (-1);
@@ -757,6 +756,7 @@
 		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
 			ural_ratectl_start(sc, ni);
 
+		ieee80211_free_node(ni);
 		break;
 
 	default:
@@ -2239,7 +2239,7 @@
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 	struct ural_softc *sc = ifp->if_softc;
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	int ok, fail;
 	int sum, retrycnt;
 
@@ -2253,8 +2253,10 @@
 	sum = ok+fail;
 	retrycnt = sc->sta[8] + fail;
 
+	ni = ieee80211_ref_node(vap->iv_bss);
 	ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
 	(void) ieee80211_ratectl_rate(ni, NULL, 0);
+	ieee80211_free_node(ni);
 
 	ifp->if_oerrors += fail;	/* count TX retry-fail as Tx errors */
 

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_urtw.c#16 (text+ko) ====

@@ -1830,7 +1830,7 @@
 static int
 urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 {
-	struct ieee80211_node *ni = vap->iv_bss;
+	struct ieee80211_node *ni;
 	struct ieee80211com *ic = vap->iv_ic;
 	struct urtw_softc *sc = ic->ic_ifp->if_softc;
 	struct urtw_vap *uvp = URTW_VAP(vap);
@@ -1844,9 +1844,6 @@
 
 	IEEE80211_UNLOCK(ic);
 
-	/* XXX temporary workaround for race in IEEE802.11 layer */
-	usb_pause_mtx(NULL, hz / 16);
-
 	URTW_LOCK(sc);
 	usb_callout_stop(&sc->sc_led_ch);
 	callout_stop(&sc->sc_watchdog_ch);
@@ -1858,6 +1855,8 @@
 	case IEEE80211_S_ASSOC:
 		break;
 	case IEEE80211_S_RUN:
+		ni = ieee80211_ref_node(vap->iv_bss);
+
 		/* setting bssid.  */
 		urtw_write32_m(sc, URTW_BSSID, ((uint32_t *)ni->ni_bssid)[0]);
 		urtw_write16_m(sc, URTW_BSSID + 4,
@@ -1872,6 +1871,8 @@
 		if (error != 0)
 			device_printf(sc->sc_dev,
 			    "could not control LED (%d)\n", error);
+
+		ieee80211_free_node(ni);
 		break;
 	default:
 		break;

==== //depot/projects/usb/src/sys/dev/usb/wlan/if_zyd.c#29 (text+ko) ====

@@ -580,30 +580,34 @@
 
 	IEEE80211_UNLOCK(ic);
 
-	/* XXX temporary workaround for race in IEEE802.11 layer */
-	usb_pause_mtx(NULL, hz / 16);
-
 	ZYD_LOCK(sc);
 	switch (nstate) {
 	case IEEE80211_S_AUTH:
 		zyd_set_chan(sc, ic->ic_curchan);
 		break;
 	case IEEE80211_S_RUN:
-		ni = vap->iv_bss;
-		if (vap->iv_opmode == IEEE80211_M_MONITOR)
+		ni = ieee80211_ref_node(vap->iv_bss);
+		if (vap->iv_opmode == IEEE80211_M_MONITOR) {
+			ieee80211_free_node(ni);
 			break;
+		}
 
 		/* turn link LED on */
 		error = zyd_set_led(sc, ZYD_LED1, 1);
-		if (error != 0)
+		if (error != 0) {
+			ieee80211_free_node(ni);
 			break;
+		}
 
 		/* make data LED blink upon Tx */
 		zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1);
 
 		IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
 		zyd_set_bssid(sc, sc->sc_bssid);
+
+ 		ieee80211_free_node(ni);
 		break;
+
 	default:
 		break;
 	}


More information about the p4-projects mailing list