123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- From: Felix Fietkau <nbd@nbd.name>
- Date: Sat, 6 Feb 2021 16:33:14 +0100
- Subject: [PATCH] mac80211: minstrel_ht: rework rate downgrade code and
- max_prob rate selection
- The current fallback code for fast rate switching on potentially failing rates
- is triggering too often if there is some strong noise on the channel. This can
- lead to wild fluctuations in the rate selection.
- Additionally, switching down to max_prob_rate can create a significant gap down
- in throughput, especially when using only 2 spatial streams, because max_prob_rate
- is limited to using fewer streams than the max_tp rates.
- In order to improve throughput without reducing reliability too much, use the
- rate downgrade code for the max_prob_rate only, and allow the non-downgraded
- max_prob_rate to use as many spatial streams as the max_tp rates
- Signed-off-by: Felix Fietkau <nbd@nbd.name>
- ---
- --- a/net/mac80211/rc80211_minstrel_ht.c
- +++ b/net/mac80211/rc80211_minstrel_ht.c
- @@ -580,6 +580,14 @@ minstrel_ht_set_best_prob_rate(struct mi
- int cur_tp_avg, cur_group, cur_idx;
- int max_gpr_group, max_gpr_idx;
- int max_gpr_tp_avg, max_gpr_prob;
- + int min_dur;
- +
- + min_dur = max(minstrel_get_duration(mi->max_tp_rate[0]),
- + minstrel_get_duration(mi->max_tp_rate[1]));
- +
- + /* make the rate at least 18% slower than max tp rates */
- + if (minstrel_get_duration(index) <= min_dur * 19 / 16)
- + return;
-
- cur_group = MI_RATE_GROUP(index);
- cur_idx = MI_RATE_IDX(index);
- @@ -601,11 +609,6 @@ minstrel_ht_set_best_prob_rate(struct mi
- !minstrel_ht_is_legacy_group(max_tp_group))
- return;
-
- - /* skip rates faster than max tp rate with lower prob */
- - if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) &&
- - mrs->prob_avg < max_tp_prob)
- - return;
- -
- max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate);
- max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate);
- max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
- @@ -663,40 +666,6 @@ minstrel_ht_assign_best_tp_rates(struct
-
- }
-
- -/*
- - * Try to increase robustness of max_prob rate by decrease number of
- - * streams if possible.
- - */
- -static inline void
- -minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
- -{
- - struct minstrel_mcs_group_data *mg;
- - int tmp_max_streams, group, tmp_idx, tmp_prob;
- - int tmp_tp = 0;
- -
- - if (!mi->sta->deflink.ht_cap.ht_supported)
- - return;
- -
- - group = MI_RATE_GROUP(mi->max_tp_rate[0]);
- - tmp_max_streams = minstrel_mcs_groups[group].streams;
- - for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
- - mg = &mi->groups[group];
- - if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
- - continue;
- -
- - tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate);
- - tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg;
- -
- - if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
- - (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
- - mi->max_prob_rate = mg->max_group_prob_rate;
- - tmp_tp = minstrel_ht_get_tp_avg(mi, group,
- - tmp_idx,
- - tmp_prob);
- - }
- - }
- -}
- -
- static u16
- __minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
- enum minstrel_sample_type type)
- @@ -1176,8 +1145,6 @@ minstrel_ht_update_stats(struct minstrel
-
- mi->max_prob_rate = tmp_max_prob_rate;
-
- - /* Try to increase robustness of max_prob_rate*/
- - minstrel_ht_prob_rate_reduce_streams(mi);
- minstrel_ht_refill_sample_rates(mi);
-
- #ifdef CPTCFG_MAC80211_DEBUGFS
- @@ -1256,7 +1223,7 @@ minstrel_ht_ri_txstat_valid(struct minst
- }
-
- static void
- -minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
- +minstrel_downgrade_prob_rate(struct minstrel_ht_sta *mi, u16 *idx)
- {
- int group, orig_group;
-
- @@ -1271,11 +1238,7 @@ minstrel_downgrade_rate(struct minstrel_
- minstrel_mcs_groups[orig_group].streams)
- continue;
-
- - if (primary)
- - *idx = mi->groups[group].max_group_tp_rate[0];
- - else
- - *idx = mi->groups[group].max_group_tp_rate[1];
- - break;
- + *idx = mi->groups[group].max_group_prob_rate;
- }
- }
-
- @@ -1286,7 +1249,7 @@ minstrel_ht_tx_status(void *priv, struct
- struct ieee80211_tx_info *info = st->info;
- struct minstrel_ht_sta *mi = priv_sta;
- struct ieee80211_tx_rate *ar = info->status.rates;
- - struct minstrel_rate_stats *rate, *rate2;
- + struct minstrel_rate_stats *rate;
- struct minstrel_priv *mp = priv;
- u32 update_interval = mp->update_interval;
- bool last, update = false;
- @@ -1354,18 +1317,13 @@ minstrel_ht_tx_status(void *priv, struct
- /*
- * check for sudden death of spatial multiplexing,
- * downgrade to a lower number of streams if necessary.
- + * only do this for the max_prob_rate to prevent spurious
- + * rate fluctuations when the link changes suddenly
- */
- - rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
- + rate = minstrel_get_ratestats(mi, mi->max_prob_rate);
- if (rate->attempts > 30 &&
- rate->success < rate->attempts / 4) {
- - minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true);
- - update = true;
- - }
- -
- - rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]);
- - if (rate2->attempts > 30 &&
- - rate2->success < rate2->attempts / 4) {
- - minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
- + minstrel_downgrade_prob_rate(mi, &mi->max_prob_rate);
- update = true;
- }
- }
|