Lines Matching +full:max +full:- +full:sample +full:- +full:rate +full:- +full:hz
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2010-2013 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2019-2020 Intel Corporation
14 #include "rate.h"
45 * Define group sort order: HT40 -> SGI -> #streams
51 _streams - 1
56 _MAX(0, 16 - __builtin_clz(duration))
58 /* MCS rate information for an MCS group */
91 (_streams) - 1)
204 * To enable sufficiently targeted rate sampling, MCS rates are divided into
209 * BW -> SGI -> #streams
304 switch ((le16_to_cpu(mcs_map) >> (2 * (nss - 1))) & 3) { in minstrel_get_valid_vht_rates()
328 * Look up an MCS group index based on mac80211 rate information
331 minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) in minstrel_ht_get_group_idx() argument
333 return GROUP_IDX((rate->idx / 8) + 1, in minstrel_ht_get_group_idx()
334 !!(rate->flags & IEEE80211_TX_RC_SHORT_GI), in minstrel_ht_get_group_idx()
335 !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)); in minstrel_ht_get_group_idx()
339 minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate) in minstrel_vht_get_group_idx() argument
341 return VHT_GROUP_IDX(ieee80211_rate_get_vht_nss(rate), in minstrel_vht_get_group_idx()
342 !!(rate->flags & IEEE80211_TX_RC_SHORT_GI), in minstrel_vht_get_group_idx()
343 !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + in minstrel_vht_get_group_idx()
344 2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)); in minstrel_vht_get_group_idx()
349 struct ieee80211_tx_rate *rate) in minstrel_ht_get_stats() argument
353 if (rate->flags & IEEE80211_TX_RC_MCS) { in minstrel_ht_get_stats()
354 group = minstrel_ht_get_group_idx(rate); in minstrel_ht_get_stats()
355 idx = rate->idx % 8; in minstrel_ht_get_stats()
359 if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { in minstrel_ht_get_stats()
360 group = minstrel_vht_get_group_idx(rate); in minstrel_ht_get_stats()
361 idx = ieee80211_rate_get_vht_mcs(rate); in minstrel_ht_get_stats()
366 for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) { in minstrel_ht_get_stats()
367 if (rate->idx != mp->cck_rates[idx]) in minstrel_ht_get_stats()
371 if ((mi->supported[group] & BIT(idx + 4)) && in minstrel_ht_get_stats()
372 (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) in minstrel_ht_get_stats()
378 for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++) in minstrel_ht_get_stats()
379 if (rate->idx == mp->ofdm_rates[mi->band][idx]) in minstrel_ht_get_stats()
384 return &mi->groups[group].rates[idx]; in minstrel_ht_get_stats()
390 return &mi->groups[MI_RATE_GROUP(index)].rates[MI_RATE_IDX(index)]; in minstrel_get_ratestats()
396 unsigned int duration = group->duration[MI_RATE_IDX(index)]; in minstrel_get_duration()
398 return duration << group->shift; in minstrel_get_duration()
406 if (mi->avg_ampdu_len) in minstrel_ht_avg_ampdu_len()
407 return MINSTREL_TRUNC(mi->avg_ampdu_len); in minstrel_ht_avg_ampdu_len()
409 if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_tp_rate[0]))) in minstrel_ht_avg_ampdu_len()
412 duration = minstrel_get_duration(mi->max_tp_rate[0]); in minstrel_ht_avg_ampdu_len()
427 * Return current throughput based on the average A-MPDU length, taking into
431 minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, in minstrel_ht_get_tp_avg() argument
434 unsigned int nsecs = 0, overhead = mi->overhead; in minstrel_ht_get_tp_avg()
442 overhead = mi->overhead_legacy; in minstrel_ht_get_tp_avg()
447 nsecs += minstrel_mcs_groups[group].duration[rate] << in minstrel_ht_get_tp_avg()
452 * account for collision related packet error rate fluctuation in minstrel_ht_get_tp_avg()
453 * (prob is scaled - see MINSTREL_FRAC above) in minstrel_ht_get_tp_avg()
478 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg; in minstrel_ht_sort_best_tp_rates()
482 tmp_group = MI_RATE_GROUP(tp_list[j - 1]); in minstrel_ht_sort_best_tp_rates()
483 tmp_idx = MI_RATE_IDX(tp_list[j - 1]); in minstrel_ht_sort_best_tp_rates()
484 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; in minstrel_ht_sort_best_tp_rates()
490 j--; in minstrel_ht_sort_best_tp_rates()
493 if (j < MAX_THR_RATES - 1) { in minstrel_ht_sort_best_tp_rates()
495 (MAX_THR_RATES - (j + 1)))); in minstrel_ht_sort_best_tp_rates()
502 * Find and set the topmost probability rate per sta and per group
517 mg = &mi->groups[cur_group]; in minstrel_ht_set_best_prob_rate()
518 mrs = &mg->rates[cur_idx]; in minstrel_ht_set_best_prob_rate()
522 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; in minstrel_ht_set_best_prob_rate()
527 max_tp_group = MI_RATE_GROUP(mi->max_tp_rate[0]); in minstrel_ht_set_best_prob_rate()
528 max_tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); in minstrel_ht_set_best_prob_rate()
529 max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg; in minstrel_ht_set_best_prob_rate()
535 /* skip rates faster than max tp rate with lower prob */ in minstrel_ht_set_best_prob_rate()
536 if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) && in minstrel_ht_set_best_prob_rate()
537 mrs->prob_avg < max_tp_prob) in minstrel_ht_set_best_prob_rate()
540 max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate); in minstrel_ht_set_best_prob_rate()
541 max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate); in minstrel_ht_set_best_prob_rate()
542 max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; in minstrel_ht_set_best_prob_rate()
544 if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) { in minstrel_ht_set_best_prob_rate()
546 mrs->prob_avg); in minstrel_ht_set_best_prob_rate()
554 mg->max_group_prob_rate = index; in minstrel_ht_set_best_prob_rate()
556 if (mrs->prob_avg > tmp_prob) in minstrel_ht_set_best_prob_rate()
558 if (mrs->prob_avg > max_gpr_prob) in minstrel_ht_set_best_prob_rate()
559 mg->max_group_prob_rate = index; in minstrel_ht_set_best_prob_rate()
565 * Assign new rate set per sta and use CCK rates only if the fastest
566 * rate (max_tp_rate[0]) is from CCK group. This prohibits such sorted
567 * rate sets where MCS and CCK rates are mixed, because CCK rates can
580 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; in minstrel_ht_assign_best_tp_rates()
585 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; in minstrel_ht_assign_best_tp_rates()
598 * Try to increase robustness of max_prob rate by decrease number of
608 if (!mi->sta->ht_cap.ht_supported) in minstrel_ht_prob_rate_reduce_streams()
611 group = MI_RATE_GROUP(mi->max_tp_rate[0]); in minstrel_ht_prob_rate_reduce_streams()
614 mg = &mi->groups[group]; in minstrel_ht_prob_rate_reduce_streams()
615 if (!mi->supported[group] || group == MINSTREL_CCK_GROUP) in minstrel_ht_prob_rate_reduce_streams()
618 tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate); in minstrel_ht_prob_rate_reduce_streams()
619 tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg; in minstrel_ht_prob_rate_reduce_streams()
623 mi->max_prob_rate = mg->max_group_prob_rate; in minstrel_ht_prob_rate_reduce_streams()
635 u16 *rates = mi->sample[type].sample_rates; in __minstrel_ht_get_sample_rate()
656 diff = new - old; in minstrel_ewma()
657 incr = (EWMA_DIV - weight) * diff / EWMA_DIV; in minstrel_ewma()
694 * Recalculate statistics and counters of a given rate
702 if (unlikely(mrs->attempts > 0)) { in minstrel_ht_calc_rate_stats()
703 cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); in minstrel_ht_calc_rate_stats()
704 minstrel_filter_avg_add(&mrs->prob_avg, in minstrel_ht_calc_rate_stats()
705 &mrs->prob_avg_1, cur_prob); in minstrel_ht_calc_rate_stats()
706 mrs->att_hist += mrs->attempts; in minstrel_ht_calc_rate_stats()
707 mrs->succ_hist += mrs->success; in minstrel_ht_calc_rate_stats()
710 mrs->last_success = mrs->success; in minstrel_ht_calc_rate_stats()
711 mrs->last_attempts = mrs->attempts; in minstrel_ht_calc_rate_stats()
712 mrs->success = 0; in minstrel_ht_calc_rate_stats()
713 mrs->attempts = 0; in minstrel_ht_calc_rate_stats()
722 u16 cur = mi->sample[type].sample_rates[i]; in minstrel_ht_find_sample_rate()
738 u16 *rates = mi->sample[type].sample_rates; in minstrel_ht_move_sample_rates()
784 u16 supported = mi->supported[group]; in minstrel_ht_group_min_rate_offset()
797 return -1; in minstrel_ht_group_min_rate_offset()
802 * Flip through groups and pick the first group rate that is faster than the
803 * highest currently selected rate
812 group = mi->sample[type].sample_group; in minstrel_ht_next_inc_rate()
828 mi->sample[type].sample_group = group; in minstrel_ht_next_inc_rate()
837 struct minstrel_mcs_group_data *mg = &mi->groups[group]; in minstrel_ht_next_group_sample_rate()
842 idx = sample_table[mg->column][mg->index]; in minstrel_ht_next_group_sample_rate()
843 if (++mg->index >= MCS_GROUP_RATES) { in minstrel_ht_next_group_sample_rate()
844 mg->index = 0; in minstrel_ht_next_group_sample_rate()
845 if (++mg->column >= ARRAY_SIZE(sample_table)) in minstrel_ht_next_group_sample_rate()
846 mg->column = 0; in minstrel_ht_next_group_sample_rate()
858 return -1; in minstrel_ht_next_group_sample_rate()
863 * Sample random rates, use those that are faster than the highest
864 * currently selected rate. Rates between the fastest and the slowest
865 * get sorted into the slow sample bucket, but only if it has room
882 slow_rates = mi->sample[MINSTREL_SAMPLE_TYPE_SLOW].sample_rates; in minstrel_ht_next_jump_rate()
883 group = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group; in minstrel_ht_next_jump_rate()
889 supported = mi->supported[group]; in minstrel_ht_next_jump_rate()
923 if (mrs->prob_avg > MINSTREL_FRAC(95, 100)) in minstrel_ht_next_jump_rate()
933 mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group = group; in minstrel_ht_next_jump_rate()
941 u32 prob_dur = minstrel_get_duration(mi->max_prob_rate); in minstrel_ht_refill_sample_rates()
942 u32 tp_dur = minstrel_get_duration(mi->max_tp_rate[0]); in minstrel_ht_refill_sample_rates()
943 u32 tp2_dur = minstrel_get_duration(mi->max_tp_rate[1]); in minstrel_ht_refill_sample_rates()
945 u32 slow_rate_dur = max(max(tp_dur, tp2_dur), prob_dur); in minstrel_ht_refill_sample_rates()
949 rates = mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates; in minstrel_ht_refill_sample_rates()
960 rates = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_rates; in minstrel_ht_refill_sample_rates()
974 for (i = 0; i < ARRAY_SIZE(mi->sample); i++) in minstrel_ht_refill_sample_rates()
975 memcpy(mi->sample[i].cur_sample_rates, mi->sample[i].sample_rates, in minstrel_ht_refill_sample_rates()
976 sizeof(mi->sample[i].cur_sample_rates)); in minstrel_ht_refill_sample_rates()
981 * Update rate statistics and select new primary rates
983 * Rules for rate selection:
984 * - max_prob_rate must use only one stream, as a tradeoff between delivery
986 * - as long as the max prob rate has a probability of more than 75%, pick
998 bool ht_supported = mi->sta->ht_cap.ht_supported; in minstrel_ht_update_stats()
1000 if (mi->ampdu_packets > 0) { in minstrel_ht_update_stats()
1001 if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN)) in minstrel_ht_update_stats()
1002 mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len, in minstrel_ht_update_stats()
1003 MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets), in minstrel_ht_update_stats()
1006 mi->avg_ampdu_len = 0; in minstrel_ht_update_stats()
1007 mi->ampdu_len = 0; in minstrel_ht_update_stats()
1008 mi->ampdu_packets = 0; in minstrel_ht_update_stats()
1011 if (mi->supported[MINSTREL_CCK_GROUP]) in minstrel_ht_update_stats()
1013 else if (mi->supported[MINSTREL_OFDM_GROUP]) in minstrel_ht_update_stats()
1022 if (mi->supported[MINSTREL_VHT_GROUP_0]) in minstrel_ht_update_stats()
1026 else if (mi->supported[MINSTREL_CCK_GROUP]) in minstrel_ht_update_stats()
1036 /* Find best rate sets within all MCS groups*/ in minstrel_ht_update_stats()
1041 mg = &mi->groups[group]; in minstrel_ht_update_stats()
1042 if (!mi->supported[group]) in minstrel_ht_update_stats()
1045 /* (re)Initialize group rate indexes */ in minstrel_ht_update_stats()
1052 for (i = MCS_GROUP_RATES - 1; i >= 0; i--) { in minstrel_ht_update_stats()
1053 if (!(mi->supported[group] & BIT(i))) in minstrel_ht_update_stats()
1058 mrs = &mg->rates[i]; in minstrel_ht_update_stats()
1059 mrs->retry_updated = false; in minstrel_ht_update_stats()
1062 if (mrs->att_hist) in minstrel_ht_update_stats()
1063 last_prob = max(last_prob, mrs->prob_avg); in minstrel_ht_update_stats()
1065 mrs->prob_avg = max(last_prob, mrs->prob_avg); in minstrel_ht_update_stats()
1066 cur_prob = mrs->prob_avg; in minstrel_ht_update_stats()
1071 /* Find max throughput rate set */ in minstrel_ht_update_stats()
1074 /* Find max throughput rate set within a group */ in minstrel_ht_update_stats()
1079 memcpy(mg->max_group_tp_rate, tmp_group_tp_rate, in minstrel_ht_update_stats()
1080 sizeof(mg->max_group_tp_rate)); in minstrel_ht_update_stats()
1083 /* Assign new rate set per sta */ in minstrel_ht_update_stats()
1086 memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate)); in minstrel_ht_update_stats()
1089 if (!mi->supported[group]) in minstrel_ht_update_stats()
1092 mg = &mi->groups[group]; in minstrel_ht_update_stats()
1093 mg->max_group_prob_rate = MI_RATE(group, 0); in minstrel_ht_update_stats()
1096 if (!(mi->supported[group] & BIT(i))) in minstrel_ht_update_stats()
1101 /* Find max probability rate per group and global */ in minstrel_ht_update_stats()
1107 mi->max_prob_rate = tmp_max_prob_rate; in minstrel_ht_update_stats()
1115 if (mp->fixed_rate_idx != -1) { in minstrel_ht_update_stats()
1117 mi->max_tp_rate[i] = mp->fixed_rate_idx; in minstrel_ht_update_stats()
1118 mi->max_prob_rate = mp->fixed_rate_idx; in minstrel_ht_update_stats()
1123 mi->last_stats_update = jiffies; in minstrel_ht_update_stats()
1124 mi->sample_time = jiffies; in minstrel_ht_update_stats()
1129 struct ieee80211_tx_rate *rate) in minstrel_ht_txstat_valid() argument
1133 if (rate->idx < 0) in minstrel_ht_txstat_valid()
1136 if (!rate->count) in minstrel_ht_txstat_valid()
1139 if (rate->flags & IEEE80211_TX_RC_MCS || in minstrel_ht_txstat_valid()
1140 rate->flags & IEEE80211_TX_RC_VHT_MCS) in minstrel_ht_txstat_valid()
1143 for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) in minstrel_ht_txstat_valid()
1144 if (rate->idx == mp->cck_rates[i]) in minstrel_ht_txstat_valid()
1147 for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates[0]); i++) in minstrel_ht_txstat_valid()
1148 if (rate->idx == mp->ofdm_rates[mi->band][i]) in minstrel_ht_txstat_valid()
1161 group--; in minstrel_downgrade_rate()
1163 if (!mi->supported[group]) in minstrel_downgrade_rate()
1171 *idx = mi->groups[group].max_group_tp_rate[0]; in minstrel_downgrade_rate()
1173 *idx = mi->groups[group].max_group_tp_rate[1]; in minstrel_downgrade_rate()
1182 struct ieee80211_tx_info *info = st->info; in minstrel_ht_tx_status()
1184 struct ieee80211_tx_rate *ar = info->status.rates; in minstrel_ht_tx_status()
1185 struct minstrel_rate_stats *rate, *rate2; in minstrel_ht_tx_status() local
1187 u32 update_interval = mp->update_interval; in minstrel_ht_tx_status()
1192 if (info->flags & IEEE80211_TX_CTL_NO_ACK) in minstrel_ht_tx_status()
1196 if ((info->flags & IEEE80211_TX_CTL_AMPDU) && in minstrel_ht_tx_status()
1197 !(info->flags & IEEE80211_TX_STAT_AMPDU)) in minstrel_ht_tx_status()
1200 if (!(info->flags & IEEE80211_TX_STAT_AMPDU)) { in minstrel_ht_tx_status()
1201 info->status.ampdu_ack_len = in minstrel_ht_tx_status()
1202 (info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); in minstrel_ht_tx_status()
1203 info->status.ampdu_len = 1; in minstrel_ht_tx_status()
1207 if (mi->total_packets >= ~0 - info->status.ampdu_len) { in minstrel_ht_tx_status()
1208 mi->total_packets = 0; in minstrel_ht_tx_status()
1209 mi->sample_packets = 0; in minstrel_ht_tx_status()
1212 mi->total_packets += info->status.ampdu_len; in minstrel_ht_tx_status()
1213 if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) in minstrel_ht_tx_status()
1214 mi->sample_packets += info->status.ampdu_len; in minstrel_ht_tx_status()
1216 mi->ampdu_packets++; in minstrel_ht_tx_status()
1217 mi->ampdu_len += info->status.ampdu_len; in minstrel_ht_tx_status()
1221 last = (i == IEEE80211_TX_MAX_RATES - 1) || in minstrel_ht_tx_status()
1224 rate = minstrel_ht_get_stats(mp, mi, &ar[i]); in minstrel_ht_tx_status()
1226 rate->success += info->status.ampdu_ack_len; in minstrel_ht_tx_status()
1228 rate->attempts += ar[i].count * info->status.ampdu_len; in minstrel_ht_tx_status()
1231 if (mp->hw->max_rates > 1) { in minstrel_ht_tx_status()
1236 rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); in minstrel_ht_tx_status()
1237 if (rate->attempts > 30 && in minstrel_ht_tx_status()
1238 rate->success < rate->attempts / 4) { in minstrel_ht_tx_status()
1239 minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); in minstrel_ht_tx_status()
1243 rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); in minstrel_ht_tx_status()
1244 if (rate2->attempts > 30 && in minstrel_ht_tx_status()
1245 rate2->success < rate2->attempts / 4) { in minstrel_ht_tx_status()
1246 minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); in minstrel_ht_tx_status()
1251 if (time_after(jiffies, mi->last_stats_update + update_interval)) { in minstrel_ht_tx_status()
1266 unsigned int cw = mp->cw_min; in minstrel_calc_retransmit()
1273 if (mrs->prob_avg < MINSTREL_FRAC(1, 10)) { in minstrel_calc_retransmit()
1274 mrs->retry_count = 1; in minstrel_calc_retransmit()
1275 mrs->retry_count_rtscts = 1; in minstrel_calc_retransmit()
1279 mrs->retry_count = 2; in minstrel_calc_retransmit()
1280 mrs->retry_count_rtscts = 2; in minstrel_calc_retransmit()
1281 mrs->retry_updated = true; in minstrel_calc_retransmit()
1287 cw = min((cw << 1) | 1, mp->cw_max); in minstrel_calc_retransmit()
1289 cw = min((cw << 1) | 1, mp->cw_max); in minstrel_calc_retransmit()
1292 overhead = mi->overhead_legacy; in minstrel_calc_retransmit()
1293 overhead_rtscts = mi->overhead_legacy_rtscts; in minstrel_calc_retransmit()
1295 overhead = mi->overhead; in minstrel_calc_retransmit()
1296 overhead_rtscts = mi->overhead_rtscts; in minstrel_calc_retransmit()
1307 cw = min((cw << 1) | 1, mp->cw_max); in minstrel_calc_retransmit()
1313 if (tx_time_rtscts < mp->segment_size) in minstrel_calc_retransmit()
1314 mrs->retry_count_rtscts++; in minstrel_calc_retransmit()
1315 } while ((tx_time < mp->segment_size) && in minstrel_calc_retransmit()
1316 (++mrs->retry_count < mp->max_retry)); in minstrel_calc_retransmit()
1328 u16 flags = group->flags; in minstrel_ht_set_rate()
1331 if (!mrs->retry_updated) in minstrel_ht_set_rate()
1334 if (mrs->prob_avg < MINSTREL_FRAC(20, 100) || !mrs->retry_count) { in minstrel_ht_set_rate()
1335 ratetbl->rate[offset].count = 2; in minstrel_ht_set_rate()
1336 ratetbl->rate[offset].count_rts = 2; in minstrel_ht_set_rate()
1337 ratetbl->rate[offset].count_cts = 2; in minstrel_ht_set_rate()
1339 ratetbl->rate[offset].count = mrs->retry_count; in minstrel_ht_set_rate()
1340 ratetbl->rate[offset].count_cts = mrs->retry_count; in minstrel_ht_set_rate()
1341 ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts; in minstrel_ht_set_rate()
1346 idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; in minstrel_ht_set_rate()
1348 idx = mp->ofdm_rates[mi->band][index % in minstrel_ht_set_rate()
1349 ARRAY_SIZE(mp->ofdm_rates[0])]; in minstrel_ht_set_rate()
1351 idx = ((group->streams - 1) << 4) | in minstrel_ht_set_rate()
1354 idx = index + (group->streams - 1) * 8; in minstrel_ht_set_rate()
1357 * - if station is in dynamic SMPS (and streams > 1) in minstrel_ht_set_rate()
1358 * - for fallback rates, to increase chances of getting through in minstrel_ht_set_rate()
1361 (mi->sta->smps_mode == IEEE80211_SMPS_DYNAMIC && in minstrel_ht_set_rate()
1362 group->streams > 1)) { in minstrel_ht_set_rate()
1363 ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts; in minstrel_ht_set_rate()
1367 ratetbl->rate[offset].idx = idx; in minstrel_ht_set_rate()
1368 ratetbl->rate[offset].flags = flags; in minstrel_ht_set_rate()
1372 minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate) in minstrel_ht_get_prob_avg() argument
1374 int group = MI_RATE_GROUP(rate); in minstrel_ht_get_prob_avg()
1375 rate = MI_RATE_IDX(rate); in minstrel_ht_get_prob_avg()
1376 return mi->groups[group].rates[rate].prob_avg; in minstrel_ht_get_prob_avg()
1382 int group = MI_RATE_GROUP(mi->max_prob_rate); in minstrel_ht_get_max_amsdu_len()
1384 int rate = MI_RATE_IDX(mi->max_prob_rate); in minstrel_ht_get_max_amsdu_len() local
1387 /* Disable A-MSDU if max_prob_rate is bad */ in minstrel_ht_get_max_amsdu_len()
1388 if (mi->groups[group].rates[rate].prob_avg < MINSTREL_FRAC(50, 100)) in minstrel_ht_get_max_amsdu_len()
1391 duration = g->duration[rate]; in minstrel_ht_get_max_amsdu_len()
1392 duration <<= g->shift; in minstrel_ht_get_max_amsdu_len()
1394 /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */ in minstrel_ht_get_max_amsdu_len()
1399 * If the rate is slower than single-stream MCS4, limit A-MSDU to usual in minstrel_ht_get_max_amsdu_len()
1406 * If the rate is slower than single-stream MCS7, or if the max throughput in minstrel_ht_get_max_amsdu_len()
1407 * rate success probability is less than 75%, limit A-MSDU to twice the usual in minstrel_ht_get_max_amsdu_len()
1411 (minstrel_ht_get_prob_avg(mi, mi->max_tp_rate[0]) < in minstrel_ht_get_max_amsdu_len()
1416 * HT A-MPDU limits maximum MPDU size under BA agreement to 4095 bytes. in minstrel_ht_get_max_amsdu_len()
1418 * the limit here to avoid the complexity of having to de-aggregate in minstrel_ht_get_max_amsdu_len()
1421 if (!mi->sta->vht_cap.vht_supported) in minstrel_ht_get_max_amsdu_len()
1439 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]); in minstrel_ht_update_rates()
1441 if (mp->hw->max_rates >= 3) { in minstrel_ht_update_rates()
1443 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[1]); in minstrel_ht_update_rates()
1446 if (mp->hw->max_rates >= 2) { in minstrel_ht_update_rates()
1447 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate); in minstrel_ht_update_rates()
1450 mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi); in minstrel_ht_update_rates()
1451 rates->rate[i].idx = -1; in minstrel_ht_update_rates()
1452 rate_control_set_rates(mp->hw, mi->sta, rates); in minstrel_ht_update_rates()
1460 if (mp->hw->max_rates > 1) { in minstrel_ht_get_sample_rate()
1461 seq = mi->sample_seq; in minstrel_ht_get_sample_rate()
1462 mi->sample_seq = (seq + 1) % ARRAY_SIZE(minstrel_sample_seq); in minstrel_ht_get_sample_rate()
1476 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); in minstrel_ht_get_rate()
1477 struct ieee80211_tx_rate *rate = &info->status.rates[0]; in minstrel_ht_get_rate() local
1482 info->flags |= mi->tx_flags; in minstrel_ht_get_rate()
1485 if (mp->fixed_rate_idx != -1) in minstrel_ht_get_rate()
1489 /* Don't use EAPOL frames for sampling on non-mrr hw */ in minstrel_ht_get_rate()
1490 if (mp->hw->max_rates == 1 && in minstrel_ht_get_rate()
1491 (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) in minstrel_ht_get_rate()
1494 if (time_is_after_jiffies(mi->sample_time)) in minstrel_ht_get_rate()
1497 mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL; in minstrel_ht_get_rate()
1506 (sample_idx >= 4) != txrc->short_preamble) in minstrel_ht_get_rate()
1509 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; in minstrel_ht_get_rate()
1510 rate->count = 1; in minstrel_ht_get_rate()
1513 int idx = sample_idx % ARRAY_SIZE(mp->cck_rates); in minstrel_ht_get_rate()
1514 rate->idx = mp->cck_rates[idx]; in minstrel_ht_get_rate()
1516 int idx = sample_idx % ARRAY_SIZE(mp->ofdm_rates[0]); in minstrel_ht_get_rate()
1517 rate->idx = mp->ofdm_rates[mi->band][idx]; in minstrel_ht_get_rate()
1518 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { in minstrel_ht_get_rate()
1519 ieee80211_rate_set_vht(rate, MI_RATE_IDX(sample_idx), in minstrel_ht_get_rate()
1520 sample_group->streams); in minstrel_ht_get_rate()
1522 rate->idx = sample_idx + (sample_group->streams - 1) * 8; in minstrel_ht_get_rate()
1525 rate->flags = sample_group->flags; in minstrel_ht_get_rate()
1535 if (sband->band != NL80211_BAND_2GHZ) in minstrel_ht_update_cck()
1538 if (sta->ht_cap.ht_supported && in minstrel_ht_update_cck()
1539 !ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) in minstrel_ht_update_cck()
1543 if (mp->cck_rates[i] == 0xff || in minstrel_ht_update_cck()
1544 !rate_supported(sta, sband->band, mp->cck_rates[i])) in minstrel_ht_update_cck()
1547 mi->supported[MINSTREL_CCK_GROUP] |= BIT(i); in minstrel_ht_update_cck()
1548 if (sband->bitrates[i].flags & IEEE80211_RATE_SHORT_PREAMBLE) in minstrel_ht_update_cck()
1549 mi->supported[MINSTREL_CCK_GROUP] |= BIT(i + 4); in minstrel_ht_update_cck()
1561 if (sta->ht_cap.ht_supported) in minstrel_ht_update_ofdm()
1564 rates = mp->ofdm_rates[sband->band]; in minstrel_ht_update_ofdm()
1565 for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates[0]); i++) { in minstrel_ht_update_ofdm()
1567 !rate_supported(sta, sband->band, rates[i])) in minstrel_ht_update_ofdm()
1570 mi->supported[MINSTREL_OFDM_GROUP] |= BIT(i); in minstrel_ht_update_ofdm()
1581 struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; in minstrel_ht_update_caps()
1582 u16 ht_cap = sta->ht_cap.cap; in minstrel_ht_update_caps()
1583 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; in minstrel_ht_update_caps()
1594 if (vht_cap->vht_supported) in minstrel_ht_update_caps()
1595 use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0); in minstrel_ht_update_caps()
1601 mi->sta = sta; in minstrel_ht_update_caps()
1602 mi->band = sband->band; in minstrel_ht_update_caps()
1603 mi->last_stats_update = jiffies; in minstrel_ht_update_caps()
1605 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0); in minstrel_ht_update_caps()
1606 mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0); in minstrel_ht_update_caps()
1607 mi->overhead += ack_dur; in minstrel_ht_update_caps()
1608 mi->overhead_rtscts = mi->overhead + 2 * ack_dur; in minstrel_ht_update_caps()
1610 ctl_rate = &sband->bitrates[rate_lowest_index(sband, sta)]; in minstrel_ht_update_caps()
1611 erp = ctl_rate->flags & IEEE80211_RATE_ERP_G; in minstrel_ht_update_caps()
1612 ack_dur = ieee80211_frame_duration(sband->band, 10, in minstrel_ht_update_caps()
1613 ctl_rate->bitrate, erp, 1, in minstrel_ht_update_caps()
1615 mi->overhead_legacy = ack_dur; in minstrel_ht_update_caps()
1616 mi->overhead_legacy_rtscts = mi->overhead_legacy + 2 * ack_dur; in minstrel_ht_update_caps()
1618 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); in minstrel_ht_update_caps()
1626 stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >> in minstrel_ht_update_caps()
1629 ldpc = vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC; in minstrel_ht_update_caps()
1632 mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT; in minstrel_ht_update_caps()
1634 mi->tx_flags |= IEEE80211_TX_CTL_LDPC; in minstrel_ht_update_caps()
1636 for (i = 0; i < ARRAY_SIZE(mi->groups); i++) { in minstrel_ht_update_caps()
1640 mi->supported[i] = 0; in minstrel_ht_update_caps()
1655 sta->bandwidth < IEEE80211_STA_RX_BW_40) in minstrel_ht_update_caps()
1661 if (sta->smps_mode == IEEE80211_SMPS_STATIC && nss > 1) in minstrel_ht_update_caps()
1664 /* HT rate */ in minstrel_ht_update_caps()
1669 mi->supported[i] = mcs->rx_mask[nss - 1]; in minstrel_ht_update_caps()
1670 if (mi->supported[i]) in minstrel_ht_update_caps()
1675 /* VHT rate */ in minstrel_ht_update_caps()
1676 if (!vht_cap->vht_supported || in minstrel_ht_update_caps()
1682 if (sta->bandwidth < IEEE80211_STA_RX_BW_80 || in minstrel_ht_update_caps()
1684 !(vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80))) { in minstrel_ht_update_caps()
1696 mi->supported[i] = minstrel_get_valid_vht_rates(bw, nss, in minstrel_ht_update_caps()
1697 vht_cap->vht_mcs.tx_mcs_map); in minstrel_ht_update_caps()
1699 if (mi->supported[i]) in minstrel_ht_update_caps()
1706 /* create an initial rate table with the lowest supported rates */ in minstrel_ht_update_caps()
1734 struct ieee80211_hw *hw = mp->hw; in minstrel_ht_alloc_sta()
1739 sband = hw->wiphy->bands[i]; in minstrel_ht_alloc_sta()
1740 if (sband && sband->n_bitrates > max_rates) in minstrel_ht_alloc_sta()
1741 max_rates = sband->n_bitrates; in minstrel_ht_alloc_sta()
1759 for (i = 0; i < sband->n_bitrates; i++) { in minstrel_ht_fill_rate_array()
1760 struct ieee80211_rate *rate = &sband->bitrates[i]; in minstrel_ht_fill_rate_array() local
1762 if ((rate_flags & sband->bitrates[i].flags) != rate_flags) in minstrel_ht_fill_rate_array()
1766 if (rate->bitrate != bitrates[j]) in minstrel_ht_fill_rate_array()
1780 u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); in minstrel_ht_init_cck_rates()
1782 memset(mp->cck_rates, 0xff, sizeof(mp->cck_rates)); in minstrel_ht_init_cck_rates()
1783 sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; in minstrel_ht_init_cck_rates()
1787 BUILD_BUG_ON(ARRAY_SIZE(mp->cck_rates) != ARRAY_SIZE(bitrates)); in minstrel_ht_init_cck_rates()
1788 minstrel_ht_fill_rate_array(mp->cck_rates, sband, in minstrel_ht_init_cck_rates()
1799 u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); in minstrel_ht_init_ofdm_rates()
1801 memset(mp->ofdm_rates[band], 0xff, sizeof(mp->ofdm_rates[band])); in minstrel_ht_init_ofdm_rates()
1802 sband = mp->hw->wiphy->bands[band]; in minstrel_ht_init_ofdm_rates()
1806 BUILD_BUG_ON(ARRAY_SIZE(mp->ofdm_rates[band]) != ARRAY_SIZE(bitrates)); in minstrel_ht_init_ofdm_rates()
1807 minstrel_ht_fill_rate_array(mp->ofdm_rates[band], sband, in minstrel_ht_init_ofdm_rates()
1824 * Just an approximation. Using the per-queue values would complicate in minstrel_ht_alloc()
1826 mp->cw_min = 15; in minstrel_ht_alloc()
1827 mp->cw_max = 1023; in minstrel_ht_alloc()
1830 mp->segment_size = 6000; in minstrel_ht_alloc()
1832 if (hw->max_rate_tries > 0) in minstrel_ht_alloc()
1833 mp->max_retry = hw->max_rate_tries; in minstrel_ht_alloc()
1836 mp->max_retry = 7; in minstrel_ht_alloc()
1838 if (hw->max_rates >= 4) in minstrel_ht_alloc()
1839 mp->has_mrr = true; in minstrel_ht_alloc()
1841 mp->hw = hw; in minstrel_ht_alloc()
1842 mp->update_interval = HZ / 20; in minstrel_ht_alloc()
1845 for (i = 0; i < ARRAY_SIZE(mp->hw->wiphy->bands); i++) in minstrel_ht_alloc()
1857 mp->fixed_rate_idx = (u32) -1; in minstrel_ht_add_debugfs()
1859 &mp->fixed_rate_idx); in minstrel_ht_add_debugfs()
1874 i = MI_RATE_GROUP(mi->max_tp_rate[0]); in minstrel_ht_get_expected_throughput()
1875 j = MI_RATE_IDX(mi->max_tp_rate[0]); in minstrel_ht_get_expected_throughput()
1876 prob = mi->groups[i].rates[j].prob_avg; in minstrel_ht_get_expected_throughput()