PERFORCE change 137688 for review

Sam Leffler sam at FreeBSD.org
Fri Mar 14 05:31:20 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=137688

Change 137688 by sam at sam_ebb on 2008/03/14 05:30:19

	o reorder code in detach to avoid teardown races
	o track amrr changes
	o fix scanning so scan stop restores the previous bssid
	  w/o touching the bss node as that may change concurrently
	o replace callout thread for amrr work by inline calls
	  to ieee80211_amrr_choose on xmit
	o replace IFQ_POLL/IFQ_DEQUEUE by deq/prepend on q full;
	  this is not right but makes the driver consistent with
	  the other usb drivers so we can fix 'em all at once

Affected files ...

.. //depot/projects/vap/sys/dev/usb/if_zyd.c#10 edit
.. //depot/projects/vap/sys/dev/usb/if_zydreg.h#6 edit

Differences ...

==== //depot/projects/vap/sys/dev/usb/if_zyd.c#10 (text+ko) ====

@@ -65,10 +65,7 @@
 #include <dev/usb/if_zydreg.h>
 #include <dev/usb/if_zydfw.h>
 
-#ifdef USB_DEBUG
 #define ZYD_DEBUG
-#endif
-
 #ifdef ZYD_DEBUG
 #define DPRINTF(x)	do { if (zyddebug > 0) printf x; } while (0)
 #define DPRINTFN(n, x)	do { if (zyddebug > (n)) printf x; } while (0)
@@ -228,8 +225,6 @@
 static void	zyd_init(void *);
 static void	zyd_stop(struct zyd_softc *, int);
 static int	zyd_loadfirmware(struct zyd_softc *, u_char *, size_t);
-static void	zyd_iter_func(void *, struct ieee80211_node *);
-static void	zyd_amrr_timeout(void *);
 static void	zyd_newassoc(struct ieee80211_node *, int);
 static void	zyd_scantask(void *);
 static void	zyd_scan_start(struct ieee80211com *);
@@ -384,6 +379,8 @@
 	    sc->fw_rev >> 8, sc->fw_rev & 0xff, zyd_rf_name(sc->rf_rev),
 	    sc->pa_rev, ether_sprintf(ic->ic_myaddr));
 
+	IEEE80211_ADDR_COPY(sc->sc_bssid, ic->ic_myaddr);
+
 	ic->ic_ifp = ifp;
 	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
 	ic->ic_opmode = IEEE80211_M_STA;
@@ -451,16 +448,16 @@
 	ifp->if_flags &= ~IFF_UP;
 
 	zyd_stop(sc, 1);
+	bpfdetach(ifp);
+	ieee80211_ifdetach(ic);
+
 	usb_rem_task(sc->sc_udev, &sc->sc_scantask);
 	usb_rem_task(sc->sc_udev, &sc->sc_task);
 	callout_stop(&sc->sc_watchdog_ch);
 
 	zyd_close_pipes(sc);
 
-	bpfdetach(ifp);
-	ieee80211_ifdetach(ic);
 	if_free(ifp);
-
 	mtx_destroy(&sc->sc_mtx);
 
 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
@@ -492,10 +489,10 @@
 	zvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = zyd_newstate;
 
-	callout_init(&zvp->amrr_ch, 0);
 	ieee80211_amrr_init(&zvp->amrr, vap,
 	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
-	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
+	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
+	    1000 /* 1 sec */);
 
 	/* complete setup */
 	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
@@ -508,7 +505,7 @@
 {
 	struct zyd_vap *zvp = ZYD_VAP(vap);
 
-	callout_stop(&zvp->amrr_ch);
+	ieee80211_amrr_cleanup(&zvp->amrr);
 	ieee80211_vap_detach(vap);
 	free(zvp, M_80211_VAP);
 }
@@ -719,7 +716,6 @@
 	case IEEE80211_S_RUN:
 	{
 		struct ieee80211_node *ni = vap->iv_bss;
-		const struct ieee80211_txparam *tp;
 
 		zyd_set_chan(sc, ic->ic_curchan);
 
@@ -730,19 +726,14 @@
 			/* make data LED blink upon Tx */
 			zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS, 1);
 
-			zyd_set_bssid(sc, ni->ni_bssid);
+			IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
+			zyd_set_bssid(sc, sc->sc_bssid);
 		}
 
 		if (vap->iv_opmode == IEEE80211_M_STA) {
 			/* fake a join to init the tx rate */
 			zyd_newassoc(ni, 1);
 		}
-
-		/* start automatic rate control timer */
-		tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
-		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
-			callout_reset(&zvp->amrr_ch, hz, zyd_amrr_timeout, vap);
-
 		break;
 	}
 	default:
@@ -751,6 +742,11 @@
 
 	IEEE80211_LOCK(ic);	/*XXX*/
 	zvp->newstate(vap, sc->sc_state, sc->sc_arg);
+	if (sc->sc_state == IEEE80211_S_RUN) {
+		/* XXX compensate for deferred handling of newstate */
+		vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+		if_start(vap->iv_ifp);
+	}
 	IEEE80211_UNLOCK(ic);
 }
 
@@ -762,7 +758,6 @@
 	struct zyd_softc *sc = ic->ic_ifp->if_softc;
 
 	usb_rem_task(sc->sc_udev, &sc->sc_task);
-	callout_stop(&zvp->amrr_ch);
 
 	/* do it in a process context */
 	sc->sc_state = nstate;
@@ -1902,7 +1897,8 @@
 		 */
 		ni = ieee80211_find_txnode(vap, retry->macaddr);
 		if (ni != NULL) {
-			ZYD_NODE(ni)->amn.amn_retrycnt++;
+			ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn,
+			    IEEE80211_AMRR_FAILURE, 1);
 			ieee80211_free_node(ni);
 		}
 		if (le16toh(retry->count) & 0x100)
@@ -2230,7 +2226,8 @@
 
 	ni = data->ni;
 	/* update rate control statistics */
-	ZYD_NODE(ni)->amn.amn_txcnt++;
+	ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn,
+	    IEEE80211_AMRR_SUCCESS, 0);
 
 	/*
 	 * Do any tx complete callback.  Note this must
@@ -2278,11 +2275,12 @@
 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 		rate = tp->mcastrate;
 		desc->flags |= ZYD_TX_FLAG_MULTICAST;
-	} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
+	} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
 		rate = tp->ucastrate;
-	else
-		rate = ni->ni_rates.rs_rates[ni->ni_txrate];
-	rate &= IEEE80211_RATE_VAL;
+	} else {
+		(void) ieee80211_amrr_choose(ni, &ZYD_NODE(ni)->amn);
+		rate = ni->ni_txrate;
+	}
 
 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 		k = ieee80211_crypto_encap(ni, m0);
@@ -2385,14 +2383,14 @@
 	struct mbuf *m;
 
 	for (;;) {
-		IFQ_POLL(&ifp->if_snd, m);
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
 		if (m == NULL)
 			break;
 		if (sc->tx_queued >= ZYD_TX_LIST_CNT) {
+			IFQ_DRV_PREPEND(&ifp->if_snd, m);
 			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 			break;
 		}
-		IFQ_DEQUEUE(&ifp->if_snd, m);
 		ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
 		m = ieee80211_encap(ni, m);
 		if (m == NULL) {
@@ -2686,44 +2684,11 @@
 }
 
 static void
-zyd_iter_func(void *arg, struct ieee80211_node *ni)
-{
-	struct ieee80211vap *vap = ni->ni_vap;
-	struct zyd_node *zn = (struct zyd_node *)ni;
-
-	ieee80211_amrr_choose(&ZYD_VAP(vap)->amrr, ni, &zn->amn);
-}
-
-static void
-zyd_amrr_timeout(void *arg)
-{
-	struct ieee80211vap *vap = arg;
-	struct ieee80211com *ic = vap->iv_ic;
-	struct zyd_softc *sc = ic->ic_ifp->if_softc;
-
-	ZYD_LOCK(sc);
-	if (vap->iv_opmode == IEEE80211_M_STA)
-		zyd_iter_func(sc, vap->iv_bss);
-	else
-		ieee80211_iterate_nodes(&ic->ic_sta, zyd_iter_func, sc);
-	ZYD_UNLOCK(sc);
-
-	callout_reset(&ZYD_VAP(vap)->amrr_ch, hz, zyd_amrr_timeout, vap);
-}
-
-static void
 zyd_newassoc(struct ieee80211_node *ni, int isnew)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
-	int i;
 
-	ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn);
-
-	/* set rate to some reasonable initial value */
-	for (i = ni->ni_rates.rs_nrates - 1;
-	     i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
-	     i--);
-	ni->ni_txrate = i;
+	ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni);
 }
 
 static void
@@ -2767,18 +2732,19 @@
 {
 	struct zyd_softc *sc = arg;
 	struct ieee80211com *ic = &sc->sc_ic;
-	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
 	struct ifnet *ifp = ic->ic_ifp;
 
 	ZYD_LOCK(sc);
 
 	switch (sc->sc_scan_action) {
 	case ZYD_SCAN_START:
+		/* want broadcast address while scanning */
                 zyd_set_bssid(sc, ifp->if_broadcastaddr);
                 break;
 
         case ZYD_SCAN_END:
-                zyd_set_bssid(sc, vap->iv_bss->ni_bssid);
+		/* restore previous bssid */
+                zyd_set_bssid(sc, sc->sc_bssid);
                 break;
 
         case ZYD_SET_CHANNEL:

==== //depot/projects/vap/sys/dev/usb/if_zydreg.h#6 (text+ko) ====

@@ -1200,7 +1200,7 @@
 	int				sc_flags;
 	int				sc_if_flags;
 #define ZD1211_FWLOADED (1 << 0)
-
+	uint8_t				sc_bssid[IEEE80211_ADDR_LEN];
 
 	enum ieee80211_state		sc_state;
 	int				sc_arg;


More information about the p4-projects mailing list