This switches athn(4) to the new RA Tx rate adaptation module. Tests on athn(4) PCI devices are welcome. USB devices don't need to be tested in this case Tx rate adaptation is taken care of by firmware.
I could only test on AR9285 so far, but the result looks promising. diff c6a6a64b49f2287751632205d64f594eb6c1ee42 636e9964c6e5313bb1c75823249d483597a0e93a blob - 43169fcccf130b28c5b2e0a95e1b7689244e43d5 blob + 2a8e9aacae52a047979890b95c2880a004b2495b --- sys/dev/cardbus/if_athn_cardbus.c +++ sys/dev/cardbus/if_athn_cardbus.c @@ -43,7 +43,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - 3c11b4c004b4dd5fb12e7789f74bfb3e346b7acf blob + bbe145570c10ef1466c23ae70f626634bd8d354d --- sys/dev/ic/ar5008.c +++ sys/dev/ic/ar5008.c @@ -51,7 +51,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> @@ -1064,7 +1064,7 @@ ar5008_tx_process(struct athn_softc *sc, int qid) struct athn_tx_buf *bf; struct ar_tx_desc *ds; uint8_t failcnt; - int txfail; + int txfail = 0, rtscts; bf = SIMPLEQ_FIRST(&txq->head); if (bf == NULL) @@ -1079,13 +1079,15 @@ ar5008_tx_process(struct athn_softc *sc, int qid) sc->sc_tx_timer = 0; - txfail = (ds->ds_status1 & AR_TXS1_EXCESSIVE_RETRIES); - if (txfail) - ifp->if_oerrors++; + /* These status bits are valid if “FRM_XMIT_OK” is clear. */ + if ((ds->ds_status1 & AR_TXS1_FRM_XMIT_OK) == 0) { + txfail = (ds->ds_status1 & AR_TXS1_EXCESSIVE_RETRIES); + if (txfail) + ifp->if_oerrors++; + if (ds->ds_status1 & AR_TXS1_UNDERRUN) + athn_inc_tx_trigger_level(sc); + } - if (ds->ds_status1 & AR_TXS1_UNDERRUN) - athn_inc_tx_trigger_level(sc); - an = (struct athn_node *)bf->bf_ni; ni = (struct ieee80211_node *)bf->bf_ni; @@ -1094,33 +1096,51 @@ ar5008_tx_process(struct athn_softc *sc, int qid) * for the final series used. We must add the number of tries for * each series that was fully processed to punish transmit rates in * the earlier series which did not perform well. - * If RTS/CTS was used, each series used the same transmit rate. - * Ignore the series count in this case, since each series had - * the same chance of success. */ failcnt = MS(ds->ds_status1, AR_TXS1_DATA_FAIL_CNT); - if (!(ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE))) { - /* NB: Assume two tries per series. */ - failcnt += MS(ds->ds_status9, AR_TXS9_FINAL_IDX) * 2; - } + /* Assume two tries per series, as per AR_TXC2_XMIT_DATA_TRIESx. */ + failcnt += MS(ds->ds_status9, AR_TXS9_FINAL_IDX) * 2; + rtscts = (ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE)); + /* Update rate control statistics. */ - if (ni->ni_flags & IEEE80211_NODE_HT) { - an->mn.frames++; - an->mn.ampdu_size = bf->bf_m->m_pkthdr.len + IEEE80211_CRC_LEN; - an->mn.agglen = 1; /* XXX We do not yet support Tx agg. */ - if (failcnt > 0) - an->mn.retries += failcnt; - if (txfail) - an->mn.txfail++; + if ((ni->ni_flags & IEEE80211_NODE_HT) && ic->ic_fixed_mcs == -1) { + const struct ieee80211_ht_rateset *rs = + ieee80211_ra_get_ht_rateset(bf->bf_txmcs, + ieee80211_node_supports_ht_sgi20(ni)); + unsigned int retries = 0, i; + int mcs = bf->bf_txmcs; + + /* With RTS/CTS each Tx series used the same MCS. */ + if (rtscts) { + retries = failcnt; + } else { + for (i = 0; i < failcnt; i++) { + if (mcs > rs->min_mcs) { + ieee80211_ra_add_stats_ht(&an->rn, + ic, ni, mcs, 1, 1); + if (i % 2) /* two tries per series */ + mcs--; + } else + retries++; + } + } + + if (txfail && retries == 0) { + ieee80211_ra_add_stats_ht(&an->rn, ic, ni, + mcs, 1, 1); + } else { + ieee80211_ra_add_stats_ht(&an->rn, ic, ni, + mcs, retries + 1, retries); + } if (ic->ic_state == IEEE80211_S_RUN) { #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode != IEEE80211_M_HOSTAP || ni->ni_state == IEEE80211_STA_ASSOC) #endif - ieee80211_mira_choose(&an->mn, ic, ni); + ieee80211_ra_choose(&an->rn, ic, ni); } - } else { + } else if (ic->ic_fixed_rate == -1) { an->amn.amn_txcnt++; if (failcnt > 0) an->amn.amn_retrycnt++; @@ -1492,11 +1512,6 @@ ar5008_tx(struct athn_softc *sc, struct mbuf *m, struc /* Use same fixed rate for all tries. */ ridx[0] = ridx[1] = ridx[2] = ridx[3] = sc->fixed_ridx; - } else if ((ni->ni_flags & IEEE80211_NODE_HT) && - ieee80211_mira_is_probing(&an->mn)) { - /* Use same fixed rate for all tries. */ - ridx[0] = ridx[1] = ridx[2] = ridx[3] = - ATHN_RIDX_MCS0 + ni->ni_txmcs; } else { /* Use fallback table of the node. */ int txrate; @@ -1562,6 +1577,7 @@ ar5008_tx(struct athn_softc *sc, struct mbuf *m, struc } bf->bf_m = m; bf->bf_ni = ni; + bf->bf_txmcs = ni->ni_txmcs; bf->bf_txflags = txflags; wh = mtod(m, struct ieee80211_frame *); @@ -1607,16 +1623,12 @@ ar5008_tx(struct athn_softc *sc, struct mbuf *m, struc if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { - int rtsthres = ic->ic_rtsthreshold; enum ieee80211_htprot htprot; - if (ni->ni_flags & IEEE80211_NODE_HT) - rtsthres = ieee80211_mira_get_rts_threshold(&an->mn, - ic, ni, totlen); htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK); /* NB: Group frames are sent using CCK in 802.11b/g. */ - if (totlen > rtsthres) { + if (totlen > ic->ic_rtsthreshold) { ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE; } else if (((ic->ic_flags & IEEE80211_F_USEPROT) && athn_rates[ridx[0]].phy == IEEE80211_T_OFDM) || blob - c2b0d05b3fe2f8b721790c3a0955028c7d36e923 blob + 830f460f211fb2f0c84b482cdada36cdec4cbc4c --- sys/dev/ic/ar5416.c +++ sys/dev/ic/ar5416.c @@ -51,7 +51,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - 14a7f15c8a72ad9d97c59433cfd811f6de4d2214 blob + 0db7b5f5520a3d4e1ebf0039157bbe55ead103a1 --- sys/dev/ic/ar9003.c +++ sys/dev/ic/ar9003.c @@ -51,7 +51,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - acb00c62ed242d348010edb679bcc289a0c9cd7f blob + 91071ffff1e0408b552cb2d60ac4888c4d5edbc6 --- sys/dev/ic/ar9280.c +++ sys/dev/ic/ar9280.c @@ -51,7 +51,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - 057ea48e06ba07e29d1d055a29231cab2cef5616 blob + e4aaa701edc2d5bf1d3ec7a219ed097d8278fdd2 --- sys/dev/ic/ar9285.c +++ sys/dev/ic/ar9285.c @@ -52,7 +52,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - df89bf7d767b94c6089fee763c21c0dece84f4b9 blob + d46441f4677ed3962867068828b2ff88e56e0d7d --- sys/dev/ic/ar9287.c +++ sys/dev/ic/ar9287.c @@ -51,7 +51,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - 34cead5782df98ee5b8ae5b0ca3d0beefc9b5864 blob + 7fc464067a5b8780137a01091e0b0eba9e443099 --- sys/dev/ic/ar9380.c +++ sys/dev/ic/ar9380.c @@ -49,7 +49,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - d20bb5615c20f30c2d7bc1bc4bfc66370dfeb232 blob + f410a488af23f47eb7900394a5e23e27924d033b --- sys/dev/ic/athn.c +++ sys/dev/ic/athn.c @@ -53,7 +53,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> @@ -127,11 +127,8 @@ int athn_hw_reset(struct athn_softc *, struct ieee802 struct ieee80211_node *athn_node_alloc(struct ieee80211com *); void athn_newassoc(struct ieee80211com *, struct ieee80211_node *, int); -void athn_node_leave(struct ieee80211com *, struct ieee80211_node *); int athn_media_change(struct ifnet *); void athn_next_scan(void *); -void athn_iter_mira_delete(void *, struct ieee80211_node *); -void athn_delete_mira_nodes(struct athn_softc *); int athn_newstate(struct ieee80211com *, enum ieee80211_state, int); void athn_updateedca(struct ieee80211com *); @@ -379,9 +376,6 @@ athn_attach(struct athn_softc *sc) if_attach(ifp); ieee80211_ifattach(ifp); ic->ic_node_alloc = athn_node_alloc; -#ifndef IEEE80211_STA_ONLY - ic->ic_node_leave = athn_node_leave; -#endif ic->ic_newassoc = athn_newassoc; ic->ic_updateslot = athn_updateslot; ic->ic_updateedca = athn_updateedca; @@ -404,13 +398,10 @@ void athn_detach(struct athn_softc *sc) { struct ifnet *ifp = &sc->sc_ic.ic_if; - struct ieee80211com *ic = &sc->sc_ic; int qid; timeout_del(&sc->scan_to); timeout_del(&sc->calib_to); - if (ic->ic_flags & IEEE80211_F_HTON) - athn_delete_mira_nodes(sc); if (!(sc->flags & ATHN_FLAG_USB)) { for (qid = 0; qid < ATHN_QID_COUNT; qid++) @@ -2479,7 +2470,7 @@ athn_node_alloc(struct ieee80211com *ic) an = malloc(sizeof(struct athn_node), M_DEVBUF, M_NOWAIT | M_ZERO); if (an && (ic->ic_flags & IEEE80211_F_HTON)) - ieee80211_mira_node_init(&an->mn); + ieee80211_ra_node_init(&an->rn); return (struct ieee80211_node *)an; } @@ -2495,7 +2486,7 @@ athn_newassoc(struct ieee80211com *ic, struct ieee8021 if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) ieee80211_amrr_node_init(&sc->amrr, &an->amn); else if (ic->ic_opmode == IEEE80211_M_STA) - ieee80211_mira_node_init(&an->mn); + ieee80211_ra_node_init(&an->rn); /* Start at lowest available bit-rate, AMRR will raise. */ ni->ni_txrate = 0; @@ -2552,16 +2543,6 @@ athn_newassoc(struct ieee80211com *ic, struct ieee8021 } } -#ifndef IEEE80211_STA_ONLY -void -athn_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni) -{ - struct athn_node *an = (void *)ni; - if (ic->ic_flags & IEEE80211_F_HTON) - ieee80211_mira_cancel_timeouts(&an->mn); -} -#endif - int athn_media_change(struct ifnet *ifp) { @@ -2604,26 +2585,6 @@ athn_next_scan(void *arg) splx(s); } -void -athn_iter_mira_delete(void *arg, struct ieee80211_node *ni) -{ - struct athn_node *an = (struct athn_node *)ni; - ieee80211_mira_cancel_timeouts(&an->mn); -} - -/* Delete pending timeouts managed by MiRA. */ -void -athn_delete_mira_nodes(struct athn_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - - if (ic->ic_opmode == IEEE80211_M_STA) { - struct athn_node *an = (struct athn_node *)ic->ic_bss; - ieee80211_mira_cancel_timeouts(&an->mn); - } else - ieee80211_iterate_nodes(ic, athn_iter_mira_delete, sc); -} - int athn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) { @@ -2634,10 +2595,6 @@ athn_newstate(struct ieee80211com *ic, enum ieee80211_ timeout_del(&sc->calib_to); - if ((ic->ic_flags & IEEE80211_F_HTON) && - ic->ic_state == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) - athn_delete_mira_nodes(sc); - switch (nstate) { case IEEE80211_S_INIT: athn_set_led(sc, 0); blob - c21c69794415adb83a18fc08809ff718d85af409 blob + da86bf73ce43f3278abd049a08e15b73d8a74e33 --- sys/dev/ic/athnvar.h +++ sys/dev/ic/athnvar.h @@ -79,6 +79,7 @@ struct athn_tx_buf { struct mbuf *bf_m; struct ieee80211_node *bf_ni; + int bf_txmcs; int bf_txflags; #define ATHN_TXFLAG_PAPRD (1 << 0) #define ATHN_TXFLAG_CAB (1 << 1) @@ -295,7 +296,7 @@ static const uint16_t ar_mcs_ndbps[][2] = { struct athn_node { struct ieee80211_node ni; struct ieee80211_amrr_node amn; - struct ieee80211_mira_node mn; + struct ieee80211_ra_node rn; uint8_t ridx[ATHN_NUM_RATES]; uint8_t fallback[ATHN_NUM_RATES]; uint8_t sta_index; blob - 874f3523b5eff7240135126401c71d3a34395317 blob + b7c75ef72cdd787b4bda3264ba603e86061c1985 --- sys/dev/pci/if_athn_pci.c +++ sys/dev/pci/if_athn_pci.c @@ -43,7 +43,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h> blob - 771baafcdac926e3752111a37d6963447775c8ab blob + 3655df8bade95c8e7d42cf9216412470913c08c5 --- sys/dev/usb/if_athn_usb.c +++ sys/dev/usb/if_athn_usb.c @@ -49,7 +49,7 @@ #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_mira.h> +#include <net80211/ieee80211_ra.h> #include <net80211/ieee80211_radiotap.h> #include <dev/ic/athnreg.h>