Blame view

net/mac80211/rc80211_pid_algo.c 14.6 KB
ad0183759   Mattias Nissler   mac80211: add PID...
1
2
3
4
  /*
   * Copyright 2002-2005, Instant802 Networks, Inc.
   * Copyright 2005, Devicescape Software, Inc.
   * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de>
b7c50de92   Stefano Brivio   rc80211-pid: fix ...
5
   * Copyright 2007-2008, Stefano Brivio <stefano.brivio@polimi.it>
ad0183759   Mattias Nissler   mac80211: add PID...
6
7
8
9
10
11
12
13
14
   *
   * 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.
   */
  
  #include <linux/netdevice.h>
  #include <linux/types.h>
  #include <linux/skbuff.h>
4b475898e   Johannes Berg   mac80211: better ...
15
  #include <linux/debugfs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/slab.h>
ad0183759   Mattias Nissler   mac80211: add PID...
17
  #include <net/mac80211.h>
2c8dccc77   Johannes Berg   mac80211: rename ...
18
  #include "rate.h"
ee3858551   Luis Carlos Cobo   mac80211: mesh da...
19
  #include "mesh.h"
12446c67f   Mattias Nissler   rc80211-pid: add ...
20
  #include "rc80211_pid.h"
ad0183759   Mattias Nissler   mac80211: add PID...
21
22
23
24
25
26
27
  
  /* This is an implementation of a TX rate control algorithm that uses a PID
   * controller. Given a target failed frames rate, the controller decides about
   * TX rate changes to meet the target failed frames rate.
   *
   * The controller basically computes the following:
   *
1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
28
   * adj = CP * err + CI * err_avg + CD * (err - last_err) * (1 + sharpening)
ad0183759   Mattias Nissler   mac80211: add PID...
29
30
31
32
33
34
   *
   * where
   * 	adj	adjustment value that is used to switch TX rate (see below)
   * 	err	current error: target vs. current failed frames percentage
   * 	last_err	last error
   * 	err_avg	average (i.e. poor man's integral) of recent errors
1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
35
36
37
   *	sharpening	non-zero when fast response is needed (i.e. right after
   *			association or no frames sent for a long time), heading
   * 			to zero over time
ad0183759   Mattias Nissler   mac80211: add PID...
38
39
40
41
42
43
44
45
46
47
   * 	CP	Proportional coefficient
   * 	CI	Integral coefficient
   * 	CD	Derivative coefficient
   *
   * CP, CI, CD are subject to careful tuning.
   *
   * The integral component uses a exponential moving average approach instead of
   * an actual sliding window. The advantage is that we don't need to keep an
   * array of the last N error values and computation is easier.
   *
90d501d61   Stefano Brivio   rc80211-pid: add ...
48
49
50
51
52
53
54
55
56
57
58
59
   * Once we have the adj value, we map it to a rate by means of a learning
   * algorithm. This algorithm keeps the state of the percentual failed frames
   * difference between rates. The behaviour of the lowest available rate is kept
   * as a reference value, and every time we switch between two rates, we compute
   * the difference between the failed frames each rate exhibited. By doing so,
   * we compare behaviours which different rates exhibited in adjacent timeslices,
   * thus the comparison is minimally affected by external conditions. This
   * difference gets propagated to the whole set of measurements, so that the
   * reference is always the same. Periodically, we normalize this set so that
   * recent events weigh the most. By comparing the adj value with this set, we
   * avoid pejorative switches to lower rates and allow for switches to higher
   * rates if they behaved well.
ad0183759   Mattias Nissler   mac80211: add PID...
60
61
62
63
64
   *
   * Note that for the computations we use a fixed-point representation to avoid
   * floating point arithmetic. Hence, all values are shifted left by
   * RC_PID_ARITH_SHIFT.
   */
ad0183759   Mattias Nissler   mac80211: add PID...
65

b7c50de92   Stefano Brivio   rc80211-pid: fix ...
66
67
68
69
  /* Adjust the rate while ensuring that we won't switch to a lower rate if it
   * exhibited a worse failed frames behaviour and we'll choose the highest rate
   * whose failed frames behaviour is not worse than the one of the original rate
   * target. While at it, check that the new rate is valid. */
4b7679a56   Johannes Berg   mac80211: clean u...
70
71
72
  static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband,
  					 struct ieee80211_sta *sta,
  					 struct rc_pid_sta_info *spinfo, int adj,
90d501d61   Stefano Brivio   rc80211-pid: add ...
73
  					 struct rc_pid_rateinfo *rinfo)
ad0183759   Mattias Nissler   mac80211: add PID...
74
  {
b7c50de92   Stefano Brivio   rc80211-pid: fix ...
75
  	int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
ae17e9860   Johannes Berg   mac80211: move tx...
76
  	int cur = spinfo->txrate_idx;
ad0183759   Mattias Nissler   mac80211: add PID...
77

b7c50de92   Stefano Brivio   rc80211-pid: fix ...
78
79
  	band = sband->band;
  	n_bitrates = sband->n_bitrates;
ad0183759   Mattias Nissler   mac80211: add PID...
80

b7c50de92   Stefano Brivio   rc80211-pid: fix ...
81
82
83
  	/* Map passed arguments to sorted values. */
  	cur_sorted = rinfo[cur].rev_index;
  	new_sorted = cur_sorted + adj;
ad0183759   Mattias Nissler   mac80211: add PID...
84

b7c50de92   Stefano Brivio   rc80211-pid: fix ...
85
86
87
88
89
90
91
  	/* Check limits. */
  	if (new_sorted < 0)
  		new_sorted = rinfo[0].rev_index;
  	else if (new_sorted >= n_bitrates)
  		new_sorted = rinfo[n_bitrates - 1].rev_index;
  
  	tmp = new_sorted;
ad0183759   Mattias Nissler   mac80211: add PID...
92

b7c50de92   Stefano Brivio   rc80211-pid: fix ...
93
94
95
96
97
98
99
100
101
102
103
104
  	if (adj < 0) {
  		/* Ensure that the rate decrease isn't disadvantageous. */
  		for (probe = cur_sorted; probe >= new_sorted; probe--)
  			if (rinfo[probe].diff <= rinfo[cur_sorted].diff &&
  			    rate_supported(sta, band, rinfo[probe].index))
  				tmp = probe;
  	} else {
  		/* Look for rate increase with zero (or below) cost. */
  		for (probe = new_sorted + 1; probe < n_bitrates; probe++)
  			if (rinfo[probe].diff <= rinfo[new_sorted].diff &&
  			    rate_supported(sta, band, rinfo[probe].index))
  				tmp = probe;
ad0183759   Mattias Nissler   mac80211: add PID...
105
  	}
12446c67f   Mattias Nissler   rc80211-pid: add ...
106

b7c50de92   Stefano Brivio   rc80211-pid: fix ...
107
108
109
  	/* Fit the rate found to the nearest supported rate. */
  	do {
  		if (rate_supported(sta, band, rinfo[tmp].index)) {
ae17e9860   Johannes Berg   mac80211: move tx...
110
  			spinfo->txrate_idx = rinfo[tmp].index;
b7c50de92   Stefano Brivio   rc80211-pid: fix ...
111
112
113
114
115
116
117
  			break;
  		}
  		if (adj < 0)
  			tmp--;
  		else
  			tmp++;
  	} while (tmp < n_bitrates && tmp >= 0);
12446c67f   Mattias Nissler   rc80211-pid: add ...
118
  #ifdef CONFIG_MAC80211_DEBUGFS
ae17e9860   Johannes Berg   mac80211: move tx...
119
120
121
  	rate_control_pid_event_rate_change(&spinfo->events,
  		spinfo->txrate_idx,
  		sband->bitrates[spinfo->txrate_idx].bitrate);
12446c67f   Mattias Nissler   rc80211-pid: add ...
122
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
123
  }
90d501d61   Stefano Brivio   rc80211-pid: add ...
124
  /* Normalize the failed frames per-rate differences. */
1946b74ce   Mattias Nissler   rc80211-pid: expo...
125
  static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l)
90d501d61   Stefano Brivio   rc80211-pid: add ...
126
  {
1946b74ce   Mattias Nissler   rc80211-pid: expo...
127
128
  	int i, norm_offset = pinfo->norm_offset;
  	struct rc_pid_rateinfo *r = pinfo->rinfo;
90d501d61   Stefano Brivio   rc80211-pid: add ...
129

1946b74ce   Mattias Nissler   rc80211-pid: expo...
130
131
132
133
  	if (r[0].diff > norm_offset)
  		r[0].diff -= norm_offset;
  	else if (r[0].diff < -norm_offset)
  		r[0].diff += norm_offset;
90d501d61   Stefano Brivio   rc80211-pid: add ...
134
  	for (i = 0; i < l - 1; i++)
1946b74ce   Mattias Nissler   rc80211-pid: expo...
135
136
  		if (r[i + 1].diff > r[i].diff + norm_offset)
  			r[i + 1].diff -= norm_offset;
90d501d61   Stefano Brivio   rc80211-pid: add ...
137
  		else if (r[i + 1].diff <= r[i].diff)
1946b74ce   Mattias Nissler   rc80211-pid: expo...
138
  			r[i + 1].diff += norm_offset;
90d501d61   Stefano Brivio   rc80211-pid: add ...
139
  }
ad0183759   Mattias Nissler   mac80211: add PID...
140
  static void rate_control_pid_sample(struct rc_pid_info *pinfo,
4b7679a56   Johannes Berg   mac80211: clean u...
141
142
143
  				    struct ieee80211_supported_band *sband,
  				    struct ieee80211_sta *sta,
  				    struct rc_pid_sta_info *spinfo)
ad0183759   Mattias Nissler   mac80211: add PID...
144
  {
90d501d61   Stefano Brivio   rc80211-pid: add ...
145
  	struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
ad0183759   Mattias Nissler   mac80211: add PID...
146
147
  	u32 pf;
  	s32 err_avg;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
148
149
150
  	u32 err_prop;
  	u32 err_int;
  	u32 err_der;
90d501d61   Stefano Brivio   rc80211-pid: add ...
151
  	int adj, i, j, tmp;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
152
  	unsigned long period;
ad0183759   Mattias Nissler   mac80211: add PID...
153

1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
154
155
  	/* In case nothing happened during the previous control interval, turn
  	 * the sharpening factor on. */
8e9310c17   Bob Copeland   mac80211: pid: re...
156
  	period = msecs_to_jiffies(pinfo->sampling_period);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
157
158
  	if (jiffies - spinfo->last_sample > 2 * period)
  		spinfo->sharp_cnt = pinfo->sharpen_duration;
1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
159

ad0183759   Mattias Nissler   mac80211: add PID...
160
  	spinfo->last_sample = jiffies;
1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
161
  	/* This should never happen, but in case, we assume the old sample is
ad0183759   Mattias Nissler   mac80211: add PID...
162
  	 * still a good measurement and copy it. */
1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
163
  	if (unlikely(spinfo->tx_num_xmit == 0))
ad0183759   Mattias Nissler   mac80211: add PID...
164
  		pf = spinfo->last_pf;
bfc32e6a9   Javier Cardona   mac80211: Decoupl...
165
  	else
ad0183759   Mattias Nissler   mac80211: add PID...
166
  		pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
4b7679a56   Johannes Berg   mac80211: clean u...
167

1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
168
169
  	spinfo->tx_num_xmit = 0;
  	spinfo->tx_num_failed = 0;
90d501d61   Stefano Brivio   rc80211-pid: add ...
170
  	/* If we just switched rate, update the rate behaviour info. */
ae17e9860   Johannes Berg   mac80211: move tx...
171
  	if (pinfo->oldrate != spinfo->txrate_idx) {
90d501d61   Stefano Brivio   rc80211-pid: add ...
172
173
  
  		i = rinfo[pinfo->oldrate].rev_index;
ae17e9860   Johannes Berg   mac80211: move tx...
174
  		j = rinfo[spinfo->txrate_idx].rev_index;
90d501d61   Stefano Brivio   rc80211-pid: add ...
175
176
177
178
179
  
  		tmp = (pf - spinfo->last_pf);
  		tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT);
  
  		rinfo[j].diff = rinfo[i].diff + tmp;
ae17e9860   Johannes Berg   mac80211: move tx...
180
  		pinfo->oldrate = spinfo->txrate_idx;
90d501d61   Stefano Brivio   rc80211-pid: add ...
181
  	}
8318d78a4   Johannes Berg   cfg80211 API for ...
182
  	rate_control_pid_normalize(pinfo, sband->n_bitrates);
90d501d61   Stefano Brivio   rc80211-pid: add ...
183

ad0183759   Mattias Nissler   mac80211: add PID...
184
  	/* Compute the proportional, integral and derivative errors. */
e850f68b8   Bob Copeland   mac80211: fix sig...
185
  	err_prop = (pinfo->target - pf) << RC_PID_ARITH_SHIFT;
ad0183759   Mattias Nissler   mac80211: add PID...
186

1946b74ce   Mattias Nissler   rc80211-pid: expo...
187
  	err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift;
ad0183759   Mattias Nissler   mac80211: add PID...
188
  	spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
189
  	err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift;
ad0183759   Mattias Nissler   mac80211: add PID...
190

1946b74ce   Mattias Nissler   rc80211-pid: expo...
191
192
  	err_der = (pf - spinfo->last_pf) *
  		  (1 + pinfo->sharpen_factor * spinfo->sharp_cnt);
ad0183759   Mattias Nissler   mac80211: add PID...
193
  	spinfo->last_pf = pf;
1dc4d1e6a   Stefano Brivio   rc80211-pid: add ...
194
195
  	if (spinfo->sharp_cnt)
  			spinfo->sharp_cnt--;
ad0183759   Mattias Nissler   mac80211: add PID...
196

12446c67f   Mattias Nissler   rc80211-pid: add ...
197
198
199
200
  #ifdef CONFIG_MAC80211_DEBUGFS
  	rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int,
  					 err_der);
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
201
202
203
  	/* Compute the controller output. */
  	adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i
  	      + err_der * pinfo->coeff_d);
90d501d61   Stefano Brivio   rc80211-pid: add ...
204
  	adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT);
ad0183759   Mattias Nissler   mac80211: add PID...
205
206
207
  
  	/* Change rate. */
  	if (adj)
4b7679a56   Johannes Berg   mac80211: clean u...
208
  		rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo);
ad0183759   Mattias Nissler   mac80211: add PID...
209
  }
4b7679a56   Johannes Berg   mac80211: clean u...
210
211
  static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband,
  				       struct ieee80211_sta *sta, void *priv_sta,
e039fa4a4   Johannes Berg   mac80211: move TX...
212
  				       struct sk_buff *skb)
ad0183759   Mattias Nissler   mac80211: add PID...
213
  {
ad0183759   Mattias Nissler   mac80211: add PID...
214
  	struct rc_pid_info *pinfo = priv;
4b7679a56   Johannes Berg   mac80211: clean u...
215
  	struct rc_pid_sta_info *spinfo = priv_sta;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
216
  	unsigned long period;
e039fa4a4   Johannes Berg   mac80211: move TX...
217
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ad0183759   Mattias Nissler   mac80211: add PID...
218

4b7679a56   Johannes Berg   mac80211: clean u...
219
220
  	if (!spinfo)
  		return;
df26e7ea0   Andrew Lutomirski   rc80211_pid shoul...
221

ad0183759   Mattias Nissler   mac80211: add PID...
222
223
  	/* Ignore all frames that were sent with a different rate than the rate
  	 * we currently advise mac80211 to use. */
e6a9854b0   Johannes Berg   mac80211/drivers:...
224
  	if (info->status.rates[0].idx != spinfo->txrate_idx)
4b7679a56   Johannes Berg   mac80211: clean u...
225
  		return;
ad0183759   Mattias Nissler   mac80211: add PID...
226

ad0183759   Mattias Nissler   mac80211: add PID...
227
  	spinfo->tx_num_xmit++;
12446c67f   Mattias Nissler   rc80211-pid: add ...
228
  #ifdef CONFIG_MAC80211_DEBUGFS
e039fa4a4   Johannes Berg   mac80211: move TX...
229
  	rate_control_pid_event_tx_status(&spinfo->events, info);
12446c67f   Mattias Nissler   rc80211-pid: add ...
230
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
231
232
233
  	/* We count frames that totally failed to be transmitted as two bad
  	 * frames, those that made it out but had some retries as one good and
  	 * one bad frame. */
e6a9854b0   Johannes Berg   mac80211/drivers:...
234
  	if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
ad0183759   Mattias Nissler   mac80211: add PID...
235
236
  		spinfo->tx_num_failed += 2;
  		spinfo->tx_num_xmit++;
1dc5a8416   Larry Finger   mac80211: Fix pid...
237
  	} else if (info->status.rates[0].count > 1) {
ad0183759   Mattias Nissler   mac80211: add PID...
238
239
240
  		spinfo->tx_num_failed++;
  		spinfo->tx_num_xmit++;
  	}
ad0183759   Mattias Nissler   mac80211: add PID...
241
  	/* Update PID controller state. */
8e9310c17   Bob Copeland   mac80211: pid: re...
242
  	period = msecs_to_jiffies(pinfo->sampling_period);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
243
  	if (time_after(jiffies, spinfo->last_sample + period))
4b7679a56   Johannes Berg   mac80211: clean u...
244
  		rate_control_pid_sample(pinfo, sband, sta, spinfo);
ad0183759   Mattias Nissler   mac80211: add PID...
245
  }
4b7679a56   Johannes Berg   mac80211: clean u...
246
  static void
e6a9854b0   Johannes Berg   mac80211/drivers:...
247
248
249
  rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta,
  			  void *priv_sta,
  			  struct ieee80211_tx_rate_control *txrc)
ad0183759   Mattias Nissler   mac80211: add PID...
250
  {
e6a9854b0   Johannes Berg   mac80211/drivers:...
251
252
  	struct sk_buff *skb = txrc->skb;
  	struct ieee80211_supported_band *sband = txrc->sband;
e6a9854b0   Johannes Berg   mac80211/drivers:...
253
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4b7679a56   Johannes Berg   mac80211: clean u...
254
  	struct rc_pid_sta_info *spinfo = priv_sta;
ad0183759   Mattias Nissler   mac80211: add PID...
255
  	int rateidx;
e6a9854b0   Johannes Berg   mac80211/drivers:...
256
257
258
259
260
261
  	if (txrc->rts)
  		info->control.rates[0].count =
  			txrc->hw->conf.long_frame_max_tx_count;
  	else
  		info->control.rates[0].count =
  			txrc->hw->conf.short_frame_max_tx_count;
922368414   Gábor Stefanik   mac80211: Fix han...
262
  	/* Send management frames and NO_ACK data using lowest rate. */
4c6d4f5c3   Luis R. Rodriguez   mac80211: add hel...
263
  	if (rate_control_send_low(sta, priv_sta, txrc))
ad0183759   Mattias Nissler   mac80211: add PID...
264
  		return;
ad0183759   Mattias Nissler   mac80211: add PID...
265

ae17e9860   Johannes Berg   mac80211: move tx...
266
  	rateidx = spinfo->txrate_idx;
ad0183759   Mattias Nissler   mac80211: add PID...
267

8318d78a4   Johannes Berg   cfg80211 API for ...
268
269
  	if (rateidx >= sband->n_bitrates)
  		rateidx = sband->n_bitrates - 1;
ad0183759   Mattias Nissler   mac80211: add PID...
270

e6a9854b0   Johannes Berg   mac80211/drivers:...
271
  	info->control.rates[0].idx = rateidx;
12446c67f   Mattias Nissler   rc80211-pid: add ...
272
273
  
  #ifdef CONFIG_MAC80211_DEBUGFS
4b7679a56   Johannes Berg   mac80211: clean u...
274
  	rate_control_pid_event_tx_rate(&spinfo->events,
8318d78a4   Johannes Berg   cfg80211 API for ...
275
  		rateidx, sband->bitrates[rateidx].bitrate);
12446c67f   Mattias Nissler   rc80211-pid: add ...
276
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
277
  }
4b7679a56   Johannes Berg   mac80211: clean u...
278
279
280
  static void
  rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
  			   struct ieee80211_sta *sta, void *priv_sta)
ad0183759   Mattias Nissler   mac80211: add PID...
281
  {
4b7679a56   Johannes Berg   mac80211: clean u...
282
  	struct rc_pid_sta_info *spinfo = priv_sta;
6909268dc   Jiri Slaby   mac80211: pid, fi...
283
284
  	struct rc_pid_info *pinfo = priv;
  	struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
6909268dc   Jiri Slaby   mac80211: pid, fi...
285
286
  	int i, j, tmp;
  	bool s;
4b7679a56   Johannes Berg   mac80211: clean u...
287

ad0183759   Mattias Nissler   mac80211: add PID...
288
289
290
291
  	/* TODO: This routine should consider using RSSI from previous packets
  	 * as we need to have IEEE 802.1X auth succeed immediately after assoc..
  	 * Until that method is implemented, we will use the lowest supported
  	 * rate as a workaround. */
8318d78a4   Johannes Berg   cfg80211 API for ...
292

6909268dc   Jiri Slaby   mac80211: pid, fi...
293
294
295
296
297
298
299
300
301
302
303
304
  	/* Sort the rates. This is optimized for the most common case (i.e.
  	 * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
  	 * mapping too. */
  	for (i = 0; i < sband->n_bitrates; i++) {
  		rinfo[i].index = i;
  		rinfo[i].rev_index = i;
  		if (RC_PID_FAST_START)
  			rinfo[i].diff = 0;
  		else
  			rinfo[i].diff = i * pinfo->norm_offset;
  	}
  	for (i = 1; i < sband->n_bitrates; i++) {
3db1cd5c0   Rusty Russell   net: fix assignme...
305
  		s = false;
6909268dc   Jiri Slaby   mac80211: pid, fi...
306
307
308
309
310
311
312
313
  		for (j = 0; j < sband->n_bitrates - i; j++)
  			if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
  				     sband->bitrates[rinfo[j + 1].index].bitrate)) {
  				tmp = rinfo[j].index;
  				rinfo[j].index = rinfo[j + 1].index;
  				rinfo[j + 1].index = tmp;
  				rinfo[rinfo[j].index].rev_index = j;
  				rinfo[rinfo[j + 1].index].rev_index = j + 1;
3db1cd5c0   Rusty Russell   net: fix assignme...
314
  				s = true;
6909268dc   Jiri Slaby   mac80211: pid, fi...
315
316
317
318
  			}
  		if (!s)
  			break;
  	}
4b7679a56   Johannes Berg   mac80211: clean u...
319
  	spinfo->txrate_idx = rate_lowest_index(sband, sta);
ad0183759   Mattias Nissler   mac80211: add PID...
320
  }
4b7679a56   Johannes Berg   mac80211: clean u...
321
322
  static void *rate_control_pid_alloc(struct ieee80211_hw *hw,
  				    struct dentry *debugfsdir)
ad0183759   Mattias Nissler   mac80211: add PID...
323
324
  {
  	struct rc_pid_info *pinfo;
90d501d61   Stefano Brivio   rc80211-pid: add ...
325
  	struct rc_pid_rateinfo *rinfo;
8318d78a4   Johannes Berg   cfg80211 API for ...
326
  	struct ieee80211_supported_band *sband;
6909268dc   Jiri Slaby   mac80211: pid, fi...
327
  	int i, max_rates = 0;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
328
329
330
  #ifdef CONFIG_MAC80211_DEBUGFS
  	struct rc_pid_debugfs_entries *de;
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
331
332
  
  	pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
90d501d61   Stefano Brivio   rc80211-pid: add ...
333
334
  	if (!pinfo)
  		return NULL;
6909268dc   Jiri Slaby   mac80211: pid, fi...
335
336
  	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
  		sband = hw->wiphy->bands[i];
621ad7c96   John W. Linville   mac80211: avoid N...
337
  		if (sband && sband->n_bitrates > max_rates)
6909268dc   Jiri Slaby   mac80211: pid, fi...
338
339
340
341
  			max_rates = sband->n_bitrates;
  	}
  
  	rinfo = kmalloc(sizeof(*rinfo) * max_rates, GFP_ATOMIC);
90d501d61   Stefano Brivio   rc80211-pid: add ...
342
343
344
345
  	if (!rinfo) {
  		kfree(pinfo);
  		return NULL;
  	}
adeed4809   Mattias Nissler   rc80211_pid: Fix ...
346
347
348
349
350
351
352
353
354
355
356
  	pinfo->target = RC_PID_TARGET_PF;
  	pinfo->sampling_period = RC_PID_INTERVAL;
  	pinfo->coeff_p = RC_PID_COEFF_P;
  	pinfo->coeff_i = RC_PID_COEFF_I;
  	pinfo->coeff_d = RC_PID_COEFF_D;
  	pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
  	pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
  	pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
  	pinfo->norm_offset = RC_PID_NORM_OFFSET;
  	pinfo->rinfo = rinfo;
  	pinfo->oldrate = 0;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
357
358
  #ifdef CONFIG_MAC80211_DEBUGFS
  	de = &pinfo->dentries;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
359
  	de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR,
4b7679a56   Johannes Berg   mac80211: clean u...
360
  					debugfsdir, &pinfo->target);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
361
  	de->sampling_period = debugfs_create_u32("sampling_period",
4b7679a56   Johannes Berg   mac80211: clean u...
362
  						 S_IRUSR | S_IWUSR, debugfsdir,
1946b74ce   Mattias Nissler   rc80211-pid: expo...
363
364
  						 &pinfo->sampling_period);
  	de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR,
9902b1843   Tomas Winkler   mac80211: rc80211...
365
  					 debugfsdir, (u32 *)&pinfo->coeff_p);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
366
  	de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR,
9902b1843   Tomas Winkler   mac80211: rc80211...
367
  					 debugfsdir, (u32 *)&pinfo->coeff_i);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
368
  	de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR,
9902b1843   Tomas Winkler   mac80211: rc80211...
369
  					 debugfsdir, (u32 *)&pinfo->coeff_d);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
370
  	de->smoothing_shift = debugfs_create_u32("smoothing_shift",
4b7679a56   Johannes Berg   mac80211: clean u...
371
  						 S_IRUSR | S_IWUSR, debugfsdir,
1946b74ce   Mattias Nissler   rc80211-pid: expo...
372
373
  						 &pinfo->smoothing_shift);
  	de->sharpen_factor = debugfs_create_u32("sharpen_factor",
4b7679a56   Johannes Berg   mac80211: clean u...
374
  					       S_IRUSR | S_IWUSR, debugfsdir,
1946b74ce   Mattias Nissler   rc80211-pid: expo...
375
376
  					       &pinfo->sharpen_factor);
  	de->sharpen_duration = debugfs_create_u32("sharpen_duration",
4b7679a56   Johannes Berg   mac80211: clean u...
377
  						  S_IRUSR | S_IWUSR, debugfsdir,
1946b74ce   Mattias Nissler   rc80211-pid: expo...
378
379
  						  &pinfo->sharpen_duration);
  	de->norm_offset = debugfs_create_u32("norm_offset",
4b7679a56   Johannes Berg   mac80211: clean u...
380
  					     S_IRUSR | S_IWUSR, debugfsdir,
1946b74ce   Mattias Nissler   rc80211-pid: expo...
381
  					     &pinfo->norm_offset);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
382
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
383
384
385
386
387
388
  	return pinfo;
  }
  
  static void rate_control_pid_free(void *priv)
  {
  	struct rc_pid_info *pinfo = priv;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
389
390
  #ifdef CONFIG_MAC80211_DEBUGFS
  	struct rc_pid_debugfs_entries *de = &pinfo->dentries;
1946b74ce   Mattias Nissler   rc80211-pid: expo...
391
392
393
394
395
396
397
398
399
  	debugfs_remove(de->norm_offset);
  	debugfs_remove(de->sharpen_duration);
  	debugfs_remove(de->sharpen_factor);
  	debugfs_remove(de->smoothing_shift);
  	debugfs_remove(de->coeff_d);
  	debugfs_remove(de->coeff_i);
  	debugfs_remove(de->coeff_p);
  	debugfs_remove(de->sampling_period);
  	debugfs_remove(de->target);
1946b74ce   Mattias Nissler   rc80211-pid: expo...
400
  #endif
90d501d61   Stefano Brivio   rc80211-pid: add ...
401
  	kfree(pinfo->rinfo);
ad0183759   Mattias Nissler   mac80211: add PID...
402
403
  	kfree(pinfo);
  }
4b7679a56   Johannes Berg   mac80211: clean u...
404
405
  static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta,
  					gfp_t gfp)
ad0183759   Mattias Nissler   mac80211: add PID...
406
407
408
409
  {
  	struct rc_pid_sta_info *spinfo;
  
  	spinfo = kzalloc(sizeof(*spinfo), gfp);
12446c67f   Mattias Nissler   rc80211-pid: add ...
410
411
  	if (spinfo == NULL)
  		return NULL;
c09c7237e   Stefano Brivio   rc80211-pid: fix ...
412
  	spinfo->last_sample = jiffies;
12446c67f   Mattias Nissler   rc80211-pid: add ...
413
414
415
416
  #ifdef CONFIG_MAC80211_DEBUGFS
  	spin_lock_init(&spinfo->events.lock);
  	init_waitqueue_head(&spinfo->events.waitqueue);
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
417
418
419
  
  	return spinfo;
  }
4b7679a56   Johannes Berg   mac80211: clean u...
420
421
  static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta,
  				      void *priv_sta)
ad0183759   Mattias Nissler   mac80211: add PID...
422
  {
4b7679a56   Johannes Berg   mac80211: clean u...
423
  	kfree(priv_sta);
ad0183759   Mattias Nissler   mac80211: add PID...
424
  }
4b475898e   Johannes Berg   mac80211: better ...
425
  static struct rate_control_ops mac80211_rcpid = {
ad0183759   Mattias Nissler   mac80211: add PID...
426
427
428
429
  	.name = "pid",
  	.tx_status = rate_control_pid_tx_status,
  	.get_rate = rate_control_pid_get_rate,
  	.rate_init = rate_control_pid_rate_init,
ad0183759   Mattias Nissler   mac80211: add PID...
430
431
432
433
  	.alloc = rate_control_pid_alloc,
  	.free = rate_control_pid_free,
  	.alloc_sta = rate_control_pid_alloc_sta,
  	.free_sta = rate_control_pid_free_sta,
12446c67f   Mattias Nissler   rc80211-pid: add ...
434
435
436
437
  #ifdef CONFIG_MAC80211_DEBUGFS
  	.add_sta_debugfs = rate_control_pid_add_sta_debugfs,
  	.remove_sta_debugfs = rate_control_pid_remove_sta_debugfs,
  #endif
ad0183759   Mattias Nissler   mac80211: add PID...
438
  };
4b475898e   Johannes Berg   mac80211: better ...
439

4b475898e   Johannes Berg   mac80211: better ...
440
441
442
443
  int __init rc80211_pid_init(void)
  {
  	return ieee80211_rate_control_register(&mac80211_rcpid);
  }
f0b9205cf   Johannes Berg   mac80211 rate con...
444
  void rc80211_pid_exit(void)
4b475898e   Johannes Berg   mac80211: better ...
445
446
447
  {
  	ieee80211_rate_control_unregister(&mac80211_rcpid);
  }