Blame view

net/mac80211/rc80211_minstrel.c 15.9 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
57
58
59
60
61
62
63
64
65
66
67
68
69
  #include <net/mac80211.h>
  #include "rate.h"
  #include "rc80211_minstrel.h"
  
  #define SAMPLE_COLUMNS	10
  #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...
70
71
  	return i;
  }
cccf129f8   Felix Fietkau   mac80211: add the...
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
  static void
  minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
  {
  	u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0;
  	u32 max_prob = 0, index_max_prob = 0;
  	u32 usecs;
  	u32 p;
  	int i;
  
  	mi->stats_update = jiffies;
  	for (i = 0; i < mi->n_rates; i++) {
  		struct minstrel_rate *mr = &mi->r[i];
  
  		usecs = mr->perfect_tx_time;
  		if (!usecs)
  			usecs = 1000000;
  
  		/* To avoid rounding issues, probabilities scale from 0 (0%)
  		 * to 18000 (100%) */
  		if (mr->attempts) {
  			p = (mr->success * 18000) / mr->attempts;
  			mr->succ_hist += mr->success;
  			mr->att_hist += mr->attempts;
  			mr->cur_prob = p;
  			p = ((p * (100 - mp->ewma_level)) + (mr->probability *
  				mp->ewma_level)) / 100;
  			mr->probability = p;
  			mr->cur_tp = p * (1000000 / usecs);
  		}
  
  		mr->last_success = mr->success;
  		mr->last_attempts = mr->attempts;
  		mr->success = 0;
  		mr->attempts = 0;
  
  		/* Sample less often below the 10% chance of success.
  		 * Sample less often above the 95% chance of success. */
  		if ((mr->probability > 17100) || (mr->probability < 1800)) {
  			mr->adjusted_retry_count = mr->retry_count >> 1;
  			if (mr->adjusted_retry_count > 2)
  				mr->adjusted_retry_count = 2;
f4a8cd94f   Felix Fietkau   minstrel: improve...
113
  			mr->sample_limit = 4;
cccf129f8   Felix Fietkau   mac80211: add the...
114
  		} else {
f4a8cd94f   Felix Fietkau   minstrel: improve...
115
  			mr->sample_limit = -1;
cccf129f8   Felix Fietkau   mac80211: add the...
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
  			mr->adjusted_retry_count = mr->retry_count;
  		}
  		if (!mr->adjusted_retry_count)
  			mr->adjusted_retry_count = 2;
  	}
  
  	for (i = 0; i < mi->n_rates; i++) {
  		struct minstrel_rate *mr = &mi->r[i];
  		if (max_tp < mr->cur_tp) {
  			index_max_tp = i;
  			max_tp = mr->cur_tp;
  		}
  		if (max_prob < mr->probability) {
  			index_max_prob = i;
  			max_prob = mr->probability;
  		}
  	}
  
  	max_tp = 0;
  	for (i = 0; i < mi->n_rates; i++) {
  		struct minstrel_rate *mr = &mi->r[i];
  
  		if (i == index_max_tp)
  			continue;
  
  		if (max_tp < mr->cur_tp) {
  			index_max_tp2 = i;
  			max_tp = mr->cur_tp;
  		}
  	}
  	mi->max_tp_rate = index_max_tp;
  	mi->max_tp_rate2 = index_max_tp2;
  	mi->max_prob_rate = index_max_prob;
  }
  
  static void
  minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
                     struct ieee80211_sta *sta, void *priv_sta,
  		   struct sk_buff *skb)
  {
  	struct minstrel_sta_info *mi = priv_sta;
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
e6a9854b0   Johannes Berg   mac80211/drivers:...
158
159
160
  	struct ieee80211_tx_rate *ar = info->status.rates;
  	int i, ndx;
  	int success;
cccf129f8   Felix Fietkau   mac80211: add the...
161

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

e6a9854b0   Johannes Berg   mac80211/drivers:...
164
165
  	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
  		if (ar[i].idx < 0)
cccf129f8   Felix Fietkau   mac80211: add the...
166
  			break;
e6a9854b0   Johannes Berg   mac80211/drivers:...
167
  		ndx = rix_to_ndx(mi, ar[i].idx);
3938b45c1   Luciano Coelho   mac80211: minstre...
168
169
  		if (ndx < 0)
  			continue;
e6a9854b0   Johannes Berg   mac80211/drivers:...
170
  		mi->r[ndx].attempts += ar[i].count;
cccf129f8   Felix Fietkau   mac80211: add the...
171

bfc32e6a9   Javier Cardona   mac80211: Decoupl...
172
  		if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
cccf129f8   Felix Fietkau   mac80211: add the...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  			mi->r[ndx].success += success;
  	}
  
  	if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
  		mi->sample_count++;
  
  	if (mi->sample_deferred > 0)
  		mi->sample_deferred--;
  }
  
  
  static inline unsigned int
  minstrel_get_retry_count(struct minstrel_rate *mr,
                           struct ieee80211_tx_info *info)
  {
  	unsigned int retry = mr->adjusted_retry_count;
e6a9854b0   Johannes Berg   mac80211/drivers:...
189
  	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
cccf129f8   Felix Fietkau   mac80211: add the...
190
  		retry = max(2U, min(mr->retry_count_rtscts, retry));
e6a9854b0   Johannes Berg   mac80211/drivers:...
191
  	else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
cccf129f8   Felix Fietkau   mac80211: add the...
192
193
194
195
196
197
198
199
200
201
202
  		retry = max(2U, min(mr->retry_count_cts, retry));
  	return retry;
  }
  
  
  static int
  minstrel_get_next_sample(struct minstrel_sta_info *mi)
  {
  	unsigned int sample_ndx;
  	sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);
  	mi->sample_idx++;
5ee58d7e6   Bob Copeland   mac80211: fix min...
203
  	if ((int) mi->sample_idx > (mi->n_rates - 2)) {
cccf129f8   Felix Fietkau   mac80211: add the...
204
205
206
207
208
209
210
  		mi->sample_idx = 0;
  		mi->sample_column++;
  		if (mi->sample_column >= SAMPLE_COLUMNS)
  			mi->sample_column = 0;
  	}
  	return sample_ndx;
  }
2df78167a   Johannes Berg   wireless: fix a f...
211
  static void
e6a9854b0   Johannes Berg   mac80211/drivers:...
212
213
  minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
  		  void *priv_sta, struct ieee80211_tx_rate_control *txrc)
cccf129f8   Felix Fietkau   mac80211: add the...
214
  {
e6a9854b0   Johannes Berg   mac80211/drivers:...
215
  	struct sk_buff *skb = txrc->skb;
cccf129f8   Felix Fietkau   mac80211: add the...
216
217
218
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  	struct minstrel_sta_info *mi = priv_sta;
  	struct minstrel_priv *mp = priv;
e6a9854b0   Johannes Berg   mac80211/drivers:...
219
  	struct ieee80211_tx_rate *ar = info->control.rates;
cccf129f8   Felix Fietkau   mac80211: add the...
220
221
222
223
224
225
226
  	unsigned int ndx, sample_ndx = 0;
  	bool mrr;
  	bool sample_slower = false;
  	bool sample = false;
  	int i, delta;
  	int mrr_ndx[3];
  	int sample_rate;
4c6d4f5c3   Luis R. Rodriguez   mac80211: add hel...
227
  	if (rate_control_send_low(sta, priv_sta, txrc))
cccf129f8   Felix Fietkau   mac80211: add the...
228
  		return;
cccf129f8   Felix Fietkau   mac80211: add the...
229

e6a9854b0   Johannes Berg   mac80211/drivers:...
230
  	mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot;
cccf129f8   Felix Fietkau   mac80211: add the...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  
  	if (time_after(jiffies, mi->stats_update + (mp->update_interval *
  			HZ) / 1000))
  		minstrel_update_stats(mp, mi);
  
  	ndx = mi->max_tp_rate;
  
  	if (mrr)
  		sample_rate = mp->lookaround_rate_mrr;
  	else
  		sample_rate = mp->lookaround_rate;
  
  	mi->packet_count++;
  	delta = (mi->packet_count * sample_rate / 100) -
  			(mi->sample_count + mi->sample_deferred / 2);
  
  	/* delta > 0: sampling required */
f4a8cd94f   Felix Fietkau   minstrel: improve...
248
249
  	if ((delta > 0) && (mrr || !mi->prev_sample)) {
  		struct minstrel_rate *msr;
cccf129f8   Felix Fietkau   mac80211: add the...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
  		if (mi->packet_count >= 10000) {
  			mi->sample_deferred = 0;
  			mi->sample_count = 0;
  			mi->packet_count = 0;
  		} 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. */
  			mi->sample_count += (delta - mi->n_rates * 2);
  		}
  
  		sample_ndx = minstrel_get_next_sample(mi);
f4a8cd94f   Felix Fietkau   minstrel: improve...
268
  		msr = &mi->r[sample_ndx];
cccf129f8   Felix Fietkau   mac80211: add the...
269
  		sample = true;
f4a8cd94f   Felix Fietkau   minstrel: improve...
270
  		sample_slower = mrr && (msr->perfect_tx_time >
cccf129f8   Felix Fietkau   mac80211: add the...
271
272
273
  			mi->r[ndx].perfect_tx_time);
  
  		if (!sample_slower) {
f4a8cd94f   Felix Fietkau   minstrel: improve...
274
275
276
277
278
279
280
281
  			if (msr->sample_limit != 0) {
  				ndx = sample_ndx;
  				mi->sample_count++;
  				if (msr->sample_limit > 0)
  					msr->sample_limit--;
  			} else {
  				sample = false;
  			}
cccf129f8   Felix Fietkau   mac80211: add the...
282
283
284
285
286
287
288
289
290
291
292
  		} else {
  			/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
  			 * packets that have the sampling rate deferred to the
  			 * second MRR stage. Increase the sample counter only
  			 * if the deferred sample rate was actually used.
  			 * Use the sample_deferred counter to make sure that
  			 * the sampling is not done in large bursts */
  			info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
  			mi->sample_deferred++;
  		}
  	}
f4a8cd94f   Felix Fietkau   minstrel: improve...
293
294
295
296
297
298
299
  	mi->prev_sample = sample;
  
  	/* 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 */
  	if (!mrr && sample && (mi->r[ndx].probability > 17100))
  		ndx = mi->max_tp_rate;
e6a9854b0   Johannes Berg   mac80211/drivers:...
300
301
  	ar[0].idx = mi->r[ndx].rix;
  	ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
cccf129f8   Felix Fietkau   mac80211: add the...
302
303
  
  	if (!mrr) {
f4a8cd94f   Felix Fietkau   minstrel: improve...
304
305
  		if (!sample)
  			ar[0].count = mp->max_retry;
e6a9854b0   Johannes Berg   mac80211/drivers:...
306
307
  		ar[1].idx = mi->lowest_rix;
  		ar[1].count = mp->max_retry;
cccf129f8   Felix Fietkau   mac80211: add the...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  		return;
  	}
  
  	/* MRR setup */
  	if (sample) {
  		if (sample_slower)
  			mrr_ndx[0] = sample_ndx;
  		else
  			mrr_ndx[0] = mi->max_tp_rate;
  	} else {
  		mrr_ndx[0] = mi->max_tp_rate2;
  	}
  	mrr_ndx[1] = mi->max_prob_rate;
  	mrr_ndx[2] = 0;
e6a9854b0   Johannes Berg   mac80211/drivers:...
322
323
324
  	for (i = 1; i < 4; i++) {
  		ar[i].idx = mi->r[mrr_ndx[i - 1]].rix;
  		ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count;
cccf129f8   Felix Fietkau   mac80211: add the...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
  	}
  }
  
  
  static void
  calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local,
                      struct minstrel_rate *d, struct ieee80211_rate *rate)
  {
  	int erp = !!(rate->flags & IEEE80211_RATE_ERP_G);
  
  	d->perfect_tx_time = ieee80211_frame_duration(local, 1200,
  			rate->bitrate, erp, 1);
  	d->ack_time = ieee80211_frame_duration(local, 10,
  			rate->bitrate, erp, 1);
  }
  
  static void
  init_sample_table(struct minstrel_sta_info *mi)
  {
  	unsigned int i, col, new_idx;
  	unsigned int n_srates = mi->n_rates - 1;
  	u8 rnd[8];
  
  	mi->sample_column = 0;
  	mi->sample_idx = 0;
  	memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates);
  
  	for (col = 0; col < SAMPLE_COLUMNS; col++) {
  		for (i = 0; i < n_srates; i++) {
  			get_random_bytes(rnd, sizeof(rnd));
  			new_idx = (i + rnd[i & 7]) % n_srates;
  
  			while (SAMPLE_TBL(mi, new_idx, col) != 0)
  				new_idx = (new_idx + 1) % n_srates;
  
  			/* Don't sample the slowest rate (i.e. slowest base
  			 * rate). We must presume that the slowest rate works
  			 * fine, or else other management frames will also be
  			 * failing and the link will break */
  			SAMPLE_TBL(mi, new_idx, col) = i + 1;
  		}
  	}
  }
  
  static void
  minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
                 struct ieee80211_sta *sta, void *priv_sta)
  {
  	struct minstrel_sta_info *mi = priv_sta;
  	struct minstrel_priv *mp = priv;
d57854bb1   Christian Lamparter   minstrel: fix war...
375
376
  	struct ieee80211_local *local = hw_to_local(mp->hw);
  	struct ieee80211_rate *ctl_rate;
cccf129f8   Felix Fietkau   mac80211: add the...
377
378
379
380
  	unsigned int i, n = 0;
  	unsigned int t_slot = 9; /* FIXME: get real slot time */
  
  	mi->lowest_rix = rate_lowest_index(sband, sta);
d57854bb1   Christian Lamparter   minstrel: fix war...
381
382
383
  	ctl_rate = &sband->bitrates[mi->lowest_rix];
  	mi->sp_ack_dur = ieee80211_frame_duration(local, 10, ctl_rate->bitrate,
  				!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
cccf129f8   Felix Fietkau   mac80211: add the...
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  
  	for (i = 0; i < sband->n_bitrates; i++) {
  		struct minstrel_rate *mr = &mi->r[n];
  		unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
  		unsigned int tx_time_single;
  		unsigned int cw = mp->cw_min;
  
  		if (!rate_supported(sta, sband->band, i))
  			continue;
  		n++;
  		memset(mr, 0, sizeof(*mr));
  
  		mr->rix = i;
  		mr->bitrate = sband->bitrates[i].bitrate / 5;
d57854bb1   Christian Lamparter   minstrel: fix war...
398
  		calc_rate_durations(mi, local, mr,
cccf129f8   Felix Fietkau   mac80211: add the...
399
400
401
402
  				&sband->bitrates[i]);
  
  		/* calculate maximum number of retransmissions before
  		 * fallback (based on maximum segment size) */
f4a8cd94f   Felix Fietkau   minstrel: improve...
403
  		mr->sample_limit = -1;
cccf129f8   Felix Fietkau   mac80211: add the...
404
405
406
407
408
409
410
411
412
  		mr->retry_count = 1;
  		mr->retry_count_cts = 1;
  		mr->retry_count_rtscts = 1;
  		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...
413
414
  			tx_time_single += (t_slot * cw) >> 1;
  			cw = min((cw << 1) | 1, mp->cw_max);
cccf129f8   Felix Fietkau   mac80211: add the...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  
  			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) &&
  				(mr->retry_count_rtscts < mp->max_retry))
  				mr->retry_count_rtscts++;
  		} while ((tx_time < mp->segment_size) &&
  				(++mr->retry_count < mp->max_retry));
  		mr->adjusted_retry_count = mr->retry_count;
  	}
  
  	for (i = n; i < sband->n_bitrates; i++) {
  		struct minstrel_rate *mr = &mi->r[i];
  		mr->rix = -1;
  	}
  
  	mi->n_rates = n;
  	mi->stats_update = jiffies;
  
  	init_sample_table(mi);
  }
  
  static void *
  minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
  {
  	struct ieee80211_supported_band *sband;
  	struct minstrel_sta_info *mi;
  	struct minstrel_priv *mp = priv;
  	struct ieee80211_hw *hw = mp->hw;
  	int max_rates = 0;
  	int i;
  
  	mi = kzalloc(sizeof(struct minstrel_sta_info), gfp);
  	if (!mi)
  		return NULL;
  
  	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8e5321752   Jiri Slaby   mac80211: minstre...
456
  		sband = hw->wiphy->bands[i];
621ad7c96   John W. Linville   mac80211: avoid N...
457
  		if (sband && sband->n_bitrates > max_rates)
cccf129f8   Felix Fietkau   mac80211: add the...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  			max_rates = sband->n_bitrates;
  	}
  
  	mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
  	if (!mi->r)
  		goto error;
  
  	mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
  	if (!mi->sample_table)
  		goto error1;
  
  	mi->stats_update = jiffies;
  	return mi;
  
  error1:
  	kfree(mi->r);
  error:
  	kfree(mi);
  	return NULL;
  }
  
  static void
  minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
  {
  	struct minstrel_sta_info *mi = priv_sta;
  
  	kfree(mi->sample_table);
  	kfree(mi->r);
  	kfree(mi);
  }
cccf129f8   Felix Fietkau   mac80211: add the...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  static void *
  minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
  {
  	struct minstrel_priv *mp;
  
  	mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
  	if (!mp)
  		return NULL;
  
  	/* contention window settings
  	 * Just an approximation. Using the per-queue values would complicate
  	 * the calculations and is probably unnecessary */
  	mp->cw_min = 15;
  	mp->cw_max = 1023;
  
  	/* number of packets (in %) to use for sampling other rates
  	 * sample less often for non-mrr packets, because the overhead
  	 * is much higher than with mrr */
  	mp->lookaround_rate = 5;
  	mp->lookaround_rate_mrr = 10;
  
  	/* moving average weight for EWMA */
  	mp->ewma_level = 75;
  
  	/* maximum time that the hw is allowed to stay in one MRR segment */
  	mp->segment_size = 6000;
e6a9854b0   Johannes Berg   mac80211/drivers:...
514
515
  	if (hw->max_rate_tries > 0)
  		mp->max_retry = hw->max_rate_tries;
cccf129f8   Felix Fietkau   mac80211: add the...
516
517
518
  	else
  		/* safe default, does not necessarily have to match hw properties */
  		mp->max_retry = 7;
e6a9854b0   Johannes Berg   mac80211/drivers:...
519
  	if (hw->max_rates >= 4)
cccf129f8   Felix Fietkau   mac80211: add the...
520
521
522
523
  		mp->has_mrr = true;
  
  	mp->hw = hw;
  	mp->update_interval = 100;
24f7580e8   Zefir Kurtisi   minstrel_ht: fixe...
524
525
526
527
528
  #ifdef CONFIG_MAC80211_DEBUGFS
  	mp->fixed_rate_idx = (u32) -1;
  	mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
  			S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx);
  #endif
cccf129f8   Felix Fietkau   mac80211: add the...
529
530
531
532
533
534
  	return mp;
  }
  
  static void
  minstrel_free(void *priv)
  {
24f7580e8   Zefir Kurtisi   minstrel_ht: fixe...
535
536
537
  #ifdef CONFIG_MAC80211_DEBUGFS
  	debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
  #endif
cccf129f8   Felix Fietkau   mac80211: add the...
538
539
  	kfree(priv);
  }
eae44756d   Felix Fietkau   minstrel: make th...
540
  struct rate_control_ops mac80211_minstrel = {
cccf129f8   Felix Fietkau   mac80211: add the...
541
542
543
544
  	.name = "minstrel",
  	.tx_status = minstrel_tx_status,
  	.get_rate = minstrel_get_rate,
  	.rate_init = minstrel_rate_init,
cccf129f8   Felix Fietkau   mac80211: add the...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  	.alloc = minstrel_alloc,
  	.free = minstrel_free,
  	.alloc_sta = minstrel_alloc_sta,
  	.free_sta = minstrel_free_sta,
  #ifdef CONFIG_MAC80211_DEBUGFS
  	.add_sta_debugfs = minstrel_add_sta_debugfs,
  	.remove_sta_debugfs = minstrel_remove_sta_debugfs,
  #endif
  };
  
  int __init
  rc80211_minstrel_init(void)
  {
  	return ieee80211_rate_control_register(&mac80211_minstrel);
  }
  
  void
  rc80211_minstrel_exit(void)
  {
  	ieee80211_rate_control_unregister(&mac80211_minstrel);
  }