PERFORCE change 43213 for review
Sam Leffler
sam at FreeBSD.org
Sun Nov 30 21:37:18 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=43213
Change 43213 by sam at 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'' */
More information about the p4-projects
mailing list