Commit 965237ab authored by Felix Fietkau's avatar Felix Fietkau Committed by Johannes Berg

mac80211/minstrel_ht: increase sampling frequency of some slower rates

If a rate is below the max_tp_rate, sample it frequently if:
- it is above max_tp_rate2, or
- it is above max_prob_rate and is a candidate for max_prob_rate
  (has fewer streams than max_tp_rate).
This helps the retry chain recover more quickly from bad statistics
caused by collisions or interference, and slightly reduces throughput
fluctuations with higher rates.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 96d4ac3f
...@@ -246,7 +246,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -246,7 +246,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
struct minstrel_rate_stats *mr; struct minstrel_rate_stats *mr;
int cur_prob, cur_prob_tp, cur_tp, cur_tp2; int cur_prob, cur_prob_tp, cur_tp, cur_tp2;
int group, i, index; int group, i, index;
int prob_max_streams = 1;
if (mi->ampdu_packets > 0) { if (mi->ampdu_packets > 0) {
mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len, mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
...@@ -330,7 +329,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -330,7 +329,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
cur_tp2 = cur_tp; cur_tp2 = cur_tp;
mi->max_tp_rate = mg->max_tp_rate; mi->max_tp_rate = mg->max_tp_rate;
cur_tp = mr->cur_tp; cur_tp = mr->cur_tp;
prob_max_streams = minstrel_mcs_groups[group].streams - 1; mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1;
} }
mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); mr = minstrel_get_ratestats(mi, mg->max_tp_rate2);
...@@ -340,8 +339,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -340,8 +339,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
} }
} }
if (prob_max_streams < 1) if (mi->max_prob_streams < 1)
prob_max_streams = 1; mi->max_prob_streams = 1;
for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
mg = &mi->groups[group]; mg = &mi->groups[group];
...@@ -349,7 +348,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -349,7 +348,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
continue; continue;
mr = minstrel_get_ratestats(mi, mg->max_prob_rate); mr = minstrel_get_ratestats(mi, mg->max_prob_rate);
if (cur_prob_tp < mr->cur_tp && if (cur_prob_tp < mr->cur_tp &&
minstrel_mcs_groups[group].streams <= prob_max_streams) { minstrel_mcs_groups[group].streams <= mi->max_prob_streams) {
mi->max_prob_rate = mg->max_prob_rate; mi->max_prob_rate = mg->max_prob_rate;
cur_prob = mr->cur_prob; cur_prob = mr->cur_prob;
cur_prob_tp = mr->cur_tp; cur_prob_tp = mr->cur_tp;
...@@ -630,6 +629,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -630,6 +629,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
{ {
struct minstrel_rate_stats *mr; struct minstrel_rate_stats *mr;
struct minstrel_mcs_group_data *mg; struct minstrel_mcs_group_data *mg;
unsigned int sample_dur, sample_group;
int sample_idx = 0; int sample_idx = 0;
if (mi->sample_wait > 0) { if (mi->sample_wait > 0) {
...@@ -644,7 +644,8 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -644,7 +644,8 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
mg = &mi->groups[mi->sample_group]; mg = &mi->groups[mi->sample_group];
sample_idx = sample_table[mg->column][mg->index]; sample_idx = sample_table[mg->column][mg->index];
mr = &mg->rates[sample_idx]; mr = &mg->rates[sample_idx];
sample_idx += mi->sample_group * MCS_GROUP_RATES; sample_group = mi->sample_group;
sample_idx += sample_group * MCS_GROUP_RATES;
minstrel_next_sample_idx(mi); minstrel_next_sample_idx(mi);
/* /*
...@@ -665,8 +666,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) ...@@ -665,8 +666,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
* Make sure that lower rates get sampled only occasionally, * Make sure that lower rates get sampled only occasionally,
* if the link is working perfectly. * if the link is working perfectly.
*/ */
if (minstrel_get_duration(sample_idx) > sample_dur = minstrel_get_duration(sample_idx);
minstrel_get_duration(mi->max_tp_rate)) { if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) &&
(mi->max_prob_streams <
minstrel_mcs_groups[sample_group].streams ||
sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
if (mr->sample_skipped < 20) if (mr->sample_skipped < 20)
return -1; return -1;
......
...@@ -85,6 +85,7 @@ struct minstrel_ht_sta { ...@@ -85,6 +85,7 @@ struct minstrel_ht_sta {
/* best probability rate */ /* best probability rate */
unsigned int max_prob_rate; unsigned int max_prob_rate;
unsigned int max_prob_streams;
/* time of last status update */ /* time of last status update */
unsigned long stats_update; unsigned long stats_update;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment