1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -70,6 +70,8 @@ struct minstrel_mcs_group_data {
};
struct minstrel_ht_sta {
+ struct ieee80211_tx_rate tx_rates[3];
+
/* ampdu length (average, per sampling interval) */
unsigned int ampdu_len;
unsigned int ampdu_packets;
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -87,6 +87,10 @@ const struct mcs_group minstrel_mcs_grou
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
+static void
+minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ struct ieee80211_tx_rate *rate, int index,
+ bool sample, bool rtscts);
/*
* Perform EWMA (Exponentially Weighted Moving Average) calculation
*/
@@ -174,6 +178,17 @@ minstrel_ht_calc_tp(struct minstrel_priv
mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
}
+static void
+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+{
+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[0], mi->max_tp_rate,
+ false, false);
+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[1], mi->max_tp_rate2,
+ false, true);
+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[2], mi->max_prob_rate,
+ false, true);
+}
+
/*
* Update rate statistics and select new primary rates
*
@@ -294,6 +309,7 @@ minstrel_ht_update_stats(struct minstrel
}
}
+ minstrel_ht_update_rates(mp, mi);
mi->stats_update = jiffies;
}
@@ -332,8 +348,8 @@ minstrel_next_sample_idx(struct minstrel
}
static void
-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
- bool primary)
+minstrel_downgrade_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ unsigned int *idx, bool primary)
{
int group, orig_group;
@@ -352,6 +368,7 @@ minstrel_downgrade_rate(struct minstrel_
*idx = mi->groups[group].max_tp_rate;
else
*idx = mi->groups[group].max_tp_rate2;
+ minstrel_ht_update_rates(mp, mi);
break;
}
}
@@ -452,13 +469,13 @@ minstrel_ht_tx_status(void *priv, struct
if (rate->attempts > 30 &&
MINSTREL_FRAC(rate->success, rate->attempts) <
MINSTREL_FRAC(20, 100))
- minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
+ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate, true);
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
if (rate2->attempts > 30 &&
MINSTREL_FRAC(rate2->success, rate2->attempts) <
MINSTREL_FRAC(20, 100))
- minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
+ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate2, false);
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
minstrel_ht_update_stats(mp, mi);
@@ -523,7 +540,6 @@ minstrel_calc_retransmit(struct minstrel
static void
minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
struct ieee80211_tx_rate *rate, int index,
- struct ieee80211_tx_rate_control *txrc,
bool sample, bool rtscts)
{
const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
@@ -611,6 +627,7 @@ minstrel_ht_get_rate(void *priv, struct
struct minstrel_priv *mp = priv;
int sample_idx;
bool sample = false;
+ int last = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
return;
@@ -636,11 +653,10 @@ minstrel_ht_get_rate(void *priv, struct
if (sample_idx >= 0) {
sample = true;
minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
- txrc, true, false);
+ true, false);
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
} else {
- minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
- txrc, false, false);
+ ar[0] = mi->tx_rates[0];
}
if (mp->hw->max_rates >= 3) {
@@ -650,33 +666,27 @@ minstrel_ht_get_rate(void *priv, struct
* max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
*/
if (sample_idx >= 0)
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
- txrc, false, false);
+ ar[1] = mi->tx_rates[0];
else
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
- txrc, false, true);
-
- minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
- txrc, false, !sample);
+ ar[1] = mi->tx_rates[1];
- ar[3].count = 0;
- ar[3].idx = -1;
+ ar[2] = mi->tx_rates[2];
+ last = 3;
} else if (mp->hw->max_rates == 2) {
/*
* Only 2 tx rates supported, use
* sample_rate -> max_prob_rate for sampling and
* max_tp_rate -> max_prob_rate by default.
*/
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
- txrc, false, !sample);
-
- ar[2].count = 0;
- ar[2].idx = -1;
+ ar[1] = mi->tx_rates[2];
+ last = 2;
} else {
/* Not using MRR, only use the first rate */
- ar[1].count = 0;
- ar[1].idx = -1;
+ last = 1;
+
}
+ ar[last].count = 0;
+ ar[last].idx = -1;
mi->total_packets++;
@@ -768,6 +778,7 @@ minstrel_ht_update_caps(void *priv, stru
if (!n_supported)
goto use_legacy;
+ minstrel_ht_update_rates(mp, mi);
return;
use_legacy:
|