From owner-p4-projects@FreeBSD.ORG Sun Nov 30 21:37:18 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D334C16A4D0; Sun, 30 Nov 2003 21:37:17 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AC3D416A4CE for ; Sun, 30 Nov 2003 21:37:17 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1546343FBF for ; Sun, 30 Nov 2003 21:37:16 -0800 (PST) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.9/8.12.9) with ESMTP id hB15bFXJ099284 for ; Sun, 30 Nov 2003 21:37:15 -0800 (PST) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.9/8.12.9/Submit) id hB15bFnK099281 for perforce@freebsd.org; Sun, 30 Nov 2003 21:37:15 -0800 (PST) (envelope-from sam@freebsd.org) Date: Sun, 30 Nov 2003 21:37:15 -0800 (PST) Message-Id: <200312010537.hB15bFnK099281@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 43213 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Dec 2003 05:37:18 -0000 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'' */