55ff817009294fde4c61548f95a49ca506d15b4d
[openwrt.git] / package / kernel / mac80211 / patches / 343-mac80211-minstrel_ht-improve-sample-rate-skip-logic.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Thu, 3 Mar 2016 23:20:06 +0100
3 Subject: [PATCH] mac80211: minstrel_ht: improve sample rate skip logic
4
5 There were a few issues that were slowing down the process of finding
6 the optimal rate, especially on devices with multi-rate retry
7 limitations:
8
9 When max_tp_rate[0] was slower than max_tp_rate[1], the code did not
10 sample max_tp_rate[1], which would often allow it to switch places with
11 max_tp_rate[0] (e.g. if only the first sampling attempts were bad, but the
12 rate is otherwise good).
13
14 Also, sample attempts of rates between max_tp_rate[0] and [1] were being
15 ignored in this case, because the code only checked if the rate was
16 slower than [1].
17
18 Fix this by checking against the fastest / second fastest max_tp_rate
19 instead of assuming a specific order between the two.
20
21 In my tests this patch significantly reduces the time until minstrel_ht
22 finds the optimal rate right after assoc
23
24 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
25 ---
26
27 --- a/net/mac80211/rc80211_minstrel_ht.c
28 +++ b/net/mac80211/rc80211_minstrel_ht.c
29 @@ -958,6 +958,7 @@ minstrel_get_sample_rate(struct minstrel
30         struct minstrel_rate_stats *mrs;
31         struct minstrel_mcs_group_data *mg;
32         unsigned int sample_dur, sample_group, cur_max_tp_streams;
33 +       int tp_rate1, tp_rate2;
34         int sample_idx = 0;
35  
36         if (mi->sample_wait > 0) {
37 @@ -979,14 +980,22 @@ minstrel_get_sample_rate(struct minstrel
38         mrs = &mg->rates[sample_idx];
39         sample_idx += sample_group * MCS_GROUP_RATES;
40  
41 +       /* Set tp_rate1, tp_rate2 to the highest / second highest max_tp_rate */
42 +       if (minstrel_get_duration(mi->max_tp_rate[0]) >
43 +           minstrel_get_duration(mi->max_tp_rate[1])) {
44 +               tp_rate1 = mi->max_tp_rate[1];
45 +               tp_rate2 = mi->max_tp_rate[0];
46 +       } else {
47 +               tp_rate1 = mi->max_tp_rate[0];
48 +               tp_rate2 = mi->max_tp_rate[1];
49 +       }
50 +
51         /*
52          * Sampling might add some overhead (RTS, no aggregation)
53 -        * to the frame. Hence, don't use sampling for the currently
54 -        * used rates.
55 +        * to the frame. Hence, don't use sampling for the highest currently
56 +        * used highest throughput or probability rate.
57          */
58 -       if (sample_idx == mi->max_tp_rate[0] ||
59 -           sample_idx == mi->max_tp_rate[1] ||
60 -           sample_idx == mi->max_prob_rate)
61 +       if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate)
62                 return -1;
63  
64         /*
65 @@ -1001,10 +1010,10 @@ minstrel_get_sample_rate(struct minstrel
66          * if the link is working perfectly.
67          */
68  
69 -       cur_max_tp_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
70 +       cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
71                 MCS_GROUP_RATES].streams;
72         sample_dur = minstrel_get_duration(sample_idx);
73 -       if (sample_dur >= minstrel_get_duration(mi->max_tp_rate[1]) &&
74 +       if (sample_dur >= minstrel_get_duration(tp_rate2) &&
75             (cur_max_tp_streams - 1 <
76              minstrel_mcs_groups[sample_group].streams ||
77              sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {