mac80211: replace legacy minstrel with minstrel_ht, improve rate selection
[openwrt/staging/rmilecki.git] / package / kernel / mac80211 / patches / subsys / 343-mac80211-minstrel_ht-fix-max-probability-rate-select.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sat, 26 Dec 2020 19:09:08 +0100
3 Subject: [PATCH] mac80211: minstrel_ht: fix max probability rate selection
4
5 - do not select rates faster than the max throughput rate if probability is lower
6 - reset previous rate before sorting again
7
8 This ensures that the max prob rate gets set to a more reliable rate
9
10 Signed-off-by: Felix Fietkau <nbd@nbd.name>
11 ---
12
13 --- a/net/mac80211/rc80211_minstrel_ht.c
14 +++ b/net/mac80211/rc80211_minstrel_ht.c
15 @@ -495,12 +495,13 @@ minstrel_ht_sort_best_tp_rates(struct mi
16 * Find and set the topmost probability rate per sta and per group
17 */
18 static void
19 -minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
20 +minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 *dest, u16 index)
21 {
22 struct minstrel_mcs_group_data *mg;
23 struct minstrel_rate_stats *mrs;
24 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
25 - int max_tp_group, cur_tp_avg, cur_group, cur_idx;
26 + int max_tp_group, max_tp_idx, max_tp_prob;
27 + int cur_tp_avg, cur_group, cur_idx;
28 int max_gpr_group, max_gpr_idx;
29 int max_gpr_tp_avg, max_gpr_prob;
30
31 @@ -509,18 +510,26 @@ minstrel_ht_set_best_prob_rate(struct mi
32 mg = &mi->groups[index / MCS_GROUP_RATES];
33 mrs = &mg->rates[index % MCS_GROUP_RATES];
34
35 - tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
36 - tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
37 + tmp_group = *dest / MCS_GROUP_RATES;
38 + tmp_idx = *dest % MCS_GROUP_RATES;
39 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
40 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
41
42 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
43 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */
44 max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES;
45 + max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES;
46 + max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg;
47 +
48 if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) &&
49 !minstrel_ht_is_legacy_group(max_tp_group))
50 return;
51
52 + /* skip rates faster than max tp rate with lower prob */
53 + if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) &&
54 + mrs->prob_avg < max_tp_prob)
55 + return;
56 +
57 max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
58 max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
59 max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
60 @@ -538,7 +547,7 @@ minstrel_ht_set_best_prob_rate(struct mi
61 mg->max_group_prob_rate = index;
62 } else {
63 if (mrs->prob_avg > tmp_prob)
64 - mi->max_prob_rate = index;
65 + *dest = index;
66 if (mrs->prob_avg > max_gpr_prob)
67 mg->max_group_prob_rate = index;
68 }
69 @@ -816,7 +825,8 @@ minstrel_ht_update_stats(struct minstrel
70 struct minstrel_rate_stats *mrs;
71 int group, i, j, cur_prob;
72 u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
73 - u16 tmp_legacy_tp_rate[MAX_THR_RATES], index;
74 + u16 tmp_legacy_tp_rate[MAX_THR_RATES], tmp_max_prob_rate;
75 + u16 index;
76 bool ht_supported = mi->sta->ht_cap.ht_supported;
77
78 mi->sample_mode = MINSTREL_SAMPLE_IDLE;
79 @@ -903,9 +913,6 @@ minstrel_ht_update_stats(struct minstrel
80 /* Find max throughput rate set within a group */
81 minstrel_ht_sort_best_tp_rates(mi, index,
82 tmp_group_tp_rate);
83 -
84 - /* Find max probability rate per group and global */
85 - minstrel_ht_set_best_prob_rate(mi, index);
86 }
87
88 memcpy(mg->max_group_tp_rate, tmp_group_tp_rate,
89 @@ -917,6 +924,27 @@ minstrel_ht_update_stats(struct minstrel
90 tmp_legacy_tp_rate);
91 memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate));
92
93 + for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
94 + if (!mi->supported[group])
95 + continue;
96 +
97 + mg = &mi->groups[group];
98 + mg->max_group_prob_rate = MCS_GROUP_RATES * group;
99 +
100 + for (i = 0; i < MCS_GROUP_RATES; i++) {
101 + if (!(mi->supported[group] & BIT(i)))
102 + continue;
103 +
104 + index = MCS_GROUP_RATES * group + i;
105 +
106 + /* Find max probability rate per group and global */
107 + minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate,
108 + index);
109 + }
110 + }
111 +
112 + mi->max_prob_rate = tmp_max_prob_rate;
113 +
114 /* Try to increase robustness of max_prob_rate*/
115 minstrel_ht_prob_rate_reduce_streams(mi);
116