Blame view

net/mac80211/rc80211_minstrel.c 16.8 KB
cccf129f8   Felix Fietkau   mac80211: add the...
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
  /*
   * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * Based on minstrel.c:
   *   Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz>
   *   Sponsored by Indranet Technologies Ltd
   *
   * Based on sample.c:
   *   Copyright (c) 2005 John Bicket
   *   All rights reserved.
   *
   *   Redistribution and use in source and binary forms, with or without
   *   modification, are permitted provided that the following conditions
   *   are met:
   *   1. Redistributions of source code must retain the above copyright
   *      notice, this list of conditions and the following disclaimer,
   *      without modification.
   *   2. Redistributions in binary form must reproduce at minimum a disclaimer
   *      similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   *      redistribution must be conditioned upon including a substantially
   *      similar Disclaimer requirement for further binary redistribution.
   *   3. Neither the names of the above-listed copyright holders nor the names
   *      of any contributors may be used to endorse or promote products derived
   *      from this software without specific prior written permission.
   *
   *   Alternatively, this software may be distributed under the terms of the
   *   GNU General Public License ("GPL") version 2 as published by the Free
   *   Software Foundation.
   *
   *   NO WARRANTY
   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   *   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   *   LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   *   THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   *   OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   *   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   *   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   *   THE POSSIBILITY OF SUCH DAMAGES.
   */
  #include <linux/netdevice.h>
  #include <linux/types.h>
  #include <linux/skbuff.h>
  #include <linux/debugfs.h>
  #include <linux/random.h>
  #include <linux/ieee80211.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
53
  #include <linux/slab.h>
cccf129f8   Felix Fietkau   mac80211: add the...
54
55
56
  #include <net/mac80211.h>
  #include "rate.h"
  #include "rc80211_minstrel.h"
cccf129f8   Felix Fietkau   mac80211: add the...
57
58
59
60
61
62
63
64
65
66
67
  #define SAMPLE_TBL(_mi, _idx, _col) \
  		_mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col]
  
  /* convert mac80211 rate index to local array index */
  static inline int
  rix_to_ndx(struct minstrel_sta_info *mi, int rix)
  {
  	int i = rix;
  	for (i = rix; i >= 0; i--)
  		if (mi->r[i].rix == rix)
  			break;
cccf129f8   Felix Fietkau   mac80211: add the...
68
69
  	return i;
  }
6a27b2c40   Thomas Huehn   mac80211: restruc...
70
  /* return current EMWA throughput */
5f63afe02   Felix Fietkau   mac80211: minstre...
71
  int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg)
6a27b2c40   Thomas Huehn   mac80211: restruc...
72
73
74
75
76
77
78
79
  {
  	int usecs;
  
  	usecs = mr->perfect_tx_time;
  	if (!usecs)
  		usecs = 1000000;
  
  	/* reset thr. below 10% success */
5f63afe02   Felix Fietkau   mac80211: minstre...
80
  	if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100))
6a27b2c40   Thomas Huehn   mac80211: restruc...
81
  		return 0;
50e55a8ea   Thomas Huehn   mac80211: add max...
82

5f63afe02   Felix Fietkau   mac80211: minstre...
83
  	if (prob_avg > MINSTREL_FRAC(90, 100))
50e55a8ea   Thomas Huehn   mac80211: add max...
84
  		return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs));
6a27b2c40   Thomas Huehn   mac80211: restruc...
85
  	else
5f63afe02   Felix Fietkau   mac80211: minstre...
86
  		return MINSTREL_TRUNC(100000 * (prob_avg / usecs));
6a27b2c40   Thomas Huehn   mac80211: restruc...
87
  }
2ff2b690c   Thomas Huehn   mac80211: improve...
88
89
90
91
  /* find & sort topmost throughput rates */
  static inline void
  minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
  {
f5eeb5fa1   Adrien Schildknecht   mac80211: fix inv...
92
93
  	int j;
  	struct minstrel_rate_stats *tmp_mrs;
50e55a8ea   Thomas Huehn   mac80211: add max...
94
  	struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats;
2ff2b690c   Thomas Huehn   mac80211: improve...
95

f5eeb5fa1   Adrien Schildknecht   mac80211: fix inv...
96
  	for (j = MAX_THR_RATES; j > 0; --j) {
50e55a8ea   Thomas Huehn   mac80211: add max...
97
  		tmp_mrs = &mi->r[tp_list[j - 1]].stats;
5f63afe02   Felix Fietkau   mac80211: minstre...
98
99
  		if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <=
  		    minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg))
f5eeb5fa1   Adrien Schildknecht   mac80211: fix inv...
100
  			break;
50e55a8ea   Thomas Huehn   mac80211: add max...
101
  	}
6a27b2c40   Thomas Huehn   mac80211: restruc...
102

2ff2b690c   Thomas Huehn   mac80211: improve...
103
104
105
106
107
  	if (j < MAX_THR_RATES - 1)
  		memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
  	if (j < MAX_THR_RATES)
  		tp_list[j] = i;
  }
cccf129f8   Felix Fietkau   mac80211: add the...
108
  static void
06d961a8e   Felix Fietkau   mac80211/minstrel...
109
110
111
112
113
114
115
116
  minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *ratetbl,
  		  int offset, int idx)
  {
  	struct minstrel_rate *r = &mi->r[idx];
  
  	ratetbl->rate[offset].idx = r->rix;
  	ratetbl->rate[offset].count = r->adjusted_retry_count;
  	ratetbl->rate[offset].count_cts = r->retry_count_cts;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
117
  	ratetbl->rate[offset].count_rts = r->stats.retry_count_rtscts;
06d961a8e   Felix Fietkau   mac80211/minstrel...
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
  }
  
  static void
  minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
  {
  	struct ieee80211_sta_rates *ratetbl;
  	int i = 0;
  
  	ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC);
  	if (!ratetbl)
  		return;
  
  	/* Start with max_tp_rate */
  	minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]);
  
  	if (mp->hw->max_rates >= 3) {
  		/* At least 3 tx rates supported, use max_tp_rate2 next */
  		minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[1]);
  	}
  
  	if (mp->hw->max_rates >= 2) {
  		/* At least 2 tx rates supported, use max_prob_rate next */
  		minstrel_set_rate(mi, ratetbl, i++, mi->max_prob_rate);
  	}
  
  	/* Use lowest rate last */
  	ratetbl->rate[i].idx = mi->lowest_rix;
  	ratetbl->rate[i].count = mp->max_retry;
  	ratetbl->rate[i].count_cts = mp->max_retry;
  	ratetbl->rate[i].count_rts = mp->max_retry;
  
  	rate_control_set_rates(mp->hw, mi->sta, ratetbl);
  }
f62838bcc   Thomas Huehn   mac80211: unify M...
151
  /*
5f919abc7   Thomas Huehn   mac80211: add sta...
152
  * Recalculate statistics and counters of a given rate
f62838bcc   Thomas Huehn   mac80211: unify M...
153
154
  */
  void
b1103d256   Felix Fietkau   mac80211: minstre...
155
156
  minstrel_calc_rate_stats(struct minstrel_priv *mp,
  			 struct minstrel_rate_stats *mrs)
f62838bcc   Thomas Huehn   mac80211: unify M...
157
  {
1109dc392   Felix Fietkau   mac80211: minstre...
158
  	unsigned int cur_prob;
f62838bcc   Thomas Huehn   mac80211: unify M...
159
160
  	if (unlikely(mrs->attempts > 0)) {
  		mrs->sample_skipped = 0;
1109dc392   Felix Fietkau   mac80211: minstre...
161
  		cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
b1103d256   Felix Fietkau   mac80211: minstre...
162
  		if (mp->new_avg) {
5f63afe02   Felix Fietkau   mac80211: minstre...
163
164
  			minstrel_filter_avg_add(&mrs->prob_avg,
  						&mrs->prob_avg_1, cur_prob);
b1103d256   Felix Fietkau   mac80211: minstre...
165
  		} else if (unlikely(!mrs->att_hist)) {
5f63afe02   Felix Fietkau   mac80211: minstre...
166
  			mrs->prob_avg = cur_prob;
5f919abc7   Thomas Huehn   mac80211: add sta...
167
  		} else {
5f919abc7   Thomas Huehn   mac80211: add sta...
168
  			/*update exponential weighted moving avarage */
5f63afe02   Felix Fietkau   mac80211: minstre...
169
170
171
  			mrs->prob_avg = minstrel_ewma(mrs->prob_avg,
  						      cur_prob,
  						      EWMA_LEVEL);
5f919abc7   Thomas Huehn   mac80211: add sta...
172
  		}
f62838bcc   Thomas Huehn   mac80211: unify M...
173
174
175
176
177
178
179
180
181
182
183
  		mrs->att_hist += mrs->attempts;
  		mrs->succ_hist += mrs->success;
  	} else {
  		mrs->sample_skipped++;
  	}
  
  	mrs->last_success = mrs->success;
  	mrs->last_attempts = mrs->attempts;
  	mrs->success = 0;
  	mrs->attempts = 0;
  }
06d961a8e   Felix Fietkau   mac80211/minstrel...
184
  static void
cccf129f8   Felix Fietkau   mac80211: add the...
185
186
  minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
  {
2ff2b690c   Thomas Huehn   mac80211: improve...
187
188
  	u8 tmp_tp_rate[MAX_THR_RATES];
  	u8 tmp_prob_rate = 0;
6a27b2c40   Thomas Huehn   mac80211: restruc...
189
  	int i, tmp_cur_tp, tmp_prob_tp;
cccf129f8   Felix Fietkau   mac80211: add the...
190

f359d3fe8   Weilong Chen   mac80211: fix che...
191
  	for (i = 0; i < MAX_THR_RATES; i++)
2ff2b690c   Thomas Huehn   mac80211: improve...
192
  	    tmp_tp_rate[i] = 0;
cccf129f8   Felix Fietkau   mac80211: add the...
193
194
  	for (i = 0; i < mi->n_rates; i++) {
  		struct minstrel_rate *mr = &mi->r[i];
ca12c0c83   Thomas Huehn   mac80211: Unify r...
195
  		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
50e55a8ea   Thomas Huehn   mac80211: add max...
196
  		struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats;
cccf129f8   Felix Fietkau   mac80211: add the...
197

5f919abc7   Thomas Huehn   mac80211: add sta...
198
  		/* Update statistics of success probability per rate */
b1103d256   Felix Fietkau   mac80211: minstre...
199
  		minstrel_calc_rate_stats(mp, mrs);
cccf129f8   Felix Fietkau   mac80211: add the...
200
201
202
  
  		/* Sample less often below the 10% chance of success.
  		 * Sample less often above the 95% chance of success. */
5f63afe02   Felix Fietkau   mac80211: minstre...
203
204
  		if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
  		    mrs->prob_avg < MINSTREL_FRAC(10, 100)) {
ca12c0c83   Thomas Huehn   mac80211: Unify r...
205
  			mr->adjusted_retry_count = mrs->retry_count >> 1;
cccf129f8   Felix Fietkau   mac80211: add the...
206
207
  			if (mr->adjusted_retry_count > 2)
  				mr->adjusted_retry_count = 2;
f4a8cd94f   Felix Fietkau   minstrel: improve...
208
  			mr->sample_limit = 4;
cccf129f8   Felix Fietkau   mac80211: add the...
209
  		} else {
f4a8cd94f   Felix Fietkau   minstrel: improve...
210
  			mr->sample_limit = -1;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
211
  			mr->adjusted_retry_count = mrs->retry_count;
cccf129f8   Felix Fietkau   mac80211: add the...
212
213
214
  		}
  		if (!mr->adjusted_retry_count)
  			mr->adjusted_retry_count = 2;
cccf129f8   Felix Fietkau   mac80211: add the...
215

2ff2b690c   Thomas Huehn   mac80211: improve...
216
217
218
219
220
221
222
  		minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate);
  
  		/* To determine the most robust rate (max_prob_rate) used at
  		 * 3rd mmr stage we distinct between two cases:
  		 * (1) if any success probabilitiy >= 95%, out of those rates
  		 * choose the maximum throughput rate as max_prob_rate
  		 * (2) if all success probabilities < 95%, the rate with
d070f9137   Stephen Hemminger   mac80211: fix spe...
223
  		 * highest success probability is chosen as max_prob_rate */
5f63afe02   Felix Fietkau   mac80211: minstre...
224
225
  		if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) {
  			tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg);
50e55a8ea   Thomas Huehn   mac80211: add max...
226
  			tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate],
5f63afe02   Felix Fietkau   mac80211: minstre...
227
  							  tmp_mrs->prob_avg);
6a27b2c40   Thomas Huehn   mac80211: restruc...
228
  			if (tmp_cur_tp >= tmp_prob_tp)
2ff2b690c   Thomas Huehn   mac80211: improve...
229
230
  				tmp_prob_rate = i;
  		} else {
5f63afe02   Felix Fietkau   mac80211: minstre...
231
  			if (mrs->prob_avg >= tmp_mrs->prob_avg)
2ff2b690c   Thomas Huehn   mac80211: improve...
232
  				tmp_prob_rate = i;
cccf129f8   Felix Fietkau   mac80211: add the...
233
234
  		}
  	}
2ff2b690c   Thomas Huehn   mac80211: improve...
235
236
237
  	/* Assign the new rate set */
  	memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate));
  	mi->max_prob_rate = tmp_prob_rate;
8f1576119   Thomas Huehn   mac80211: add doc...
238

45966aeba   Lorenzo Bianconi   mac80211: add fix...
239
240
241
242
243
244
245
246
  #ifdef CONFIG_MAC80211_DEBUGFS
  	/* use fixed index if set */
  	if (mp->fixed_rate_idx != -1) {
  		mi->max_tp_rate[0] = mp->fixed_rate_idx;
  		mi->max_tp_rate[1] = mp->fixed_rate_idx;
  		mi->max_prob_rate = mp->fixed_rate_idx;
  	}
  #endif
8f1576119   Thomas Huehn   mac80211: add doc...
247
  	/* Reset update timer */
9134073bc   Thomas Huehn   mac80211: improve...
248
  	mi->last_stats_update = jiffies;
06d961a8e   Felix Fietkau   mac80211/minstrel...
249
250
  
  	minstrel_update_rates(mp, mi);
cccf129f8   Felix Fietkau   mac80211: add the...
251
252
253
254
  }
  
  static void
  minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
18fb84d98   Felix Fietkau   mac80211: make ra...
255
  		   void *priv_sta, struct ieee80211_tx_status *st)
cccf129f8   Felix Fietkau   mac80211: add the...
256
  {
18fb84d98   Felix Fietkau   mac80211: make ra...
257
  	struct ieee80211_tx_info *info = st->info;
8acbcddb5   Johannes Berg   minstrel: update ...
258
  	struct minstrel_priv *mp = priv;
cccf129f8   Felix Fietkau   mac80211: add the...
259
  	struct minstrel_sta_info *mi = priv_sta;
e6a9854b0   Johannes Berg   mac80211/drivers:...
260
261
262
  	struct ieee80211_tx_rate *ar = info->status.rates;
  	int i, ndx;
  	int success;
cccf129f8   Felix Fietkau   mac80211: add the...
263

e6a9854b0   Johannes Berg   mac80211/drivers:...
264
  	success = !!(info->flags & IEEE80211_TX_STAT_ACK);
cccf129f8   Felix Fietkau   mac80211: add the...
265

e6a9854b0   Johannes Berg   mac80211/drivers:...
266
  	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
b2911a843   Felix Fietkau   mac80211: minstre...
267
  		if (ar[i].idx < 0 || !ar[i].count)
cccf129f8   Felix Fietkau   mac80211: add the...
268
  			break;
e6a9854b0   Johannes Berg   mac80211/drivers:...
269
  		ndx = rix_to_ndx(mi, ar[i].idx);
3938b45c1   Luciano Coelho   mac80211: minstre...
270
271
  		if (ndx < 0)
  			continue;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
272
  		mi->r[ndx].stats.attempts += ar[i].count;
cccf129f8   Felix Fietkau   mac80211: add the...
273

bfc32e6a9   Javier Cardona   mac80211: Decoupl...
274
  		if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
ca12c0c83   Thomas Huehn   mac80211: Unify r...
275
  			mi->r[ndx].stats.success += success;
cccf129f8   Felix Fietkau   mac80211: add the...
276
  	}
b1103d256   Felix Fietkau   mac80211: minstre...
277
278
  	if (time_after(jiffies, mi->last_stats_update +
  				mp->update_interval / (mp->new_avg ? 2 : 1)))
8acbcddb5   Johannes Berg   minstrel: update ...
279
  		minstrel_update_stats(mp, mi);
cccf129f8   Felix Fietkau   mac80211: add the...
280
281
282
283
284
  }
  
  
  static inline unsigned int
  minstrel_get_retry_count(struct minstrel_rate *mr,
f359d3fe8   Weilong Chen   mac80211: fix che...
285
  			 struct ieee80211_tx_info *info)
cccf129f8   Felix Fietkau   mac80211: add the...
286
  {
8d819a92c   Felix Fietkau   mac80211: minstre...
287
  	u8 retry = mr->adjusted_retry_count;
cccf129f8   Felix Fietkau   mac80211: add the...
288

991fec091   Felix Fietkau   mac80211: fix CTS...
289
  	if (info->control.use_rts)
8d819a92c   Felix Fietkau   mac80211: minstre...
290
  		retry = max_t(u8, 2, min(mr->stats.retry_count_rtscts, retry));
991fec091   Felix Fietkau   mac80211: fix CTS...
291
  	else if (info->control.use_cts_prot)
8d819a92c   Felix Fietkau   mac80211: minstre...
292
  		retry = max_t(u8, 2, min(mr->retry_count_cts, retry));
cccf129f8   Felix Fietkau   mac80211: add the...
293
294
295
296
297
298
299
300
  	return retry;
  }
  
  
  static int
  minstrel_get_next_sample(struct minstrel_sta_info *mi)
  {
  	unsigned int sample_ndx;
8f1576119   Thomas Huehn   mac80211: add doc...
301
302
  	sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column);
  	mi->sample_row++;
f744bf81f   Thomas Huehn   mac80211: add low...
303
  	if ((int) mi->sample_row >= mi->n_rates) {
8f1576119   Thomas Huehn   mac80211: add doc...
304
  		mi->sample_row = 0;
cccf129f8   Felix Fietkau   mac80211: add the...
305
306
307
308
309
310
  		mi->sample_column++;
  		if (mi->sample_column >= SAMPLE_COLUMNS)
  			mi->sample_column = 0;
  	}
  	return sample_ndx;
  }
2df78167a   Johannes Berg   wireless: fix a f...
311
  static void
e6a9854b0   Johannes Berg   mac80211/drivers:...
312
313
  minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
  		  void *priv_sta, struct ieee80211_tx_rate_control *txrc)
cccf129f8   Felix Fietkau   mac80211: add the...
314
  {
e6a9854b0   Johannes Berg   mac80211/drivers:...
315
  	struct sk_buff *skb = txrc->skb;
cccf129f8   Felix Fietkau   mac80211: add the...
316
317
318
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  	struct minstrel_sta_info *mi = priv_sta;
  	struct minstrel_priv *mp = priv;
06d961a8e   Felix Fietkau   mac80211/minstrel...
319
320
321
  	struct ieee80211_tx_rate *rate = &info->control.rates[0];
  	struct minstrel_rate *msr, *mr;
  	unsigned int ndx;
8f1576119   Thomas Huehn   mac80211: add doc...
322
  	bool mrr_capable;
5c9fc93bc   Felix Fietkau   mac80211/minstrel...
323
  	bool prev_sample;
06d961a8e   Felix Fietkau   mac80211/minstrel...
324
  	int delta;
8f1576119   Thomas Huehn   mac80211: add doc...
325
  	int sampling_ratio;
cccf129f8   Felix Fietkau   mac80211: add the...
326

8f1576119   Thomas Huehn   mac80211: add doc...
327
328
329
330
331
332
333
334
  	/* check multi-rate-retry capabilities & adjust lookaround_rate */
  	mrr_capable = mp->has_mrr &&
  		      !txrc->rts &&
  		      !txrc->bss_conf->use_cts_prot;
  	if (mrr_capable)
  		sampling_ratio = mp->lookaround_rate_mrr;
  	else
  		sampling_ratio = mp->lookaround_rate;
cccf129f8   Felix Fietkau   mac80211: add the...
335

8f1576119   Thomas Huehn   mac80211: add doc...
336
  	/* increase sum packet counter */
ca12c0c83   Thomas Huehn   mac80211: Unify r...
337
  	mi->total_packets++;
8f1576119   Thomas Huehn   mac80211: add doc...
338

45966aeba   Lorenzo Bianconi   mac80211: add fix...
339
340
341
342
  #ifdef CONFIG_MAC80211_DEBUGFS
  	if (mp->fixed_rate_idx != -1)
  		return;
  #endif
38252e9ef   Thomas Huehn   mac80211: minstre...
343
344
345
346
  	/* Don't use EAPOL frames for sampling on non-mrr hw */
  	if (mp->hw->max_rates == 1 &&
  	    (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
  		return;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
347
  	delta = (mi->total_packets * sampling_ratio / 100) -
4fe40b8e1   Felix Fietkau   mac80211: minstre...
348
  			mi->sample_packets;
cccf129f8   Felix Fietkau   mac80211: add the...
349

06d961a8e   Felix Fietkau   mac80211/minstrel...
350
  	/* delta < 0: no sampling required */
5c9fc93bc   Felix Fietkau   mac80211/minstrel...
351
  	prev_sample = mi->prev_sample;
06d961a8e   Felix Fietkau   mac80211/minstrel...
352
353
354
  	mi->prev_sample = false;
  	if (delta < 0 || (!mrr_capable && prev_sample))
  		return;
cccf129f8   Felix Fietkau   mac80211: add the...
355

ca12c0c83   Thomas Huehn   mac80211: Unify r...
356
  	if (mi->total_packets >= 10000) {
ca12c0c83   Thomas Huehn   mac80211: Unify r...
357
358
  		mi->sample_packets = 0;
  		mi->total_packets = 0;
06d961a8e   Felix Fietkau   mac80211/minstrel...
359
360
361
362
363
364
365
366
367
368
  	} else if (delta > mi->n_rates * 2) {
  		/* With multi-rate retry, not every planned sample
  		 * attempt actually gets used, due to the way the retry
  		 * chain is set up - [max_tp,sample,prob,lowest] for
  		 * sample_rate < max_tp.
  		 *
  		 * If there's too much sampling backlog and the link
  		 * starts getting worse, minstrel would start bursting
  		 * out lots of sampling frames, which would result
  		 * in a large throughput loss. */
ca12c0c83   Thomas Huehn   mac80211: Unify r...
369
  		mi->sample_packets += (delta - mi->n_rates * 2);
06d961a8e   Felix Fietkau   mac80211/minstrel...
370
371
372
373
374
375
376
377
378
379
380
  	}
  
  	/* get next random rate sample */
  	ndx = minstrel_get_next_sample(mi);
  	msr = &mi->r[ndx];
  	mr = &mi->r[mi->max_tp_rate[0]];
  
  	/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
  	 * rate sampling method should be used.
  	 * Respect such rates that are not sampled for 20 interations.
  	 */
4fe40b8e1   Felix Fietkau   mac80211: minstre...
381
382
  	if (msr->perfect_tx_time < mr->perfect_tx_time ||
  	    msr->stats.sample_skipped >= 20) {
17dce1580   Jiri Slaby   mac80211/minstrel...
383
  		if (!msr->sample_limit)
06d961a8e   Felix Fietkau   mac80211/minstrel...
384
  			return;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
385
  		mi->sample_packets++;
06d961a8e   Felix Fietkau   mac80211/minstrel...
386
387
  		if (msr->sample_limit > 0)
  			msr->sample_limit--;
cccf129f8   Felix Fietkau   mac80211: add the...
388
  	}
f4a8cd94f   Felix Fietkau   minstrel: improve...
389
390
391
392
  
  	/* If we're not using MRR and the sampling rate already
  	 * has a probability of >95%, we shouldn't be attempting
  	 * to use it, as this only wastes precious airtime */
06d961a8e   Felix Fietkau   mac80211/minstrel...
393
  	if (!mrr_capable &&
5f63afe02   Felix Fietkau   mac80211: minstre...
394
  	   (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100)))
cccf129f8   Felix Fietkau   mac80211: add the...
395
  		return;
cccf129f8   Felix Fietkau   mac80211: add the...
396

06d961a8e   Felix Fietkau   mac80211/minstrel...
397
  	mi->prev_sample = true;
8f1576119   Thomas Huehn   mac80211: add doc...
398

06d961a8e   Felix Fietkau   mac80211/minstrel...
399
400
  	rate->idx = mi->r[ndx].rix;
  	rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
4fe40b8e1   Felix Fietkau   mac80211: minstre...
401
  	info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
cccf129f8   Felix Fietkau   mac80211: add the...
402
403
404
405
  }
  
  
  static void
57fbcce37   Johannes Berg   cfg80211: remove ...
406
  calc_rate_durations(enum nl80211_band band,
4ee73f338   Michal Kazior   mac80211: remove ...
407
  		    struct minstrel_rate *d,
438b61b77   Simon Wunderlich   mac80211: fix tim...
408
409
  		    struct ieee80211_rate *rate,
  		    struct cfg80211_chan_def *chandef)
cccf129f8   Felix Fietkau   mac80211: add the...
410
411
  {
  	int erp = !!(rate->flags & IEEE80211_RATE_ERP_G);
438b61b77   Simon Wunderlich   mac80211: fix tim...
412
  	int shift = ieee80211_chandef_get_shift(chandef);
cccf129f8   Felix Fietkau   mac80211: add the...
413

4ee73f338   Michal Kazior   mac80211: remove ...
414
  	d->perfect_tx_time = ieee80211_frame_duration(band, 1200,
438b61b77   Simon Wunderlich   mac80211: fix tim...
415
416
  			DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1,
  			shift);
4ee73f338   Michal Kazior   mac80211: remove ...
417
  	d->ack_time = ieee80211_frame_duration(band, 10,
438b61b77   Simon Wunderlich   mac80211: fix tim...
418
419
  			DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1,
  			shift);
cccf129f8   Felix Fietkau   mac80211: add the...
420
421
422
423
424
425
  }
  
  static void
  init_sample_table(struct minstrel_sta_info *mi)
  {
  	unsigned int i, col, new_idx;
cccf129f8   Felix Fietkau   mac80211: add the...
426
427
428
  	u8 rnd[8];
  
  	mi->sample_column = 0;
8f1576119   Thomas Huehn   mac80211: add doc...
429
  	mi->sample_row = 0;
f744bf81f   Thomas Huehn   mac80211: add low...
430
  	memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates);
cccf129f8   Felix Fietkau   mac80211: add the...
431
432
  
  	for (col = 0; col < SAMPLE_COLUMNS; col++) {
f7d8ad81c   Karl Beldan   mac80211: minstre...
433
  		prandom_bytes(rnd, sizeof(rnd));
f744bf81f   Thomas Huehn   mac80211: add low...
434
  		for (i = 0; i < mi->n_rates; i++) {
f744bf81f   Thomas Huehn   mac80211: add low...
435
  			new_idx = (i + rnd[i & 7]) % mi->n_rates;
f744bf81f   Thomas Huehn   mac80211: add low...
436
437
  			while (SAMPLE_TBL(mi, new_idx, col) != 0xff)
  				new_idx = (new_idx + 1) % mi->n_rates;
cccf129f8   Felix Fietkau   mac80211: add the...
438

f744bf81f   Thomas Huehn   mac80211: add low...
439
  			SAMPLE_TBL(mi, new_idx, col) = i;
cccf129f8   Felix Fietkau   mac80211: add the...
440
441
442
443
444
445
  		}
  	}
  }
  
  static void
  minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
3de805cf9   Simon Wunderlich   mac80211/rc80211:...
446
447
  		   struct cfg80211_chan_def *chandef,
  		   struct ieee80211_sta *sta, void *priv_sta)
cccf129f8   Felix Fietkau   mac80211: add the...
448
449
450
  {
  	struct minstrel_sta_info *mi = priv_sta;
  	struct minstrel_priv *mp = priv;
d57854bb1   Christian Lamparter   minstrel: fix war...
451
  	struct ieee80211_rate *ctl_rate;
cccf129f8   Felix Fietkau   mac80211: add the...
452
453
  	unsigned int i, n = 0;
  	unsigned int t_slot = 9; /* FIXME: get real slot time */
438b61b77   Simon Wunderlich   mac80211: fix tim...
454
  	u32 rate_flags;
cccf129f8   Felix Fietkau   mac80211: add the...
455

06d961a8e   Felix Fietkau   mac80211/minstrel...
456
  	mi->sta = sta;
cccf129f8   Felix Fietkau   mac80211: add the...
457
  	mi->lowest_rix = rate_lowest_index(sband, sta);
d57854bb1   Christian Lamparter   minstrel: fix war...
458
  	ctl_rate = &sband->bitrates[mi->lowest_rix];
4ee73f338   Michal Kazior   mac80211: remove ...
459
460
  	mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
  				ctl_rate->bitrate,
438b61b77   Simon Wunderlich   mac80211: fix tim...
461
462
  				!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1,
  				ieee80211_chandef_get_shift(chandef));
cccf129f8   Felix Fietkau   mac80211: add the...
463

438b61b77   Simon Wunderlich   mac80211: fix tim...
464
  	rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
06d961a8e   Felix Fietkau   mac80211/minstrel...
465
466
  	memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
  	mi->max_prob_rate = 0;
cccf129f8   Felix Fietkau   mac80211: add the...
467
468
  	for (i = 0; i < sband->n_bitrates; i++) {
  		struct minstrel_rate *mr = &mi->r[n];
ca12c0c83   Thomas Huehn   mac80211: Unify r...
469
  		struct minstrel_rate_stats *mrs = &mi->r[n].stats;
cccf129f8   Felix Fietkau   mac80211: add the...
470
471
472
  		unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
  		unsigned int tx_time_single;
  		unsigned int cw = mp->cw_min;
438b61b77   Simon Wunderlich   mac80211: fix tim...
473
  		int shift;
cccf129f8   Felix Fietkau   mac80211: add the...
474
475
476
  
  		if (!rate_supported(sta, sband->band, i))
  			continue;
438b61b77   Simon Wunderlich   mac80211: fix tim...
477
478
  		if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
  			continue;
cccf129f8   Felix Fietkau   mac80211: add the...
479
480
  		n++;
  		memset(mr, 0, sizeof(*mr));
ca12c0c83   Thomas Huehn   mac80211: Unify r...
481
  		memset(mrs, 0, sizeof(*mrs));
cccf129f8   Felix Fietkau   mac80211: add the...
482
483
  
  		mr->rix = i;
438b61b77   Simon Wunderlich   mac80211: fix tim...
484
485
486
487
488
  		shift = ieee80211_chandef_get_shift(chandef);
  		mr->bitrate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
  					   (1 << shift) * 5);
  		calc_rate_durations(sband->band, mr, &sband->bitrates[i],
  				    chandef);
cccf129f8   Felix Fietkau   mac80211: add the...
489
490
491
  
  		/* calculate maximum number of retransmissions before
  		 * fallback (based on maximum segment size) */
f4a8cd94f   Felix Fietkau   minstrel: improve...
492
  		mr->sample_limit = -1;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
493
  		mrs->retry_count = 1;
cccf129f8   Felix Fietkau   mac80211: add the...
494
  		mr->retry_count_cts = 1;
ca12c0c83   Thomas Huehn   mac80211: Unify r...
495
  		mrs->retry_count_rtscts = 1;
cccf129f8   Felix Fietkau   mac80211: add the...
496
497
498
499
500
501
  		tx_time = mr->perfect_tx_time + mi->sp_ack_dur;
  		do {
  			/* add one retransmission */
  			tx_time_single = mr->ack_time + mr->perfect_tx_time;
  
  			/* contention window */
8fddddff0   Daniel Halperin   mac80211: fix con...
502
503
  			tx_time_single += (t_slot * cw) >> 1;
  			cw = min((cw << 1) | 1, mp->cw_max);
cccf129f8   Felix Fietkau   mac80211: add the...
504
505
506
507
508
509
510
511
  
  			tx_time += tx_time_single;
  			tx_time_cts += tx_time_single + mi->sp_ack_dur;
  			tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur;
  			if ((tx_time_cts < mp->segment_size) &&
  				(mr->retry_count_cts < mp->max_retry))
  				mr->retry_count_cts++;
  			if ((tx_time_rtscts < mp->segment_size) &&
ca12c0c83   Thomas Huehn   mac80211: Unify r...
512
513
  				(mrs->retry_count_rtscts < mp->max_retry))
  				mrs->retry_count_rtscts++;
cccf129f8   Felix Fietkau   mac80211: add the...
514
  		} while ((tx_time < mp->segment_size) &&
ca12c0c83   Thomas Huehn   mac80211: Unify r...
515
516
  				(++mr->stats.retry_count < mp->max_retry));
  		mr->adjusted_retry_count = mrs->retry_count;
991fec091   Felix Fietkau   mac80211: fix CTS...
517
  		if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G))
ca12c0c83   Thomas Huehn   mac80211: Unify r...
518
  			mr->retry_count_cts = mrs->retry_count;
cccf129f8   Felix Fietkau   mac80211: add the...
519
520
521
522
523
524
525
526
  	}
  
  	for (i = n; i < sband->n_bitrates; i++) {
  		struct minstrel_rate *mr = &mi->r[i];
  		mr->rix = -1;
  	}
  
  	mi->n_rates = n;
9134073bc   Thomas Huehn   mac80211: improve...
527
  	mi->last_stats_update = jiffies;
cccf129f8   Felix Fietkau   mac80211: add the...
528
529
  
  	init_sample_table(mi);
06d961a8e   Felix Fietkau   mac80211/minstrel...
530
  	minstrel_update_rates(mp, mi);
cccf129f8   Felix Fietkau   mac80211: add the...
531
  }
cca674d47   Antonio Quartulli   mac80211: export ...
532
533
534
  static u32 minstrel_get_expected_throughput(void *priv_sta)
  {
  	struct minstrel_sta_info *mi = priv_sta;
50e55a8ea   Thomas Huehn   mac80211: add max...
535
  	struct minstrel_rate_stats *tmp_mrs;
cca674d47   Antonio Quartulli   mac80211: export ...
536
  	int idx = mi->max_tp_rate[0];
6a27b2c40   Thomas Huehn   mac80211: restruc...
537
  	int tmp_cur_tp;
cca674d47   Antonio Quartulli   mac80211: export ...
538
539
540
541
  
  	/* convert pkt per sec in kbps (1200 is the average pkt size used for
  	 * computing cur_tp
  	 */
50e55a8ea   Thomas Huehn   mac80211: add max...
542
  	tmp_mrs = &mi->r[idx].stats;
5f63afe02   Felix Fietkau   mac80211: minstre...
543
  	tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10;
6a27b2c40   Thomas Huehn   mac80211: restruc...
544
545
546
  	tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
  
  	return tmp_cur_tp;
cca674d47   Antonio Quartulli   mac80211: export ...
547
  }
631ad703b   Johannes Berg   mac80211: make ra...
548
  const struct rate_control_ops mac80211_minstrel = {
18fb84d98   Felix Fietkau   mac80211: make ra...
549
  	.tx_status_ext = minstrel_tx_status,
cccf129f8   Felix Fietkau   mac80211: add the...
550
551
  	.get_rate = minstrel_get_rate,
  	.rate_init = minstrel_rate_init,
cca674d47   Antonio Quartulli   mac80211: export ...
552
  	.get_expected_throughput = minstrel_get_expected_throughput,
cccf129f8   Felix Fietkau   mac80211: add the...
553
  };