53#include <sys/sysctl.h>
54#include <sys/kernel.h>
56#include <sys/malloc.h>
60#include <machine/bus.h>
61#include <machine/resource.h>
64#include <sys/socket.h>
67#include <net/if_var.h>
68#include <net/if_media.h>
69#include <net/if_arp.h>
70#include <net/ethernet.h>
72#include <net80211/ieee80211_var.h>
77#include <netinet/in.h>
78#include <netinet/if_ether.h>
113#define MCS_HT20_SGI 1
115#define MCS_HT40_SGI 3
137 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
138 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
139 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
140 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
143 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
144 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
145 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
146 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
149 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
150 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
151 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
152 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
155 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
156 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
157 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
158 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
176 struct ath_node *an, uint8_t rix0,
int is_aggr)
178#define MCS_IDX(ix) (rt->info[ix].dot11Rate)
182 int max_pkt_length = 65530;
184 int is_ht40 = (an->
an_node.ni_chw == 40);
188 if (rt->
info[rix0].
phy != IEEE80211_T_HT) {
196 KASSERT(rix0 == sched->
r0, (
"rix0 (%x) != sched->r0 (%x)!\n",
223 if (sched->
t0 != 0) {
224 max_pkt_length =
MIN(max_pkt_length,
227 if (sched->
t1 != 0) {
228 max_pkt_length =
MIN(max_pkt_length,
231 if (sched->
t2 != 0 && (! is_aggr)) {
232 max_pkt_length =
MIN(max_pkt_length,
235 if (sched->
t3 != 0 && (! is_aggr)) {
236 max_pkt_length =
MIN(max_pkt_length,
240 return max_pkt_length;
249#if NUM_PACKET_SIZE_BINS > 1
253#if NUM_PACKET_SIZE_BINS > 2
257#if NUM_PACKET_SIZE_BINS > 3
261#if NUM_PACKET_SIZE_BINS > 4
265#if NUM_PACKET_SIZE_BINS > 5
269#if NUM_PACKET_SIZE_BINS > 6
273#if NUM_PACKET_SIZE_BINS > 7
277#if NUM_PACKET_SIZE_BINS > 8
278#error "add support for more packet sizes"
299 return rt->
info[rix].
phy == IEEE80211_T_HT ?
308 return rt->
info[rix].
phy == IEEE80211_T_HT ?
"MCS" :
"Mb ";
317 int size_bin,
int require_acked_before)
320 int best_rate_rix, best_rate_tt, best_rate_pct;
327 for (mask = sn->
ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
332 if ((an->
an_node.ni_flags & IEEE80211_NODE_HT) &&
333 (rt->
info[rix].
phy != IEEE80211_T_HT)) {
339 (require_acked_before &&
361 if (an->
an_node.ni_flags & IEEE80211_NODE_HT) {
365 IEEE80211_NOTE(an->
an_node.ni_vap,
366 IEEE80211_MSG_RATECTL,
368 "%s: size %d comparing best rate 0x%x pkts/ewma/tt (%ju/%d/%d) "
369 "to 0x%x pkts/ewma/tt (%ju/%d/%d)",
381 if (best_rate_pct > (pct + 50))
388 if (! (an->
an_node.ni_flags & IEEE80211_NODE_HT)) {
389 if (best_rate_tt == 0 || tt <= best_rate_tt) {
401 if (an->
an_node.ni_flags & IEEE80211_NODE_HT) {
402 if (best_rate_tt == 0 || ((tt * 10) <= (best_rate_tt * 10))) {
409 return (best_rate_tt ? best_rate_rix : -1);
419#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
420#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
438 if ((mask & ((uint64_t) 1<<rix)) == 0) {
462 if ((an->
an_node.ni_flags & IEEE80211_NODE_HT) &&
463 (rt->
info[rix].
phy != IEEE80211_T_HT)) {
464 mask &= ~((uint64_t) 1<<rix);
471 mask &= ~((uint64_t) 1<<rix);
478 mask &= ~((uint64_t) 1<<rix);
493 if (an->
an_node.ni_flags & IEEE80211_NODE_HT) {
494 uint8_t current_mcs, rix_mcs;
497 rix_mcs =
MCS(rix) & 0x7;
499 if (rix_mcs < (current_mcs - 2) ||
500 rix_mcs > (current_mcs + 2)) {
501 mask &= ~((uint64_t) 1<<rix);
507 if (! (an->
an_node.ni_flags & IEEE80211_NODE_HT)) {
509 mask &= ~((uint64_t) 1<<rix);
525#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
526#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
527#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
528 const struct ieee80211_txparam *tp = ni->ni_txparms;
532 for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) {
533 if (
MCS(srate) == tp->ucastrate)
538 for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) {
539 if (
RATE(srate) == tp->ucastrate)
552 const struct ieee80211_txparam *tp = ni->ni_txparms;
555 if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
576#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
577#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
578#define RATE(ix) (DOT11RATE(ix) / 2)
585 for (rix = rt->
rateCount-1; rix > 0; rix--) {
586 if ((sn->
ratemask & ((uint64_t) 1<<rix)) == 0)
590 if (rt->
info[rix].
phy == IEEE80211_T_HT)
617#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
618#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
619#define RATE(ix) (DOT11RATE(ix) / 2)
620 int rix = -1, ht_rix = -1;
626 for (rix = rt->
rateCount-1; rix > 0; rix--) {
628 if ((sn->
ratemask & ((uint64_t) 1<<rix)) == 0)
632 if (rt->
info[rix].
phy == IEEE80211_T_HT)
636 if (rt->
info[rix].
phy != IEEE80211_T_HT)
644 if (((
MCS(rix)& 0x7f) <= 4) &&
654 return MAX(rix, ht_rix);
662 int shortPreamble,
size_t frameLen,
int tid,
663 int is_aggr, u_int8_t *rix0,
int *try0,
664 u_int8_t *txrate,
int *maxdur,
int *maxpktlen)
666#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
667#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
668#define RATE(ix) (DOT11RATE(ix) / 2)
671 struct ieee80211com *ic = &sc->
sc_ic;
674 int rix, mrr, best_rix, change_rates;
675 unsigned average_tx_time;
687 *maxpktlen = frameLen;
690 device_printf(sc->
sc_dev,
"%s: currates != sc_currates!\n",
707 if (max_pkt_len > 0) {
708 *maxpktlen = frameLen =
MIN(frameLen, max_pkt_len);
717 if (mrr && (ic->ic_flags & IEEE80211_F_USEPROT && !sc->
sc_mrrprot))
729 if (max_pkt_len > 0) {
732 "Limiting maxpktlen from %d to %d bytes\n",
733 (
int) frameLen, max_pkt_len);
735 *maxpktlen = frameLen =
MIN(frameLen, max_pkt_len);
753 IEEE80211_NOTE(an->
an_node.ni_vap, IEEE80211_MSG_RATECTL,
754 &an->
an_node,
"att %d sample_tt %d size %u "
755 "sample rate %d %s current rate %d %s",
774 if (an->
an_node.ni_flags & IEEE80211_NODE_HT)
782 IEEE80211_NOTE(an->
an_node.ni_vap,
783 IEEE80211_MSG_RATECTL, &an->
an_node,
784 "%s: switching quickly..", __func__);
788 IEEE80211_NOTE(an->
an_node.ni_vap,
789 IEEE80211_MSG_RATECTL, &an->
an_node,
790 "%s: min_switch %d > ticks_since_switch %d..",
793 }
else if ((! (an->
an_node.ni_flags & IEEE80211_NODE_HT)) &&
794 (2*average_tx_time < sn->stats[size_bin][sn->
current_rix[size_bin]].average_tx_time)) {
796 IEEE80211_NOTE(an->
an_node.ni_vap,
797 IEEE80211_MSG_RATECTL, &an->
an_node,
798 "%s: 2x att (= %d) < cur_rix att %d",
802 }
else if ((an->
an_node.ni_flags & IEEE80211_NODE_HT)) {
813 printf(
"cur rix/att %x/%d, best rix/att %x/%d\n",
814 MCS(cur_rix), cur_att,
MCS(best_rix), average_tx_time);
816 if ((best_rix != cur_rix) &&
817 (average_tx_time * 9) <= (cur_att * 10)) {
818 IEEE80211_NOTE(an->
an_node.ni_vap,
819 IEEE80211_MSG_RATECTL, &an->
an_node,
820 "%s: HT: size %d best_rix 0x%x > "
821 " cur_rix 0x%x, average_tx_time %d,"
824 MCS(best_rix),
MCS(cur_rix),
825 average_tx_time, cur_att);
834 IEEE80211_NOTE(an->
an_node.ni_vap,
835 IEEE80211_MSG_RATECTL,
837"%s: size %d switch rate %d %s (%d/%d) EWMA %d -> %d %s (%d/%d) EWMA %d after %d packets mrr %d",
860 (rt->
info[best_rix].
phy == IEEE80211_T_HT) ?
876 printf(
"%s: ERROR: rix %d out of bounds (rateCount=%d)\n",
882 KASSERT(rix >= 0 && rix < rt->rateCount, (
"rix is %d", rix));
905 KASSERT(rix0 == sched->
r0, (
"rix0 (%x) != sched->r0 (%x)!\n",
910 rc[0].
rix = sched->
r0;
911 rc[1].
rix = sched->
r1;
912 rc[2].
rix = sched->
r2;
913 rc[3].
rix = sched->
r3;
928 struct ath_desc *ds,
int shortPreamble, u_int8_t rix)
933 uint8_t rix1, s1code, rix2, s2code, rix3, s3code;
966 int rix0,
int tries0,
967 int short_tries,
int tries,
int status,
968 int nframes,
int nbad)
972#ifdef IEEE80211_DEBUG
978 int is_ht40 = (an->
an_node.ni_chw == 40);
989 if (tries > tries0) {
1009 0 ,
MIN(tries0, tries) - 1, is_ht40);
1023 if (nframes == nbad) {
1038 pct = ((nframes - nbad) * 1000) / nframes;
1062 IEEE80211_NOTE(an->
an_node.ni_vap, IEEE80211_MSG_RATECTL,
1064 "%s: size %d %s %s rate %d %s tries (%d/%d) tt %d "
1065 "avg_tt (%d/%d) nfrm %d nbad %d",
1068 status ?
"FAIL" :
"OK",
1072 short_tries, tries, tt,
1087 device_printf(sc->
sc_dev,
1088 "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
1089 series, hwrate, tries, status);
1095 int frame_size,
int rc_framesize,
int nframes,
int nbad)
1097 struct ieee80211com *ic = &sc->
sc_ic;
1099 int final_rix, short_tries, long_tries;
1109 device_printf(sc->
sc_dev,
"%s: nframes=0?\n", __func__);
1113 if (frame_size == 0)
1115 if (rc_framesize == 0)
1116 rc_framesize = 1500;
1142 device_printf(sc->
sc_dev,
1143 "%s: completed but frame size buckets mismatch "
1144 "(completed %d tx'ed %d)\n",
1145 __func__, frame_size, rc_framesize);
1147 frame_size = rc_framesize;
1151 IEEE80211_NOTE(an->
an_node.ni_vap, IEEE80211_MSG_RATECTL,
1153 "%s: size %d %s rate/try %d/%d no rates yet",
1156 status ?
"FAIL" :
"OK",
1157 short_tries, long_tries);
1162 if (mrr && (ic->ic_flags & IEEE80211_F_USEPROT && !sc->
sc_mrrprot))
1167 device_printf(sc->
sc_dev,
1168 "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
1176 IEEE80211_NOTE(an->
an_node.ni_vap, IEEE80211_MSG_RATECTL,
1177 &an->
an_node,
"%s: size %d (%d bytes) %s rate/short/long %d %s/%d/%d nframes/nbad [%d/%d]",
1181 status ?
"FAIL" :
"OK",
1183 short_tries, long_tries, nframes, nbad);
1185 final_rix, long_tries,
1186 short_tries, long_tries, status,
1197 IEEE80211_NOTE(an->
an_node.ni_vap, IEEE80211_MSG_RATECTL,
1199"%s: size %d (%d bytes) finaltsidx %d short %d long %d %s rate/try [%d %s/%d %d %s/%d %d %s/%d %d %s/%d] nframes/nbad [%d/%d]",
1206 status ?
"FAIL" :
"OK",
1217 for (i = 0; i < 4; i++) {
1219 badrate(sc, 0, rc[i].ratecode, rc[i].tries,
1230 rc[0].rix, rc[0].tries,
1231 short_tries, long_tries,
1234 long_tries -= rc[0].
tries;
1237 if (rc[1].tries && finalTSIdx > 0) {
1239 rc[1].rix, rc[1].tries,
1240 short_tries, long_tries,
1243 long_tries -= rc[1].
tries;
1246 if (rc[2].tries && finalTSIdx > 1) {
1248 rc[2].rix, rc[2].tries,
1249 short_tries, long_tries,
1252 long_tries -= rc[2].
tries;
1255 if (rc[3].tries && finalTSIdx > 2) {
1257 rc[3].rix, rc[3].tries,
1258 short_tries, long_tries,
1298#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
1299#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
1300#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
1306 KASSERT(rt != NULL, (
"no rate table, mode %u", sc->
sc_curmode));
1308 KASSERT(sc->
sc_curmode < IEEE80211_MODE_MAX+2,
1312 KASSERT(sn->
sched != NULL,
1313 (
"no mrr schedule for mode %u", sc->
sc_curmode));
1327 if (ni->ni_flags & IEEE80211_NODE_HT) {
1328 for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
1336 (
"mcs %u has rix %d",
MCS(x), rix));
1342 for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
1350 (
"rate %u has rix %d",
RATE(x), rix));
1353#ifdef IEEE80211_DEBUG
1354 if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) {
1357 ieee80211_note(ni->ni_vap,
"[%6D] %s: size 1600 rate/tt",
1358 ni->ni_macaddr,
":", __func__);
1359 for (mask = sn->
ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
1360 if ((mask & 1) == 0)
1364 (ni->ni_chw == 40)));
1383 for (rix = 0, mask = sn->
ratemask; mask != 0; rix++, mask >>= 1) {
1384 if ((mask & 1) == 0)
1395 (ni->ni_chw == 40));
1402 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1403 "%s: %d rates %d%sMbps (%dus)- %d%sMbps (%dus)", __func__,
1415 ni->ni_txrate =
RATE(0);
1451 device_printf(sc->
sc_dev,
"%s: len=%d, too short\n",
1473 if (rt->
info[y].
phy == IEEE80211_T_HT)
1474 tv->
ratecode[y] |= IEEE80211_RATE_MCS;
1516 printf(
"\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%jx\n",
1517 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni),
1522 printf(
"[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n",
1527 printf(
"[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n",
1534 printf(
"[%4u] packets since sample %d sample tt %u\n",
1538 for (mask = sn->
ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
1539 if ((mask & 1) == 0)
1544 printf(
"[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n",
1565 struct ieee80211com *ic = &sc->
sc_ic;
1569 error = sysctl_handle_int(oidp, &v, 0, req);
1570 if (error || !req->newptr)
1572 ieee80211_iterate_nodes(&ic->ic_sta,
sample_stats, sc);
1583 error = sysctl_handle_int(oidp, &rate, 0, req);
1584 if (error || !req->newptr)
1586 if (!(0 <= rate && rate < 100))
1600 error = sysctl_handle_int(oidp, &rate, 0, req);
1601 if (error || !req->newptr)
1603 if (!(2 <= rate && rate <= 100))
1612 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->
sc_dev);
1613 struct sysctl_oid *tree = device_get_sysctl_tree(sc->
sc_dev);
1615 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1616 "smoothing_rate", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1618 "sample: smoothing rate for avg tx time (%%)");
1619 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1620 "sample_rate", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1622 "sample: percent air time devoted to sampling new rates (%%)");
1624 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1625 "sample_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1634 ssc = malloc(
sizeof(
struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
1653 free(ssc, M_DEVBUF);
#define ATH_RATE_TLV_RATETABLE
#define ATH_RATE_TLV_SAMPLENODE
#define ath_hal_setupxtxdesc(_ah, _ds, _txr1, _txtr1, _txr2, _txtr2, _txr3, _txtr3)
#define ATH_NODE_LOCK_ASSERT(_an)
static void sample_stats(void *arg, struct ieee80211_node *ni)
void ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
static int ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
static __inline int pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin, int require_acked_before)
void ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
int ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an, struct ath_rateioctl *rs)
static void ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *ssc)
static void ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni)
void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, uint8_t rix0, int is_aggr, struct ath_rc_series *rc)
static int ath_rate_pick_seed_rate_legacy(struct ath_softc *sc, struct ath_node *an, int frameLen)
void ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
void ath_rate_detach(struct ath_ratectrl *arc)
struct ath_ratectrl * ath_rate_attach(struct ath_softc *sc)
static __inline int size_to_bin(int size)
void ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, const struct ath_rc_series *rc, const struct ath_tx_status *ts, int frame_size, int rc_framesize, int nframes, int nbad)
static const char * dot11rate_label(const HAL_RATE_TABLE *rt, int rix)
static void update_stats(struct ath_softc *sc, struct ath_node *an, int frame_size, int rix0, int tries0, int short_tries, int tries, int status, int nframes, int nbad)
static __inline int pick_sample_rate(struct sample_softc *ssc, struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin)
static int ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an, int frameLen)
static int ath_rate_sysctl_sample_rate(SYSCTL_HANDLER_ARGS)
static int ath_rate_sample_max_4ms_framelen[4][32]
static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *)
static int ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni)
void ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, struct ath_desc *ds, int shortPreamble, u_int8_t rix)
void ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
static int dot11rate(const HAL_RATE_TABLE *rt, int rix)
static const struct txschedule * mrr_schedules[IEEE80211_MODE_MAX+2]
static void badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status)
static int ath_rate_sysctl_smoothing_rate(SYSCTL_HANDLER_ARGS)
static int ath_rate_sample_find_min_pktlength(struct ath_softc *sc, struct ath_node *an, uint8_t rix0, int is_aggr)
void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, int tid, int is_aggr, u_int8_t *rix0, int *try0, u_int8_t *txrate, int *maxdur, int *maxpktlen)
#define ATH_SOFTC_SAMPLE(sc)
#define NUM_PACKET_SIZE_BINS
#define IS_RATE_DEFINED(sn, rix)
static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, int length, int rix, int short_retries, int long_retries, int is_ht40)
#define ATH_NODE_SAMPLE(an)
static const int packet_size_bins[NUM_PACKET_SIZE_BINS]
static int bin_to_size(int index)
uint8_t rateCodeToIndex[256]
struct HAL_RATE_TABLE::@3 info[64]
struct ieee80211_node an_node
uint8_t ratecode[ATH_RATE_TLV_RATETABLE_NENTRIES]
const HAL_RATE_TABLE * sc_currates
enum ieee80211_phymode sc_curmode
struct ieee80211com sc_ic
unsigned sample_tt[NUM_PACKET_SIZE_BINS]
struct rate_stats stats[NUM_PACKET_SIZE_BINS][SAMPLE_MAXRATES]
int current_rix[NUM_PACKET_SIZE_BINS]
const HAL_RATE_TABLE * currates
int ticks_since_switch[NUM_PACKET_SIZE_BINS]
int current_sample_rix[NUM_PACKET_SIZE_BINS]
int packets_since_sample[NUM_PACKET_SIZE_BINS]
const struct txschedule * sched
int last_sample_rix[NUM_PACKET_SIZE_BINS]
int packets_sent[NUM_PACKET_SIZE_BINS]
int packets_since_switch[NUM_PACKET_SIZE_BINS]
int stale_failure_timeout
int max_successive_failures
static const struct txschedule series_11ng[]
static const struct txschedule series_11na[]
static const struct txschedule series_quarter[]
static const struct txschedule series_half[]
static const struct txschedule series_11a[]
static const struct txschedule series_11g[]