0dbfa9d4fb430e9d0f230e8d27d569a1e3aec6f8
[openwrt/staging/jow.git] /
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 @@ -863,6 +873,7 @@ minstrel_ht_update_stats(struct minstrel
80 else
81 index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES;
82
83 + tmp_max_prob_rate = index;
84 for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++)
85 tmp_mcs_tp_rate[j] = index;
86
87 @@ -903,9 +914,6 @@ minstrel_ht_update_stats(struct minstrel
88 /* Find max throughput rate set within a group */
89 minstrel_ht_sort_best_tp_rates(mi, index,
90 tmp_group_tp_rate);
91 -
92 - /* Find max probability rate per group and global */
93 - minstrel_ht_set_best_prob_rate(mi, index);
94 }
95
96 memcpy(mg->max_group_tp_rate, tmp_group_tp_rate,
97 @@ -917,6 +925,27 @@ minstrel_ht_update_stats(struct minstrel
98 tmp_legacy_tp_rate);
99 memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate));
100
101 + for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
102 + if (!mi->supported[group])
103 + continue;
104 +
105 + mg = &mi->groups[group];
106 + mg->max_group_prob_rate = MCS_GROUP_RATES * group;
107 +
108 + for (i = 0; i < MCS_GROUP_RATES; i++) {
109 + if (!(mi->supported[group] & BIT(i)))
110 + continue;
111 +
112 + index = MCS_GROUP_RATES * group + i;
113 +
114 + /* Find max probability rate per group and global */
115 + minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate,
116 + index);
117 + }
118 + }
119 +
120 + mi->max_prob_rate = tmp_max_prob_rate;
121 +
122 /* Try to increase robustness of max_prob_rate*/
123 minstrel_ht_prob_rate_reduce_streams(mi);
124