Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 30 Nov 2003 21:37:15 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 43213 for review
Message-ID:  <200312010537.hB15bFnK099281@repoman.freebsd.org>

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

Change 43213 by sam@sam_ebb on 2003/11/30 21:36:21

	o use the multi-rate retry support in the 5212 to retry
	  data frames at the current rate, then a rate one step
	  below the current rate, then falling back to the lowest
	  supported rate; this appears to smooth performance in
	  the presence of noise but there are better algorithms
	o precalculate the conversion from ieee rate to h/w rate
	  cookies

Affected files ...

.. //depot/projects/netperf/sys/dev/ath/if_ath.c#45 edit
.. //depot/projects/netperf/sys/dev/ath/if_athvar.h#10 edit

Differences ...

==== //depot/projects/netperf/sys/dev/ath/if_ath.c#45 (text+ko) ====

@@ -134,6 +134,8 @@
 
 static int	ath_rate_setup(struct ath_softc *sc, u_int mode);
 static void	ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
+static void	ath_rate_update(struct ath_softc *, struct ieee80211_node *,
+			int rate);
 static void	ath_rate_ctl_reset(struct ath_softc *, enum ieee80211_state);
 static void	ath_rate_ctl(void *, struct ieee80211_node *);
 
@@ -1908,6 +1910,20 @@
 	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
 
 	/*
+	 * NB: the 802.11 layer marks whether or not we should
+	 * use short preamble based on the current mode and
+	 * negotiated parameters.
+	 */
+	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
+	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
+		shortPreamble = AH_TRUE;
+		sc->sc_stats.ast_tx_shortpre++;
+	} else {
+		shortPreamble = AH_FALSE;
+	}
+
+	an = (struct ath_node *) ni;
+	/*
 	 * Calculate Atheros packet type from IEEE80211 packet header
 	 * and setup for rate calculations.
 	 */
@@ -1922,16 +1938,23 @@
 		else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM)
 			atype = HAL_PKT_TYPE_ATIM;
 		rix = 0;			/* XXX lowest rate */
+		if (shortPreamble)
+			txrate = an->an_tx_mgtrate;
+		else
+			txrate = an->an_tx_mgtratesp;
 		break;
 	case IEEE80211_FC0_TYPE_CTL:
 		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 		if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL)
 			atype = HAL_PKT_TYPE_PSPOLL;
 		rix = 0;			/* XXX lowest rate */
+		if (shortPreamble)
+			txrate = an->an_tx_mgtrate;
+		else
+			txrate = an->an_tx_mgtratesp;
 		break;
 	default:
-		rix = sc->sc_rixmap[ni->ni_rates.rs_rates[ni->ni_txrate] &
-				IEEE80211_RATE_VAL];
+		rix = an->an_tx_rix0;
 		if (rix == 0xff) {
 			if_printf(ifp, "bogus xmit rate 0x%x\n",
 				ni->ni_rates.rs_rates[ni->ni_txrate]);
@@ -1939,22 +1962,12 @@
 			m_freem(m0);
 			return EIO;
 		}
+		if (shortPreamble)
+			txrate = an->an_tx_rate0;
+		else
+			txrate = an->an_tx_rate0sp;
 		break;
 	}
-	/*
-	 * NB: the 802.11 layer marks whether or not we should
-	 * use short preamble based on the current mode and
-	 * negotiated parameters.
-	 */
-	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
-	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
-		txrate = rt->info[rix].rateCode | rt->info[rix].shortPreamble;
-		shortPreamble = AH_TRUE;
-		sc->sc_stats.ast_tx_shortpre++;
-	} else {
-		txrate = rt->info[rix].rateCode;
-		shortPreamble = AH_FALSE;
-	}
 
 	/*
 	 * Calculate miscellaneous flags.
@@ -2023,7 +2036,6 @@
 	 * initialized to 0 which gives us ``auto'' or the
 	 * ``default'' antenna.
 	 */
-	an = (struct ath_node *) ni;
 	if (an->an_tx_antenna)
 		antenna = an->an_tx_antenna;
 	else
@@ -2054,21 +2066,31 @@
 		, hdrlen		/* header length */
 		, atype			/* Atheros packet type */
 		, 60			/* txpower XXX */
-		, txrate, 1+10		/* series 0 rate/tries */
+		, txrate, 1+3		/* series 0 rate/tries */
 		, iswep ? sc->sc_ic.ic_wep_txkey : HAL_TXKEYIX_INVALID
 		, antenna		/* antenna mode */
 		, flags			/* flags */
 		, ctsrate		/* rts/cts rate */
 		, ctsduration		/* rts/cts duration */
 	);
-#ifdef notyet
-	ath_hal_setupxtxdesc(ah, ds
-		, AH_FALSE		/* short preamble */
-		, 0, 0			/* series 1 rate/tries */
-		, 0, 0			/* series 2 rate/tries */
-		, 0, 0			/* series 3 rate/tries */
-	);
-#endif
+	if (rix != 0) {
+		if (shortPreamble) {
+			ath_hal_setupxtxdesc(ah, ds
+				, AH_TRUE		/* short preamble */
+				, an->an_tx_rate1sp, 2	/* series 1 */
+				, an->an_tx_rate2sp, 2	/* series 2 */
+				, an->an_tx_rate3sp, 2	/* series 3 */
+			);
+		} else {
+			ath_hal_setupxtxdesc(ah, ds
+				, AH_FALSE		/* no short preamble */
+				, an->an_tx_rate1, 2	/* series 1 */
+				, an->an_tx_rate2, 2	/* series 2 */
+				, an->an_tx_rate3, 2	/* series 3 */
+			);
+		}
+	}
+
 	/*
 	 * Fillin the remainder of the descriptor info.
 	 */
@@ -2551,10 +2573,6 @@
 ath_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
 {
 	if (isnew) {
-		struct ath_node *an = (struct ath_node *) ni;
-
-		an->an_tx_ok = an->an_tx_err =
-			an->an_tx_retr = an->an_tx_upper = 0;
 		/* start with highest negotiated rate */
 		/*
 		 * XXX should do otherwise but only when
@@ -2562,7 +2580,8 @@
 		 */
 		KASSERT(ni->ni_rates.rs_nrates > 0,
 			("new association w/ no rates!"));
-		ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
+		ath_rate_update((struct ath_softc *)ic, ni,
+			ni->ni_rates.rs_nrates - 1);
 	}
 }
 
@@ -2671,8 +2690,60 @@
 		sc->sc_hwmap[i] = rt->info[rt->rateCodeToIndex[i]].dot11Rate;
 	sc->sc_currates = rt;
 	sc->sc_curmode = mode;
+	/* NB: caller is responsible for reseting rate control state */
 }
 
+static void
+ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
+{
+	struct ath_node *an = (struct ath_node *) ni;
+	const HAL_RATE_TABLE *rt = sc->sc_currates;
+	u_int8_t rix;
+
+	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+
+	ni->ni_txrate = rate;
+	an->an_tx_rix0 = sc->sc_rixmap[
+		ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
+	an->an_tx_rate0 = rt->info[an->an_tx_rix0].rateCode;
+	an->an_tx_rate0sp = an->an_tx_rate0 |
+		rt->info[an->an_tx_rix0].shortPreamble;
+	/* XXX management/control frames always go at the lowest speed */
+	an->an_tx_mgtrate = rt->info[0].rateCode;
+	an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].shortPreamble;
+	if (--rate >= 0) {
+		rix = sc->sc_rixmap[
+			ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
+		an->an_tx_rate1 = rt->info[rix].rateCode;
+		an->an_tx_rate1sp = an->an_tx_rate1 |
+			rt->info[rix].shortPreamble;
+	} else
+		an->an_tx_rate1 = 0;
+#if 0
+	if (--rate >= 0) {
+		rix = sc->sc_rixmap[
+			ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
+		an->an_tx_rate2 = rt->info[rix].rateCode;
+		an->an_tx_rate2sp = an->an_tx_rate2 |
+			rt->info[rix].shortPreamble;
+	} else
+		an->an_tx_rate2 = 0;
+	if (--rate >= 0) {
+		rix = sc->sc_rixmap[
+			ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
+		an->an_tx_rate3 = rt->info[rix].rateCode;
+		an->an_tx_rate3sp = an->an_tx_rate3 |
+			rt->info[rix].shortPreamble;
+	} else
+		an->an_tx_rate3 = 0;
+#else
+	an->an_tx_rate2 = an->an_tx_mgtrate;
+	an->an_tx_rate2sp = an->an_tx_mgtratesp;
+	an->an_tx_rate3 = an->an_tx_rate3sp = 0;
+#endif
+	an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
+}
+
 /*
  * Reset the rate control state for each 802.11 state transition.
  */
@@ -2681,7 +2752,6 @@
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_node *ni;
-	struct ath_node *an;
 
 	if (ic->ic_opmode != IEEE80211_M_STA) {
 		/*
@@ -2690,28 +2760,21 @@
 		 * For any other operating mode we want to reset the
 		 * tx rate state of each node.
 		 */
-		TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
-			ni->ni_txrate = 0;		/* use lowest rate */
-			an = (struct ath_node *) ni;
-			an->an_tx_ok = an->an_tx_err = an->an_tx_retr =
-			    an->an_tx_upper = 0;
-		}
+		TAILQ_FOREACH(ni, &ic->ic_node, ni_list)
+			ath_rate_update(sc, ni, 0);	/* use lowest rate */
 	}
 	/*
 	 * Reset local xmit state; this is really only meaningful
 	 * when operating in station or adhoc mode.
 	 */
 	ni = ic->ic_bss;
-	an = (struct ath_node *) ni;
-	an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
 	if (state == IEEE80211_S_RUN) {
 		/* start with highest negotiated rate */
 		KASSERT(ni->ni_rates.rs_nrates > 0,
 			("transition to RUN state w/ no rates!"));
-		ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
+		ath_rate_update(sc, ni, ni->ni_rates.rs_nrates - 1);
 	} else {
-		/* use lowest rate */
-		ni->ni_txrate = 0;
+		ath_rate_update(sc, ni, 0);		/* use lowest rate */
 	}
 }
 
@@ -2724,7 +2787,7 @@
 	struct ath_softc *sc = arg;
 	struct ath_node *an = (struct ath_node *) ni;
 	struct ieee80211_rateset *rs = &ni->ni_rates;
-	int mod = 0, orate, enough;
+	int mod = 0, nrate, enough;
 
 	/*
 	 * Rate control
@@ -2746,15 +2809,15 @@
 	if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10)
 		mod = 1;
 
-	orate = ni->ni_txrate;
+	nrate = ni->ni_txrate;
 	switch (mod) {
 	case 0:
 		if (enough && an->an_tx_upper > 0)
 			an->an_tx_upper--;
 		break;
 	case -1:
-		if (ni->ni_txrate > 0) {
-			ni->ni_txrate--;
+		if (nrate > 0) {
+			nrate--;
 			sc->sc_stats.ast_rate_drop++;
 		}
 		an->an_tx_upper = 0;
@@ -2763,21 +2826,21 @@
 		if (++an->an_tx_upper < 2)
 			break;
 		an->an_tx_upper = 0;
-		if (ni->ni_txrate + 1 < rs->rs_nrates) {
-			ni->ni_txrate++;
+		if (nrate + 1 < rs->rs_nrates) {
+			nrate++;
 			sc->sc_stats.ast_rate_raise++;
 		}
 		break;
 	}
 
-	if (ni->ni_txrate != orate) {
+	if (nrate != ni->ni_txrate) {
 		DPRINTF(("%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
 		    __func__,
-		    (rs->rs_rates[orate] & IEEE80211_RATE_VAL) / 2,
 		    (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2,
+		    (rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2,
 		    an->an_tx_ok, an->an_tx_err, an->an_tx_retr));
-	}
-	if (ni->ni_txrate != orate || enough)
+		ath_rate_update(sc, ni, nrate);
+	} else if (enough)
 		an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0;
 }
 

==== //depot/projects/netperf/sys/dev/ath/if_athvar.h#10 (text+ko) ====

@@ -70,6 +70,17 @@
 	u_int		an_tx_retr;	/* tx retry count */
 	int		an_tx_upper;	/* tx upper rate req cnt */
 	u_int		an_tx_antenna;	/* antenna for last good frame */
+	u_int8_t	an_tx_rix0;	/* series 0 rate index */
+	u_int8_t	an_tx_mgtrate;	/* h/w rate for management/ctl frames */
+	u_int8_t	an_tx_mgtratesp;/* short preamble h/w rate for " " */
+	u_int8_t	an_tx_rate0;	/* series 0 h/w rate */
+	u_int8_t	an_tx_rate1;	/* series 1 h/w rate */
+	u_int8_t	an_tx_rate2;	/* series 2 h/w rate */
+	u_int8_t	an_tx_rate3;	/* series 3 h/w rate */
+	u_int8_t	an_tx_rate0sp;	/* series 0 short preamble h/w rate */
+	u_int8_t	an_tx_rate1sp;	/* series 1 short preamble h/w rate */
+	u_int8_t	an_tx_rate2sp;	/* series 2 short preamble h/w rate */
+	u_int8_t	an_tx_rate3sp;	/* series 3 short preamble h/w rate */
 	u_int		an_rx_antenna;	/* antenna for last rcvd frame */
 	struct ath_recv_hist an_rx_hist[ATH_RHIST_SIZE];
 	u_int		an_rx_hist_next;/* index of next ``free entry'' */



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