7af13661a8717732fffee759c637a04a58436052
[openwrt/staging/mans0n.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Fri, 22 Jan 2021 23:57:50 +0100
3 Subject: [PATCH] mac80211: minstrel_ht: significantly redesign the rate
4 probing strategy
5
6 The biggest flaw in current minstrel_ht is the fact that it needs way too
7 many probing packets to be able to quickly find the best rate.
8 Depending on the wifi hardware and operating mode, this can significantly
9 reduce throughput when not operating at the highest available data rate.
10
11 In order to be able to significantly reduce the amount of rate sampling,
12 we need a much smarter selection of probing rates.
13
14 The new approach introduced by this patch maintains a limited set of
15 available rates to be tested during a statistics window.
16
17 They are split into distinct categories:
18 - MINSTREL_SAMPLE_TYPE_INC - incremental rate upgrade:
19 Pick the next rate group and find the first rate that is faster than
20 the current max. throughput rate
21 - MINSTREL_SAMPLE_TYPE_JUMP - random testing of higher rates:
22 Pick a random rate from the next group that is faster than the current
23 max throughput rate. This allows faster adaptation when the link changes
24 significantly
25 - MINSTREL_SAMPLE_TYPE_SLOW - test a rate between max_prob, max_tp2 and
26 max_tp in order to reduce the gap between them
27
28 In order to prioritize sampling, every 6 attempts are split into 3x INC,
29 2x JUMP, 1x SLOW.
30
31 Available rates are checked and refilled on every stats window update.
32
33 With this approach, we finally get a very small delta in throughput when
34 comparing setting the optimal data rate as a fixed rate vs normal rate
35 control operation.
36
37 Signed-off-by: Felix Fietkau <nbd@nbd.name>
38 ---
39
40 --- a/net/mac80211/rc80211_minstrel_ht.c
41 +++ b/net/mac80211/rc80211_minstrel_ht.c
42 @@ -266,6 +266,14 @@ const struct mcs_group minstrel_mcs_grou
43 const s16 minstrel_cck_bitrates[4] = { 10, 20, 55, 110 };
44 const s16 minstrel_ofdm_bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 };
45 static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
46 +static const u8 minstrel_sample_seq[] = {
47 + MINSTREL_SAMPLE_TYPE_INC,
48 + MINSTREL_SAMPLE_TYPE_JUMP,
49 + MINSTREL_SAMPLE_TYPE_INC,
50 + MINSTREL_SAMPLE_TYPE_JUMP,
51 + MINSTREL_SAMPLE_TYPE_INC,
52 + MINSTREL_SAMPLE_TYPE_SLOW,
53 +};
54
55 static void
56 minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
57 @@ -620,77 +628,31 @@ minstrel_ht_prob_rate_reduce_streams(str
58 }
59 }
60
61 -static bool
62 -minstrel_ht_probe_group(struct minstrel_ht_sta *mi, const struct mcs_group *tp_group,
63 - int tp_idx, const struct mcs_group *group)
64 -{
65 - if (group->bw < tp_group->bw)
66 - return false;
67 -
68 - if (group->streams == tp_group->streams)
69 - return true;
70 -
71 - if (tp_idx < 4 && group->streams == tp_group->streams - 1)
72 - return true;
73 -
74 - return group->streams == tp_group->streams + 1;
75 -}
76 -
77 -static void
78 -minstrel_ht_find_probe_rates(struct minstrel_ht_sta *mi, u16 *rates, int *n_rates,
79 - bool faster_rate)
80 +static u16
81 +__minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
82 + enum minstrel_sample_type type)
83 {
84 - const struct mcs_group *group, *tp_group;
85 - int i, g, max_dur;
86 - int tp_idx;
87 -
88 - tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])];
89 - tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]);
90 -
91 - max_dur = minstrel_get_duration(mi->max_tp_rate[0]);
92 - if (faster_rate)
93 - max_dur -= max_dur / 16;
94 -
95 - for (g = 0; g < MINSTREL_GROUPS_NB; g++) {
96 - u16 supported = mi->supported[g];
97 -
98 - if (!supported)
99 - continue;
100 + u16 *rates = mi->sample[type].sample_rates;
101 + u16 cur;
102 + int i;
103
104 - group = &minstrel_mcs_groups[g];
105 - if (!minstrel_ht_probe_group(mi, tp_group, tp_idx, group))
106 + for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) {
107 + if (!rates[i])
108 continue;
109
110 - for (i = 0; supported; supported >>= 1, i++) {
111 - int idx;
112 -
113 - if (!(supported & 1))
114 - continue;
115 -
116 - if ((group->duration[i] << group->shift) > max_dur)
117 - continue;
118 -
119 - idx = MI_RATE(g, i);
120 - if (idx == mi->max_tp_rate[0])
121 - continue;
122 -
123 - rates[(*n_rates)++] = idx;
124 - break;
125 - }
126 + cur = rates[i];
127 + rates[i] = 0;
128 + return cur;
129 }
130 +
131 + return 0;
132 }
133
134 static void
135 minstrel_ht_rate_sample_switch(struct minstrel_priv *mp,
136 struct minstrel_ht_sta *mi)
137 {
138 - struct minstrel_rate_stats *mrs;
139 - u16 rates[MINSTREL_GROUPS_NB];
140 - int n_rates = 0;
141 - int probe_rate = 0;
142 - bool faster_rate;
143 - int i;
144 - u8 random;
145 + u16 rate;
146
147 /*
148 * Use rate switching instead of probing packets for devices with
149 @@ -699,43 +661,11 @@ minstrel_ht_rate_sample_switch(struct mi
150 if (mp->hw->max_rates > 1)
151 return;
152
153 - /*
154 - * If the current EWMA prob is >75%, look for a rate that's 6.25%
155 - * faster than the max tp rate.
156 - * If that fails, look again for a rate that is at least as fast
157 - */
158 - mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
159 - faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100);
160 - minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate);
161 - if (!n_rates && faster_rate)
162 - minstrel_ht_find_probe_rates(mi, rates, &n_rates, false);
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_RATE_GROUP(mi->max_tp_rate[0]);
167 - u16 supported = mi->supported[g_idx];
168 -
169 - supported >>= MI_RATE_IDX(mi->max_tp_rate[0]);
170 - for (i = 0; supported; supported >>= 1, i++) {
171 - if (!(supported & 1))
172 - continue;
173 -
174 - probe_rate = mi->max_tp_rate[0] + i;
175 - goto out;
176 - }
177 -
178 + rate = __minstrel_ht_get_sample_rate(mi, MINSTREL_SAMPLE_TYPE_INC);
179 + if (!rate)
180 return;
181 - }
182
183 - i = 0;
184 - if (n_rates > 1) {
185 - random = prandom_u32();
186 - i = random % n_rates;
187 - }
188 - probe_rate = rates[i];
189 -
190 -out:
191 - mi->sample_rate = probe_rate;
192 + mi->sample_rate = rate;
193 mi->sample_mode = MINSTREL_SAMPLE_ACTIVE;
194 }
195
196 @@ -804,6 +734,274 @@ minstrel_ht_calc_rate_stats(struct minst
197 mrs->attempts = 0;
198 }
199
200 +static bool
201 +minstrel_ht_find_sample_rate(struct minstrel_ht_sta *mi, int type, int idx)
202 +{
203 + int i;
204 +
205 + for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) {
206 + u16 cur = mi->sample[type].sample_rates[i];
207 +
208 + if (cur == idx)
209 + return true;
210 +
211 + if (!cur)
212 + break;
213 + }
214 +
215 + return false;
216 +}
217 +
218 +static int
219 +minstrel_ht_move_sample_rates(struct minstrel_ht_sta *mi, int type,
220 + u32 fast_rate_dur, u32 slow_rate_dur)
221 +{
222 + u16 *rates = mi->sample[type].sample_rates;
223 + int i, j;
224 +
225 + for (i = 0, j = 0; i < MINSTREL_SAMPLE_RATES; i++) {
226 + u32 duration;
227 + bool valid = false;
228 + u16 cur;
229 +
230 + cur = rates[i];
231 + if (!cur)
232 + continue;
233 +
234 + duration = minstrel_get_duration(cur);
235 + switch (type) {
236 + case MINSTREL_SAMPLE_TYPE_SLOW:
237 + valid = duration > fast_rate_dur &&
238 + duration < slow_rate_dur;
239 + break;
240 + case MINSTREL_SAMPLE_TYPE_INC:
241 + case MINSTREL_SAMPLE_TYPE_JUMP:
242 + valid = duration < fast_rate_dur;
243 + break;
244 + default:
245 + valid = false;
246 + break;
247 + }
248 +
249 + if (!valid) {
250 + rates[i] = 0;
251 + continue;
252 + }
253 +
254 + if (i == j)
255 + continue;
256 +
257 + rates[j++] = cur;
258 + rates[i] = 0;
259 + }
260 +
261 + return j;
262 +}
263 +
264 +static int
265 +minstrel_ht_group_min_rate_offset(struct minstrel_ht_sta *mi, int group,
266 + u32 max_duration)
267 +{
268 + u16 supported = mi->supported[group];
269 + int i;
270 +
271 + for (i = 0; i < MCS_GROUP_RATES && supported; i++, supported >>= 1) {
272 + if (!(supported & BIT(0)))
273 + continue;
274 +
275 + if (minstrel_get_duration(MI_RATE(group, i)) >= max_duration)
276 + continue;
277 +
278 + return i;
279 + }
280 +
281 + return -1;
282 +}
283 +
284 +/*
285 + * Incremental update rates:
286 + * Flip through groups and pick the first group rate that is faster than the
287 + * highest currently selected rate
288 + */
289 +static u16
290 +minstrel_ht_next_inc_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur)
291 +{
292 + struct minstrel_mcs_group_data *mg;
293 + u8 type = MINSTREL_SAMPLE_TYPE_INC;
294 + int i, index = 0;
295 + u8 group;
296 +
297 + group = mi->sample[type].sample_group;
298 + for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) {
299 + group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups);
300 + mg = &mi->groups[group];
301 +
302 + index = minstrel_ht_group_min_rate_offset(mi, group,
303 + fast_rate_dur);
304 + if (index < 0)
305 + continue;
306 +
307 + index = MI_RATE(group, index & 0xf);
308 + if (!minstrel_ht_find_sample_rate(mi, type, index))
309 + goto out;
310 + }
311 + index = 0;
312 +
313 +out:
314 + mi->sample[type].sample_group = group;
315 +
316 + return index;
317 +}
318 +
319 +static int
320 +minstrel_ht_next_group_sample_rate(struct minstrel_ht_sta *mi, int group,
321 + u16 supported, int offset)
322 +{
323 + struct minstrel_mcs_group_data *mg = &mi->groups[group];
324 + u16 idx;
325 + int i;
326 +
327 + for (i = 0; i < MCS_GROUP_RATES; i++) {
328 + idx = sample_table[mg->column][mg->index];
329 + if (++mg->index >= MCS_GROUP_RATES) {
330 + mg->index = 0;
331 + if (++mg->column >= ARRAY_SIZE(sample_table))
332 + mg->column = 0;
333 + }
334 +
335 + if (idx < offset)
336 + continue;
337 +
338 + if (!(supported & BIT(idx)))
339 + continue;
340 +
341 + return MI_RATE(group, idx);
342 + }
343 +
344 + return -1;
345 +}
346 +
347 +/*
348 + * Jump rates:
349 + * Sample random rates, use those that are faster than the highest
350 + * currently selected rate. Rates between the fastest and the slowest
351 + * get sorted into the slow sample bucket, but only if it has room
352 + */
353 +static u16
354 +minstrel_ht_next_jump_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur,
355 + u32 slow_rate_dur, int *slow_rate_ofs)
356 +{
357 + struct minstrel_mcs_group_data *mg;
358 + struct minstrel_rate_stats *mrs;
359 + u32 max_duration = slow_rate_dur;
360 + int i, index, offset;
361 + u16 *slow_rates;
362 + u16 supported;
363 + u32 duration;
364 + u8 group;
365 +
366 + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES)
367 + max_duration = fast_rate_dur;
368 +
369 + slow_rates = mi->sample[MINSTREL_SAMPLE_TYPE_SLOW].sample_rates;
370 + group = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group;
371 + for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) {
372 + u8 type;
373 +
374 + group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups);
375 + mg = &mi->groups[group];
376 +
377 + supported = mi->supported[group];
378 + if (!supported)
379 + continue;
380 +
381 + offset = minstrel_ht_group_min_rate_offset(mi, group,
382 + max_duration);
383 + if (offset < 0)
384 + continue;
385 +
386 + index = minstrel_ht_next_group_sample_rate(mi, group, supported,
387 + offset);
388 + if (index < 0)
389 + continue;
390 +
391 + duration = minstrel_get_duration(index);
392 + if (duration < fast_rate_dur)
393 + type = MINSTREL_SAMPLE_TYPE_JUMP;
394 + else
395 + type = MINSTREL_SAMPLE_TYPE_SLOW;
396 +
397 + if (minstrel_ht_find_sample_rate(mi, type, index))
398 + continue;
399 +
400 + if (type == MINSTREL_SAMPLE_TYPE_JUMP)
401 + goto found;
402 +
403 + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES)
404 + continue;
405 +
406 + if (duration >= slow_rate_dur)
407 + continue;
408 +
409 + /* skip slow rates with high success probability */
410 + mrs = minstrel_get_ratestats(mi, index);
411 + if (mrs->prob_avg > MINSTREL_FRAC(95, 100))
412 + continue;
413 +
414 + slow_rates[(*slow_rate_ofs)++] = index;
415 + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES)
416 + max_duration = fast_rate_dur;
417 + }
418 + index = 0;
419 +
420 +found:
421 + mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group = group;
422 +
423 + return index;
424 +}
425 +
426 +static void
427 +minstrel_ht_refill_sample_rates(struct minstrel_ht_sta *mi)
428 +{
429 + u32 prob_dur = minstrel_get_duration(mi->max_prob_rate);
430 + u32 tp_dur = minstrel_get_duration(mi->max_tp_rate[0]);
431 + u32 tp2_dur = minstrel_get_duration(mi->max_tp_rate[1]);
432 + u32 fast_rate_dur = min(min(tp_dur, tp2_dur), prob_dur);
433 + u32 slow_rate_dur = max(max(tp_dur, tp2_dur), prob_dur);
434 + u16 *rates;
435 + int i, j;
436 +
437 + rates = mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates;
438 + i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_INC,
439 + fast_rate_dur, slow_rate_dur);
440 + while (i < MINSTREL_SAMPLE_RATES) {
441 + rates[i] = minstrel_ht_next_inc_rate(mi, tp_dur);
442 + if (!rates[i])
443 + break;
444 +
445 + i++;
446 + }
447 +
448 + rates = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_rates;
449 + i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_JUMP,
450 + fast_rate_dur, slow_rate_dur);
451 + j = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_SLOW,
452 + fast_rate_dur, slow_rate_dur);
453 + while (i < MINSTREL_SAMPLE_RATES) {
454 + rates[i] = minstrel_ht_next_jump_rate(mi, fast_rate_dur,
455 + slow_rate_dur, &j);
456 + if (!rates[i])
457 + break;
458 +
459 + i++;
460 + }
461 +
462 + for (i = 0; i < ARRAY_SIZE(mi->sample); i++)
463 + memcpy(mi->sample[i].cur_sample_rates, mi->sample[i].sample_rates,
464 + sizeof(mi->sample[i].cur_sample_rates));
465 +}
466 +
467 +
468 /*
469 * Update rate statistics and select new primary rates
470 *
471 @@ -848,8 +1046,6 @@ minstrel_ht_update_stats(struct minstrel
472 mi->ampdu_packets = 0;
473 }
474
475 - mi->sample_count = 0;
476 -
477 if (mi->supported[MINSTREL_CCK_GROUP])
478 group = MINSTREL_CCK_GROUP;
479 else if (mi->supported[MINSTREL_OFDM_GROUP])
480 @@ -884,8 +1080,6 @@ minstrel_ht_update_stats(struct minstrel
481 if (!mi->supported[group])
482 continue;
483
484 - mi->sample_count++;
485 -
486 /* (re)Initialize group rate indexes */
487 for(j = 0; j < MAX_THR_RATES; j++)
488 tmp_group_tp_rate[j] = MI_RATE(group, 0);
489 @@ -952,9 +1146,7 @@ minstrel_ht_update_stats(struct minstrel
490
491 /* Try to increase robustness of max_prob_rate*/
492 minstrel_ht_prob_rate_reduce_streams(mi);
493 -
494 - /* try to sample half of all available rates during each interval */
495 - mi->sample_count *= 4;
496 + minstrel_ht_refill_sample_rates(mi);
497
498 if (sample)
499 minstrel_ht_rate_sample_switch(mp, mi);
500 @@ -971,6 +1163,7 @@ minstrel_ht_update_stats(struct minstrel
501
502 /* Reset update timer */
503 mi->last_stats_update = jiffies;
504 + mi->sample_time = jiffies;
505 }
506
507 static bool
508 @@ -1001,28 +1194,6 @@ minstrel_ht_txstat_valid(struct minstrel
509 }
510
511 static void
512 -minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi)
513 -{
514 - struct minstrel_mcs_group_data *mg;
515 -
516 - for (;;) {
517 - mi->sample_group++;
518 - mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups);
519 - mg = &mi->groups[mi->sample_group];
520 -
521 - if (!mi->supported[mi->sample_group])
522 - continue;
523 -
524 - if (++mg->index >= MCS_GROUP_RATES) {
525 - mg->index = 0;
526 - if (++mg->column >= ARRAY_SIZE(sample_table))
527 - mg->column = 0;
528 - }
529 - break;
530 - }
531 -}
532 -
533 -static void
534 minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
535 {
536 int group, orig_group;
537 @@ -1107,14 +1278,6 @@ minstrel_ht_tx_status(void *priv, struct
538 mi->ampdu_packets++;
539 mi->ampdu_len += info->status.ampdu_len;
540
541 - if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
542 - int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi);
543 -
544 - mi->sample_wait = 16 + 2 * avg_ampdu_len;
545 - mi->sample_tries = 1;
546 - mi->sample_count--;
547 - }
548 -
549 if (mi->sample_mode != MINSTREL_SAMPLE_IDLE)
550 rate_sample = minstrel_get_ratestats(mi, mi->sample_rate);
551
552 @@ -1386,97 +1549,20 @@ minstrel_ht_update_rates(struct minstrel
553 rate_control_set_rates(mp->hw, mi->sta, rates);
554 }
555
556 -static int
557 -minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
558 +static u16
559 +minstrel_ht_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
560 {
561 - struct minstrel_rate_stats *mrs;
562 - struct minstrel_mcs_group_data *mg;
563 - unsigned int sample_dur, sample_group, cur_max_tp_streams;
564 - int tp_rate1, tp_rate2;
565 - int sample_idx = 0;
566 -
567 - if (mp->hw->max_rates == 1 && mp->sample_switch &&
568 - (mi->total_packets_cur >= SAMPLE_SWITCH_THR ||
569 - mp->sample_switch == 1))
570 - return -1;
571 -
572 - if (mi->sample_wait > 0) {
573 - mi->sample_wait--;
574 - return -1;
575 - }
576 -
577 - if (!mi->sample_tries)
578 - return -1;
579 -
580 - sample_group = mi->sample_group;
581 - mg = &mi->groups[sample_group];
582 - sample_idx = sample_table[mg->column][mg->index];
583 - minstrel_set_next_sample_idx(mi);
584 -
585 - if (!(mi->supported[sample_group] & BIT(sample_idx)))
586 - return -1;
587 -
588 - mrs = &mg->rates[sample_idx];
589 - sample_idx += MI_RATE(sample_group, 0);
590 -
591 - tp_rate1 = mi->max_tp_rate[0];
592 + u8 seq;
593
594 - /* Set tp_rate2 to the second highest max_tp_rate */
595 - if (minstrel_get_duration(mi->max_tp_rate[0]) >
596 - minstrel_get_duration(mi->max_tp_rate[1])) {
597 - tp_rate2 = mi->max_tp_rate[0];
598 + if (mp->hw->max_rates > 1) {
599 + seq = mi->sample_seq;
600 + mi->sample_seq = (seq + 1) % ARRAY_SIZE(minstrel_sample_seq);
601 + seq = minstrel_sample_seq[seq];
602 } else {
603 - tp_rate2 = mi->max_tp_rate[1];
604 + seq = MINSTREL_SAMPLE_TYPE_INC;
605 }
606
607 - /*
608 - * Sampling might add some overhead (RTS, no aggregation)
609 - * to the frame. Hence, don't use sampling for the highest currently
610 - * used highest throughput or probability rate.
611 - */
612 - if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate)
613 - return -1;
614 -
615 - /*
616 - * Do not sample if the probability is already higher than 95%,
617 - * or if the rate is 3 times slower than the current max probability
618 - * rate, to avoid wasting airtime.
619 - */
620 - sample_dur = minstrel_get_duration(sample_idx);
621 - if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
622 - minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
623 - return -1;
624 -
625 -
626 - /*
627 - * For devices with no configurable multi-rate retry, skip sampling
628 - * below the per-group max throughput rate, and only use one sampling
629 - * attempt per rate
630 - */
631 - if (mp->hw->max_rates == 1 &&
632 - (minstrel_get_duration(mg->max_group_tp_rate[0]) < sample_dur ||
633 - mrs->attempts))
634 - return -1;
635 -
636 - /* Skip already sampled slow rates */
637 - if (sample_dur >= minstrel_get_duration(tp_rate1) && mrs->attempts)
638 - return -1;
639 -
640 - /*
641 - * Make sure that lower rates get sampled only occasionally,
642 - * if the link is working perfectly.
643 - */
644 -
645 - cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams;
646 - if (sample_dur >= minstrel_get_duration(tp_rate2) &&
647 - (cur_max_tp_streams - 1 <
648 - minstrel_mcs_groups[sample_group].streams ||
649 - sample_dur >= minstrel_get_duration(mi->max_prob_rate)))
650 - return -1;
651 -
652 - mi->sample_tries--;
653 -
654 - return sample_idx;
655 + return __minstrel_ht_get_sample_rate(mi, seq);
656 }
657
658 static void
659 @@ -1488,7 +1574,7 @@ minstrel_ht_get_rate(void *priv, struct
660 struct ieee80211_tx_rate *rate = &info->status.rates[0];
661 struct minstrel_ht_sta *mi = priv_sta;
662 struct minstrel_priv *mp = priv;
663 - int sample_idx;
664 + u16 sample_idx;
665
666 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
667 !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate)))
668 @@ -1504,11 +1590,19 @@ minstrel_ht_get_rate(void *priv, struct
669 /* Don't use EAPOL frames for sampling on non-mrr hw */
670 if (mp->hw->max_rates == 1 &&
671 (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
672 - sample_idx = -1;
673 - else
674 - sample_idx = minstrel_get_sample_rate(mp, mi);
675 + return;
676
677 - if (sample_idx < 0)
678 + if (mp->hw->max_rates == 1 && mp->sample_switch &&
679 + (mi->total_packets_cur >= SAMPLE_SWITCH_THR ||
680 + mp->sample_switch == 1))
681 + return;
682 +
683 + if (time_is_before_jiffies(mi->sample_time))
684 + return;
685 +
686 + mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL;
687 + sample_idx = minstrel_ht_get_sample_rate(mp, mi);
688 + if (!sample_idx)
689 return;
690
691 sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)];
692 @@ -1629,16 +1723,6 @@ minstrel_ht_update_caps(void *priv, stru
693
694 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1);
695
696 - /* When using MRR, sample more on the first attempt, without delay */
697 - if (mp->has_mrr) {
698 - mi->sample_count = 16;
699 - mi->sample_wait = 0;
700 - } else {
701 - mi->sample_count = 8;
702 - mi->sample_wait = 8;
703 - }
704 - mi->sample_tries = 4;
705 -
706 if (!use_vht) {
707 stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
708 IEEE80211_HT_CAP_RX_STBC_SHIFT;
709 --- a/net/mac80211/rc80211_minstrel_ht.h
710 +++ b/net/mac80211/rc80211_minstrel_ht.h
711 @@ -69,6 +69,8 @@
712 #define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate)
713 #define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate)
714
715 +#define MINSTREL_SAMPLE_RATES 5 /* rates per sample type */
716 +#define MINSTREL_SAMPLE_INTERVAL (HZ / 50)
717
718 struct minstrel_priv {
719 struct ieee80211_hw *hw;
720 @@ -126,6 +128,13 @@ struct minstrel_rate_stats {
721 bool retry_updated;
722 };
723
724 +enum minstrel_sample_type {
725 + MINSTREL_SAMPLE_TYPE_INC,
726 + MINSTREL_SAMPLE_TYPE_JUMP,
727 + MINSTREL_SAMPLE_TYPE_SLOW,
728 + __MINSTREL_SAMPLE_TYPE_MAX
729 +};
730 +
731 struct minstrel_mcs_group_data {
732 u8 index;
733 u8 column;
734 @@ -144,6 +153,12 @@ enum minstrel_sample_mode {
735 MINSTREL_SAMPLE_PENDING,
736 };
737
738 +struct minstrel_sample_category {
739 + u8 sample_group;
740 + u16 sample_rates[MINSTREL_SAMPLE_RATES];
741 + u16 cur_sample_rates[MINSTREL_SAMPLE_RATES];
742 +};
743 +
744 struct minstrel_ht_sta {
745 struct ieee80211_sta *sta;
746
747 @@ -175,16 +190,14 @@ struct minstrel_ht_sta {
748 /* tx flags to add for frames for this sta */
749 u32 tx_flags;
750
751 - u8 sample_wait;
752 - u8 sample_tries;
753 - u8 sample_count;
754 + unsigned long sample_time;
755 + struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX];
756 +
757 + u8 sample_seq;
758
759 enum minstrel_sample_mode sample_mode;
760 u16 sample_rate;
761
762 - /* current MCS group to be sampled */
763 - u8 sample_group;
764 -
765 u8 band;
766
767 /* Bitfield of supported MCS rates of all groups */