blob: 6aa6f0ed934812af7345c560c4bf07d24d4f8daf [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From: Felix Fietkau <nbd@nbd.name>
2Date: Thu, 21 Jan 2021 18:29:30 +0100
3Subject: [PATCH] mac80211: minstrel_ht: use bitfields to encode rate
4 indexes
5
6Get rid of a lot of divisions and modulo operations
7Reduces code size and improves performance
8
9Signed-off-by: Felix Fietkau <nbd@nbd.name>
10---
11
12--- a/net/mac80211/rc80211_minstrel_ht.c
13+++ b/net/mac80211/rc80211_minstrel_ht.c
14@@ -379,14 +379,14 @@ out:
15 static inline struct minstrel_rate_stats *
16 minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
17 {
18- return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
19+ return &mi->groups[MI_RATE_GROUP(index)].rates[MI_RATE_IDX(index)];
20 }
21
22-static inline int
23-minstrel_get_duration(int index)
24+static inline int minstrel_get_duration(int index)
25 {
26- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
27- unsigned int duration = group->duration[index % MCS_GROUP_RATES];
28+ const struct mcs_group *group = &minstrel_mcs_groups[MI_RATE_GROUP(index)];
29+ unsigned int duration = group->duration[MI_RATE_IDX(index)];
30+
31 return duration << group->shift;
32 }
33
34@@ -398,7 +398,7 @@ minstrel_ht_avg_ampdu_len(struct minstre
35 if (mi->avg_ampdu_len)
36 return MINSTREL_TRUNC(mi->avg_ampdu_len);
37
38- if (minstrel_ht_is_legacy_group(mi->max_tp_rate[0] / MCS_GROUP_RATES))
39+ if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_tp_rate[0])))
40 return 1;
41
42 duration = minstrel_get_duration(mi->max_tp_rate[0]);
43@@ -465,14 +465,14 @@ minstrel_ht_sort_best_tp_rates(struct mi
44 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
45 int j = MAX_THR_RATES;
46
47- cur_group = index / MCS_GROUP_RATES;
48- cur_idx = index % MCS_GROUP_RATES;
49+ cur_group = MI_RATE_GROUP(index);
50+ cur_idx = MI_RATE_IDX(index);
51 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg;
52 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob);
53
54 do {
55- tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
56- tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
57+ tmp_group = MI_RATE_GROUP(tp_list[j - 1]);
58+ tmp_idx = MI_RATE_IDX(tp_list[j - 1]);
59 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
60 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx,
61 tmp_prob);
62@@ -504,23 +504,23 @@ minstrel_ht_set_best_prob_rate(struct mi
63 int max_gpr_group, max_gpr_idx;
64 int max_gpr_tp_avg, max_gpr_prob;
65
66- cur_group = index / MCS_GROUP_RATES;
67- cur_idx = index % MCS_GROUP_RATES;
68- mg = &mi->groups[index / MCS_GROUP_RATES];
69- mrs = &mg->rates[index % MCS_GROUP_RATES];
70+ cur_group = MI_RATE_GROUP(index);
71+ cur_idx = MI_RATE_IDX(index);
72+ mg = &mi->groups[cur_group];
73+ mrs = &mg->rates[cur_idx];
74
75- tmp_group = *dest / MCS_GROUP_RATES;
76- tmp_idx = *dest % MCS_GROUP_RATES;
77+ tmp_group = MI_RATE_GROUP(*dest);
78+ tmp_idx = MI_RATE_IDX(*dest);
79 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
80 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
81
82 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
83 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */
84- max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES;
85- max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES;
86+ max_tp_group = MI_RATE_GROUP(mi->max_tp_rate[0]);
87+ max_tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]);
88 max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg;
89
90- if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) &&
91+ if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(index)) &&
92 !minstrel_ht_is_legacy_group(max_tp_group))
93 return;
94
95@@ -529,8 +529,8 @@ minstrel_ht_set_best_prob_rate(struct mi
96 mrs->prob_avg < max_tp_prob)
97 return;
98
99- max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
100- max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
101+ max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate);
102+ max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate);
103 max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
104
105 if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) {
106@@ -567,13 +567,13 @@ minstrel_ht_assign_best_tp_rates(struct
107 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob;
108 int i;
109
110- tmp_group = tmp_legacy_tp_rate[0] / MCS_GROUP_RATES;
111- tmp_idx = tmp_legacy_tp_rate[0] % MCS_GROUP_RATES;
112+ tmp_group = MI_RATE_GROUP(tmp_legacy_tp_rate[0]);
113+ tmp_idx = MI_RATE_IDX(tmp_legacy_tp_rate[0]);
114 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
115 tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
116
117- tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
118- tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
119+ tmp_group = MI_RATE_GROUP(tmp_mcs_tp_rate[0]);
120+ tmp_idx = MI_RATE_IDX(tmp_mcs_tp_rate[0]);
121 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
122 tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
123
124@@ -600,14 +600,14 @@ minstrel_ht_prob_rate_reduce_streams(str
125 if (!mi->sta->ht_cap.ht_supported)
126 return;
127
128- tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
129- MCS_GROUP_RATES].streams;
130+ group = MI_RATE_GROUP(mi->max_tp_rate[0]);
131+ tmp_max_streams = minstrel_mcs_groups[group].streams;
132 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
133 mg = &mi->groups[group];
134 if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
135 continue;
136
137- tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
138+ tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate);
139 tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg;
140
141 if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
142@@ -644,8 +644,8 @@ minstrel_ht_find_probe_rates(struct mins
143 int i, g, max_dur;
144 int tp_idx;
145
146- tp_group = &minstrel_mcs_groups[mi->max_tp_rate[0] / MCS_GROUP_RATES];
147- tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES;
148+ tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])];
149+ tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]);
150
151 max_dur = minstrel_get_duration(mi->max_tp_rate[0]);
152 if (faster_rate)
153@@ -670,7 +670,7 @@ minstrel_ht_find_probe_rates(struct mins
154 if ((group->duration[i] << group->shift) > max_dur)
155 continue;
156
157- idx = g * MCS_GROUP_RATES + i;
158+ idx = MI_RATE(g, i);
159 if (idx == mi->max_tp_rate[0])
160 continue;
161
162@@ -712,10 +712,10 @@ minstrel_ht_rate_sample_switch(struct mi
163
164 /* If no suitable rate was found, try to pick the next one in the group */
165 if (!n_rates) {
166- int g_idx = mi->max_tp_rate[0] / MCS_GROUP_RATES;
167+ int g_idx = MI_RATE_GROUP(mi->max_tp_rate[0]);
168 u16 supported = mi->supported[g_idx];
169
170- supported >>= mi->max_tp_rate[0] % MCS_GROUP_RATES;
171+ supported >>= MI_RATE_IDX(mi->max_tp_rate[0]);
172 for (i = 0; supported; supported >>= 1, i++) {
173 if (!(supported & 1))
174 continue;
175@@ -854,24 +854,27 @@ minstrel_ht_update_stats(struct minstrel
176 mi->sample_slow = 0;
177 mi->sample_count = 0;
178
179- memset(tmp_mcs_tp_rate, 0, sizeof(tmp_mcs_tp_rate));
180- memset(tmp_legacy_tp_rate, 0, sizeof(tmp_legacy_tp_rate));
181 if (mi->supported[MINSTREL_CCK_GROUP])
182- for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++)
183- tmp_legacy_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES;
184+ group = MINSTREL_CCK_GROUP;
185 else if (mi->supported[MINSTREL_OFDM_GROUP])
186- for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++)
187- tmp_legacy_tp_rate[j] = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES;
188+ group = MINSTREL_OFDM_GROUP;
189+ else
190+ group = 0;
191+
192+ index = MI_RATE(group, 0);
193+ for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++)
194+ tmp_legacy_tp_rate[j] = index;
195
196 if (mi->supported[MINSTREL_VHT_GROUP_0])
197- index = MINSTREL_VHT_GROUP_0 * MCS_GROUP_RATES;
198+ group = MINSTREL_VHT_GROUP_0;
199 else if (ht_supported)
200- index = MINSTREL_HT_GROUP_0 * MCS_GROUP_RATES;
201+ group = MINSTREL_HT_GROUP_0;
202 else if (mi->supported[MINSTREL_CCK_GROUP])
203- index = MINSTREL_CCK_GROUP * MCS_GROUP_RATES;
204+ group = MINSTREL_CCK_GROUP;
205 else
206- index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES;
207+ group = MINSTREL_OFDM_GROUP;
208
209+ index = MI_RATE(group, 0);
210 tmp_max_prob_rate = index;
211 for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++)
212 tmp_mcs_tp_rate[j] = index;
213@@ -888,7 +891,7 @@ minstrel_ht_update_stats(struct minstrel
214
215 /* (re)Initialize group rate indexes */
216 for(j = 0; j < MAX_THR_RATES; j++)
217- tmp_group_tp_rate[j] = MCS_GROUP_RATES * group;
218+ tmp_group_tp_rate[j] = MI_RATE(group, 0);
219
220 if (group == MINSTREL_CCK_GROUP && ht_supported)
221 tp_rate = tmp_legacy_tp_rate;
222@@ -897,7 +900,7 @@ minstrel_ht_update_stats(struct minstrel
223 if (!(mi->supported[group] & BIT(i)))
224 continue;
225
226- index = MCS_GROUP_RATES * group + i;
227+ index = MI_RATE(group, i);
228
229 mrs = &mg->rates[i];
230 mrs->retry_updated = false;
231@@ -929,13 +932,13 @@ minstrel_ht_update_stats(struct minstrel
232 continue;
233
234 mg = &mi->groups[group];
235- mg->max_group_prob_rate = MCS_GROUP_RATES * group;
236+ mg->max_group_prob_rate = MI_RATE(group, 0);
237
238 for (i = 0; i < MCS_GROUP_RATES; i++) {
239 if (!(mi->supported[group] & BIT(i)))
240 continue;
241
242- index = MCS_GROUP_RATES * group + i;
243+ index = MI_RATE(group, i);
244
245 /* Find max probability rate per group and global */
246 minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate,
247@@ -1022,7 +1025,7 @@ minstrel_downgrade_rate(struct minstrel_
248 {
249 int group, orig_group;
250
251- orig_group = group = *idx / MCS_GROUP_RATES;
252+ orig_group = group = MI_RATE_GROUP(*idx);
253 while (group > 0) {
254 group--;
255
256@@ -1206,7 +1209,7 @@ minstrel_calc_retransmit(struct minstrel
257 ctime += (t_slot * cw) >> 1;
258 cw = min((cw << 1) | 1, mp->cw_max);
259
260- if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES)) {
261+ if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(index))) {
262 overhead = mi->overhead_legacy;
263 overhead_rtscts = mi->overhead_legacy_rtscts;
264 } else {
265@@ -1239,7 +1242,7 @@ static void
266 minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
267 struct ieee80211_sta_rates *ratetbl, int offset, int index)
268 {
269- int group_idx = index / MCS_GROUP_RATES;
270+ int group_idx = MI_RATE_GROUP(index);
271 const struct mcs_group *group = &minstrel_mcs_groups[group_idx];
272 struct minstrel_rate_stats *mrs;
273 u8 idx;
274@@ -1259,7 +1262,7 @@ minstrel_ht_set_rate(struct minstrel_pri
275 ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts;
276 }
277
278- index %= MCS_GROUP_RATES;
279+ index = MI_RATE_IDX(index);
280 if (group_idx == MINSTREL_CCK_GROUP)
281 idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
282 else if (group_idx == MINSTREL_OFDM_GROUP)
283@@ -1289,17 +1292,17 @@ minstrel_ht_set_rate(struct minstrel_pri
284 static inline int
285 minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate)
286 {
287- int group = rate / MCS_GROUP_RATES;
288- rate %= MCS_GROUP_RATES;
289+ int group = MI_RATE_GROUP(rate);
290+ rate = MI_RATE_IDX(rate);
291 return mi->groups[group].rates[rate].prob_avg;
292 }
293
294 static int
295 minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi)
296 {
297- int group = mi->max_prob_rate / MCS_GROUP_RATES;
298+ int group = MI_RATE_GROUP(mi->max_prob_rate);
299 const struct mcs_group *g = &minstrel_mcs_groups[group];
300- int rate = mi->max_prob_rate % MCS_GROUP_RATES;
301+ int rate = MI_RATE_IDX(mi->max_prob_rate);
302 unsigned int duration;
303
304 /* Disable A-MSDU if max_prob_rate is bad */
305@@ -1405,7 +1408,7 @@ minstrel_get_sample_rate(struct minstrel
306 return -1;
307
308 mrs = &mg->rates[sample_idx];
309- sample_idx += sample_group * MCS_GROUP_RATES;
310+ sample_idx += MI_RATE(sample_group, 0);
311
312 tp_rate1 = mi->max_tp_rate[0];
313
314@@ -1455,8 +1458,7 @@ minstrel_get_sample_rate(struct minstrel
315 * if the link is working perfectly.
316 */
317
318- cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
319- MCS_GROUP_RATES].streams;
320+ cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams;
321 if (sample_dur >= minstrel_get_duration(tp_rate2) &&
322 (cur_max_tp_streams - 1 <
323 minstrel_mcs_groups[sample_group].streams ||
324@@ -1484,7 +1486,7 @@ minstrel_ht_get_rate(void *priv, struct
325 int sample_idx;
326
327 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
328- !minstrel_ht_is_legacy_group(mi->max_prob_rate / MCS_GROUP_RATES))
329+ !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate)))
330 minstrel_aggr_check(sta, txrc->skb);
331
332 info->flags |= mi->tx_flags;
333@@ -1512,8 +1514,8 @@ minstrel_ht_get_rate(void *priv, struct
334 if (sample_idx < 0)
335 return;
336
337- sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
338- sample_idx %= MCS_GROUP_RATES;
339+ sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)];
340+ sample_idx = MI_RATE_IDX(sample_idx);
341
342 if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] &&
343 (sample_idx >= 4) != txrc->short_preamble)
344@@ -1529,7 +1531,7 @@ minstrel_ht_get_rate(void *priv, struct
345 int idx = sample_idx % ARRAY_SIZE(mp->ofdm_rates[0]);
346 rate->idx = mp->ofdm_rates[mi->band][idx];
347 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
348- ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
349+ ieee80211_rate_set_vht(rate, MI_RATE_IDX(sample_idx),
350 sample_group->streams);
351 } else {
352 rate->idx = sample_idx + (sample_group->streams - 1) * 8;
353@@ -1898,8 +1900,8 @@ static u32 minstrel_ht_get_expected_thro
354 struct minstrel_ht_sta *mi = priv_sta;
355 int i, j, prob, tp_avg;
356
357- i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
358- j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
359+ i = MI_RATE_GROUP(mi->max_tp_rate[0]);
360+ j = MI_RATE_IDX(mi->max_tp_rate[0]);
361 prob = mi->groups[i].rates[j].prob_avg;
362
363 /* convert tp_avg from pkt per second in kbps */
364--- a/net/mac80211/rc80211_minstrel_ht.h
365+++ b/net/mac80211/rc80211_minstrel_ht.h
366@@ -6,6 +6,8 @@
367 #ifndef __RC_MINSTREL_HT_H
368 #define __RC_MINSTREL_HT_H
369
370+#include <linux/bitfield.h>
371+
372 /* number of highest throughput rates to consider*/
373 #define MAX_THR_RATES 4
374 #define SAMPLE_COLUMNS 10 /* number of columns in sample table */
375@@ -57,6 +59,17 @@
376
377 #define MCS_GROUP_RATES 10
378
379+#define MI_RATE_IDX_MASK GENMASK(3, 0)
380+#define MI_RATE_GROUP_MASK GENMASK(15, 4)
381+
382+#define MI_RATE(_group, _idx) \
383+ (FIELD_PREP(MI_RATE_GROUP_MASK, _group) | \
384+ FIELD_PREP(MI_RATE_IDX_MASK, _idx))
385+
386+#define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate)
387+#define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate)
388+
389+
390 struct minstrel_priv {
391 struct ieee80211_hw *hw;
392 bool has_mrr;
393--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
394+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
395@@ -56,7 +56,7 @@ minstrel_ht_stats_dump(struct minstrel_h
396
397 for (j = 0; j < MCS_GROUP_RATES; j++) {
398 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
399- int idx = i * MCS_GROUP_RATES + j;
400+ int idx = MI_RATE(i, j);
401 unsigned int duration;
402
403 if (!(mi->supported[i] & BIT(j)))
404@@ -201,7 +201,7 @@ minstrel_ht_stats_csv_dump(struct minstr
405
406 for (j = 0; j < MCS_GROUP_RATES; j++) {
407 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
408- int idx = i * MCS_GROUP_RATES + j;
409+ int idx = MI_RATE(i, j);
410 unsigned int duration;
411
412 if (!(mi->supported[i] & BIT(j)))