aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-05-30 10:47:28 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-06-23 05:05:23 -0400
commit20edb50e593dca7522b4f3a95b801dbf99f24c52 (patch)
tree71637451c7436f89f4b9e15db94a6c425bf9a406 /net/mac80211
parent7171511eaec5bf23fb06078f59784a3a0626b38f (diff)
mac80211: remove PID rate control
Minstrel has long since proven its worth. Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Kconfig17
-rw-r--r--net/mac80211/Makefile5
-rw-r--r--net/mac80211/main.c7
-rw-r--r--net/mac80211/rate.h13
-rw-r--r--net/mac80211/rc80211_pid.h278
-rw-r--r--net/mac80211/rc80211_pid_algo.c478
-rw-r--r--net/mac80211/rc80211_pid_debugfs.c228
7 files changed, 0 insertions, 1026 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 97b5dcad5025..aeb6a483b3bc 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -19,14 +19,6 @@ if MAC80211 != n
19config MAC80211_HAS_RC 19config MAC80211_HAS_RC
20 bool 20 bool
21 21
22config MAC80211_RC_PID
23 bool "PID controller based rate control algorithm" if EXPERT
24 select MAC80211_HAS_RC
25 ---help---
26 This option enables a TX rate control algorithm for
27 mac80211 that uses a PID controller to select the TX
28 rate.
29
30config MAC80211_RC_MINSTREL 22config MAC80211_RC_MINSTREL
31 bool "Minstrel" if EXPERT 23 bool "Minstrel" if EXPERT
32 select MAC80211_HAS_RC 24 select MAC80211_HAS_RC
@@ -51,14 +43,6 @@ choice
51 overridden through the ieee80211_default_rc_algo module 43 overridden through the ieee80211_default_rc_algo module
52 parameter if different algorithms are available. 44 parameter if different algorithms are available.
53 45
54config MAC80211_RC_DEFAULT_PID
55 bool "PID controller based rate control algorithm"
56 depends on MAC80211_RC_PID
57 ---help---
58 Select the PID controller based rate control as the
59 default rate control algorithm. You should choose
60 this unless you know what you are doing.
61
62config MAC80211_RC_DEFAULT_MINSTREL 46config MAC80211_RC_DEFAULT_MINSTREL
63 bool "Minstrel" 47 bool "Minstrel"
64 depends on MAC80211_RC_MINSTREL 48 depends on MAC80211_RC_MINSTREL
@@ -72,7 +56,6 @@ config MAC80211_RC_DEFAULT
72 string 56 string
73 default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT 57 default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
74 default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL 58 default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
75 default "pid" if MAC80211_RC_DEFAULT_PID
76 default "" 59 default ""
77 60
78endif 61endif
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 1e46ffa69167..4409bf506594 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -47,17 +47,12 @@ mac80211-$(CONFIG_PM) += pm.o
47 47
48CFLAGS_trace.o := -I$(src) 48CFLAGS_trace.o := -I$(src)
49 49
50# objects for PID algorithm
51rc80211_pid-y := rc80211_pid_algo.o
52rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o
53
54rc80211_minstrel-y := rc80211_minstrel.o 50rc80211_minstrel-y := rc80211_minstrel.o
55rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o 51rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
56 52
57rc80211_minstrel_ht-y := rc80211_minstrel_ht.o 53rc80211_minstrel_ht-y := rc80211_minstrel_ht.o
58rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o 54rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o
59 55
60mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y)
61mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) 56mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
62mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y) 57mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
63 58
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d17c26d6e369..0512a5096f0f 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1187,18 +1187,12 @@ static int __init ieee80211_init(void)
1187 if (ret) 1187 if (ret)
1188 goto err_minstrel; 1188 goto err_minstrel;
1189 1189
1190 ret = rc80211_pid_init();
1191 if (ret)
1192 goto err_pid;
1193
1194 ret = ieee80211_iface_init(); 1190 ret = ieee80211_iface_init();
1195 if (ret) 1191 if (ret)
1196 goto err_netdev; 1192 goto err_netdev;
1197 1193
1198 return 0; 1194 return 0;
1199 err_netdev: 1195 err_netdev:
1200 rc80211_pid_exit();
1201 err_pid:
1202 rc80211_minstrel_ht_exit(); 1196 rc80211_minstrel_ht_exit();
1203 err_minstrel: 1197 err_minstrel:
1204 rc80211_minstrel_exit(); 1198 rc80211_minstrel_exit();
@@ -1208,7 +1202,6 @@ static int __init ieee80211_init(void)
1208 1202
1209static void __exit ieee80211_exit(void) 1203static void __exit ieee80211_exit(void)
1210{ 1204{
1211 rc80211_pid_exit();
1212 rc80211_minstrel_ht_exit(); 1205 rc80211_minstrel_ht_exit();
1213 rc80211_minstrel_exit(); 1206 rc80211_minstrel_exit();
1214 1207
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 9aa2a1190a86..18babe302832 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -143,19 +143,6 @@ void rate_control_deinitialize(struct ieee80211_local *local);
143 143
144 144
145/* Rate control algorithms */ 145/* Rate control algorithms */
146#ifdef CONFIG_MAC80211_RC_PID
147int rc80211_pid_init(void);
148void rc80211_pid_exit(void);
149#else
150static inline int rc80211_pid_init(void)
151{
152 return 0;
153}
154static inline void rc80211_pid_exit(void)
155{
156}
157#endif
158
159#ifdef CONFIG_MAC80211_RC_MINSTREL 146#ifdef CONFIG_MAC80211_RC_MINSTREL
160int rc80211_minstrel_init(void); 147int rc80211_minstrel_init(void);
161void rc80211_minstrel_exit(void); 148void rc80211_minstrel_exit(void);
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h
deleted file mode 100644
index 19111c7bf454..000000000000
--- a/net/mac80211/rc80211_pid.h
+++ /dev/null
@@ -1,278 +0,0 @@
1/*
2 * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de>
3 * Copyright 2007, Stefano Brivio <stefano.brivio@polimi.it>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#ifndef RC80211_PID_H
11#define RC80211_PID_H
12
13/* Sampling period for measuring percentage of failed frames in ms. */
14#define RC_PID_INTERVAL 125
15
16/* Exponential averaging smoothness (used for I part of PID controller) */
17#define RC_PID_SMOOTHING_SHIFT 3
18#define RC_PID_SMOOTHING (1 << RC_PID_SMOOTHING_SHIFT)
19
20/* Sharpening factor (used for D part of PID controller) */
21#define RC_PID_SHARPENING_FACTOR 0
22#define RC_PID_SHARPENING_DURATION 0
23
24/* Fixed point arithmetic shifting amount. */
25#define RC_PID_ARITH_SHIFT 8
26
27/* Proportional PID component coefficient. */
28#define RC_PID_COEFF_P 15
29/* Integral PID component coefficient. */
30#define RC_PID_COEFF_I 9
31/* Derivative PID component coefficient. */
32#define RC_PID_COEFF_D 15
33
34/* Target failed frames rate for the PID controller. NB: This effectively gives
35 * maximum failed frames percentage we're willing to accept. If the wireless
36 * link quality is good, the controller will fail to adjust failed frames
37 * percentage to the target. This is intentional.
38 */
39#define RC_PID_TARGET_PF 14
40
41/* Rate behaviour normalization quantity over time. */
42#define RC_PID_NORM_OFFSET 3
43
44/* Push high rates right after loading. */
45#define RC_PID_FAST_START 0
46
47/* Arithmetic right shift for positive and negative values for ISO C. */
48#define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \
49 ((x) < 0 ? -((-(x)) >> (y)) : (x) >> (y))
50
51enum rc_pid_event_type {
52 RC_PID_EVENT_TYPE_TX_STATUS,
53 RC_PID_EVENT_TYPE_RATE_CHANGE,
54 RC_PID_EVENT_TYPE_TX_RATE,
55 RC_PID_EVENT_TYPE_PF_SAMPLE,
56};
57
58union rc_pid_event_data {
59 /* RC_PID_EVENT_TX_STATUS */
60 struct {
61 u32 flags;
62 struct ieee80211_tx_info tx_status;
63 };
64 /* RC_PID_EVENT_TYPE_RATE_CHANGE */
65 /* RC_PID_EVENT_TYPE_TX_RATE */
66 struct {
67 int index;
68 int rate;
69 };
70 /* RC_PID_EVENT_TYPE_PF_SAMPLE */
71 struct {
72 s32 pf_sample;
73 s32 prop_err;
74 s32 int_err;
75 s32 der_err;
76 };
77};
78
79struct rc_pid_event {
80 /* The time when the event occurred */
81 unsigned long timestamp;
82
83 /* Event ID number */
84 unsigned int id;
85
86 /* Type of event */
87 enum rc_pid_event_type type;
88
89 /* type specific data */
90 union rc_pid_event_data data;
91};
92
93/* Size of the event ring buffer. */
94#define RC_PID_EVENT_RING_SIZE 32
95
96struct rc_pid_event_buffer {
97 /* Counter that generates event IDs */
98 unsigned int ev_count;
99
100 /* Ring buffer of events */
101 struct rc_pid_event ring[RC_PID_EVENT_RING_SIZE];
102
103 /* Index to the entry in events_buf to be reused */
104 unsigned int next_entry;
105
106 /* Lock that guards against concurrent access to this buffer struct */
107 spinlock_t lock;
108
109 /* Wait queue for poll/select and blocking I/O */
110 wait_queue_head_t waitqueue;
111};
112
113struct rc_pid_events_file_info {
114 /* The event buffer we read */
115 struct rc_pid_event_buffer *events;
116
117 /* The entry we have should read next */
118 unsigned int next_entry;
119};
120
121/**
122 * struct rc_pid_debugfs_entries - tunable parameters
123 *
124 * Algorithm parameters, tunable via debugfs.
125 * @target: target percentage for failed frames
126 * @sampling_period: error sampling interval in milliseconds
127 * @coeff_p: absolute value of the proportional coefficient
128 * @coeff_i: absolute value of the integral coefficient
129 * @coeff_d: absolute value of the derivative coefficient
130 * @smoothing_shift: absolute value of the integral smoothing factor (i.e.
131 * amount of smoothing introduced by the exponential moving average)
132 * @sharpen_factor: absolute value of the derivative sharpening factor (i.e.
133 * amount of emphasis given to the derivative term after low activity
134 * events)
135 * @sharpen_duration: duration of the sharpening effect after the detected low
136 * activity event, relative to sampling_period
137 * @norm_offset: amount of normalization periodically performed on the learnt
138 * rate behaviour values (lower means we should trust more what we learnt
139 * about behaviour of rates, higher means we should trust more the natural
140 * ordering of rates)
141 */
142struct rc_pid_debugfs_entries {
143 struct dentry *target;
144 struct dentry *sampling_period;
145 struct dentry *coeff_p;
146 struct dentry *coeff_i;
147 struct dentry *coeff_d;
148 struct dentry *smoothing_shift;
149 struct dentry *sharpen_factor;
150 struct dentry *sharpen_duration;
151 struct dentry *norm_offset;
152};
153
154void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
155 struct ieee80211_tx_info *stat);
156
157void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf,
158 int index, int rate);
159
160void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf,
161 int index, int rate);
162
163void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf,
164 s32 pf_sample, s32 prop_err,
165 s32 int_err, s32 der_err);
166
167void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
168 struct dentry *dir);
169
170void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta);
171
172struct rc_pid_sta_info {
173 unsigned long last_change;
174 unsigned long last_sample;
175
176 u32 tx_num_failed;
177 u32 tx_num_xmit;
178
179 int txrate_idx;
180
181 /* Average failed frames percentage error (i.e. actual vs. target
182 * percentage), scaled by RC_PID_SMOOTHING. This value is computed
183 * using using an exponential weighted average technique:
184 *
185 * (RC_PID_SMOOTHING - 1) * err_avg_old + err
186 * err_avg = ------------------------------------------
187 * RC_PID_SMOOTHING
188 *
189 * where err_avg is the new approximation, err_avg_old the previous one
190 * and err is the error w.r.t. to the current failed frames percentage
191 * sample. Note that the bigger RC_PID_SMOOTHING the more weight is
192 * given to the previous estimate, resulting in smoother behavior (i.e.
193 * corresponding to a longer integration window).
194 *
195 * For computation, we actually don't use the above formula, but this
196 * one:
197 *
198 * err_avg_scaled = err_avg_old_scaled - err_avg_old + err
199 *
200 * where:
201 * err_avg_scaled = err * RC_PID_SMOOTHING
202 * err_avg_old_scaled = err_avg_old * RC_PID_SMOOTHING
203 *
204 * This avoids floating point numbers and the per_failed_old value can
205 * easily be obtained by shifting per_failed_old_scaled right by
206 * RC_PID_SMOOTHING_SHIFT.
207 */
208 s32 err_avg_sc;
209
210 /* Last framed failes percentage sample. */
211 u32 last_pf;
212
213 /* Sharpening needed. */
214 u8 sharp_cnt;
215
216#ifdef CONFIG_MAC80211_DEBUGFS
217 /* Event buffer */
218 struct rc_pid_event_buffer events;
219
220 /* Events debugfs file entry */
221 struct dentry *events_entry;
222#endif
223};
224
225/* Algorithm parameters. We keep them on a per-algorithm approach, so they can
226 * be tuned individually for each interface.
227 */
228struct rc_pid_rateinfo {
229
230 /* Map sorted rates to rates in ieee80211_hw_mode. */
231 int index;
232
233 /* Map rates in ieee80211_hw_mode to sorted rates. */
234 int rev_index;
235
236 /* Did we do any measurement on this rate? */
237 bool valid;
238
239 /* Comparison with the lowest rate. */
240 int diff;
241};
242
243struct rc_pid_info {
244
245 /* The failed frames percentage target. */
246 unsigned int target;
247
248 /* Rate at which failed frames percentage is sampled in 0.001s. */
249 unsigned int sampling_period;
250
251 /* P, I and D coefficients. */
252 int coeff_p;
253 int coeff_i;
254 int coeff_d;
255
256 /* Exponential averaging shift. */
257 unsigned int smoothing_shift;
258
259 /* Sharpening factor and duration. */
260 unsigned int sharpen_factor;
261 unsigned int sharpen_duration;
262
263 /* Normalization offset. */
264 unsigned int norm_offset;
265
266 /* Rates information. */
267 struct rc_pid_rateinfo *rinfo;
268
269 /* Index of the last used rate. */
270 int oldrate;
271
272#ifdef CONFIG_MAC80211_DEBUGFS
273 /* Debugfs entries created for the parameters above. */
274 struct rc_pid_debugfs_entries dentries;
275#endif
276};
277
278#endif /* RC80211_PID_H */
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
deleted file mode 100644
index d0da2a70fe68..000000000000
--- a/net/mac80211/rc80211_pid_algo.c
+++ /dev/null
@@ -1,478 +0,0 @@
1/*
2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005, Devicescape Software, Inc.
4 * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de>
5 * Copyright 2007-2008, Stefano Brivio <stefano.brivio@polimi.it>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/netdevice.h>
13#include <linux/types.h>
14#include <linux/skbuff.h>
15#include <linux/debugfs.h>
16#include <linux/slab.h>
17#include <net/mac80211.h>
18#include "rate.h"
19#include "mesh.h"
20#include "rc80211_pid.h"
21
22
23/* This is an implementation of a TX rate control algorithm that uses a PID
24 * controller. Given a target failed frames rate, the controller decides about
25 * TX rate changes to meet the target failed frames rate.
26 *
27 * The controller basically computes the following:
28 *
29 * adj = CP * err + CI * err_avg + CD * (err - last_err) * (1 + sharpening)
30 *
31 * where
32 * adj adjustment value that is used to switch TX rate (see below)
33 * err current error: target vs. current failed frames percentage
34 * last_err last error
35 * err_avg average (i.e. poor man's integral) of recent errors
36 * sharpening non-zero when fast response is needed (i.e. right after
37 * association or no frames sent for a long time), heading
38 * to zero over time
39 * CP Proportional coefficient
40 * CI Integral coefficient
41 * CD Derivative coefficient
42 *
43 * CP, CI, CD are subject to careful tuning.
44 *
45 * The integral component uses a exponential moving average approach instead of
46 * an actual sliding window. The advantage is that we don't need to keep an
47 * array of the last N error values and computation is easier.
48 *
49 * Once we have the adj value, we map it to a rate by means of a learning
50 * algorithm. This algorithm keeps the state of the percentual failed frames
51 * difference between rates. The behaviour of the lowest available rate is kept
52 * as a reference value, and every time we switch between two rates, we compute
53 * the difference between the failed frames each rate exhibited. By doing so,
54 * we compare behaviours which different rates exhibited in adjacent timeslices,
55 * thus the comparison is minimally affected by external conditions. This
56 * difference gets propagated to the whole set of measurements, so that the
57 * reference is always the same. Periodically, we normalize this set so that
58 * recent events weigh the most. By comparing the adj value with this set, we
59 * avoid pejorative switches to lower rates and allow for switches to higher
60 * rates if they behaved well.
61 *
62 * Note that for the computations we use a fixed-point representation to avoid
63 * floating point arithmetic. Hence, all values are shifted left by
64 * RC_PID_ARITH_SHIFT.
65 */
66
67
68/* Adjust the rate while ensuring that we won't switch to a lower rate if it
69 * exhibited a worse failed frames behaviour and we'll choose the highest rate
70 * whose failed frames behaviour is not worse than the one of the original rate
71 * target. While at it, check that the new rate is valid. */
72static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband,
73 struct ieee80211_sta *sta,
74 struct rc_pid_sta_info *spinfo, int adj,
75 struct rc_pid_rateinfo *rinfo)
76{
77 int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
78 int cur = spinfo->txrate_idx;
79
80 band = sband->band;
81 n_bitrates = sband->n_bitrates;
82
83 /* Map passed arguments to sorted values. */
84 cur_sorted = rinfo[cur].rev_index;
85 new_sorted = cur_sorted + adj;
86
87 /* Check limits. */
88 if (new_sorted < 0)
89 new_sorted = rinfo[0].rev_index;
90 else if (new_sorted >= n_bitrates)
91 new_sorted = rinfo[n_bitrates - 1].rev_index;
92
93 tmp = new_sorted;
94
95 if (adj < 0) {
96 /* Ensure that the rate decrease isn't disadvantageous. */
97 for (probe = cur_sorted; probe >= new_sorted; probe--)
98 if (rinfo[probe].diff <= rinfo[cur_sorted].diff &&
99 rate_supported(sta, band, rinfo[probe].index))
100 tmp = probe;
101 } else {
102 /* Look for rate increase with zero (or below) cost. */
103 for (probe = new_sorted + 1; probe < n_bitrates; probe++)
104 if (rinfo[probe].diff <= rinfo[new_sorted].diff &&
105 rate_supported(sta, band, rinfo[probe].index))
106 tmp = probe;
107 }
108
109 /* Fit the rate found to the nearest supported rate. */
110 do {
111 if (rate_supported(sta, band, rinfo[tmp].index)) {
112 spinfo->txrate_idx = rinfo[tmp].index;
113 break;
114 }
115 if (adj < 0)
116 tmp--;
117 else
118 tmp++;
119 } while (tmp < n_bitrates && tmp >= 0);
120
121#ifdef CONFIG_MAC80211_DEBUGFS
122 rate_control_pid_event_rate_change(&spinfo->events,
123 spinfo->txrate_idx,
124 sband->bitrates[spinfo->txrate_idx].bitrate);
125#endif
126}
127
128/* Normalize the failed frames per-rate differences. */
129static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l)
130{
131 int i, norm_offset = pinfo->norm_offset;
132 struct rc_pid_rateinfo *r = pinfo->rinfo;
133
134 if (r[0].diff > norm_offset)
135 r[0].diff -= norm_offset;
136 else if (r[0].diff < -norm_offset)
137 r[0].diff += norm_offset;
138 for (i = 0; i < l - 1; i++)
139 if (r[i + 1].diff > r[i].diff + norm_offset)
140 r[i + 1].diff -= norm_offset;
141 else if (r[i + 1].diff <= r[i].diff)
142 r[i + 1].diff += norm_offset;
143}
144
145static void rate_control_pid_sample(struct rc_pid_info *pinfo,
146 struct ieee80211_supported_band *sband,
147 struct ieee80211_sta *sta,
148 struct rc_pid_sta_info *spinfo)
149{
150 struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
151 u32 pf;
152 s32 err_avg;
153 u32 err_prop;
154 u32 err_int;
155 u32 err_der;
156 int adj, i, j, tmp;
157 unsigned long period;
158
159 /* In case nothing happened during the previous control interval, turn
160 * the sharpening factor on. */
161 period = msecs_to_jiffies(pinfo->sampling_period);
162 if (jiffies - spinfo->last_sample > 2 * period)
163 spinfo->sharp_cnt = pinfo->sharpen_duration;
164
165 spinfo->last_sample = jiffies;
166
167 /* This should never happen, but in case, we assume the old sample is
168 * still a good measurement and copy it. */
169 if (unlikely(spinfo->tx_num_xmit == 0))
170 pf = spinfo->last_pf;
171 else
172 pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
173
174 spinfo->tx_num_xmit = 0;
175 spinfo->tx_num_failed = 0;
176
177 /* If we just switched rate, update the rate behaviour info. */
178 if (pinfo->oldrate != spinfo->txrate_idx) {
179
180 i = rinfo[pinfo->oldrate].rev_index;
181 j = rinfo[spinfo->txrate_idx].rev_index;
182
183 tmp = (pf - spinfo->last_pf);
184 tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT);
185
186 rinfo[j].diff = rinfo[i].diff + tmp;
187 pinfo->oldrate = spinfo->txrate_idx;
188 }
189 rate_control_pid_normalize(pinfo, sband->n_bitrates);
190
191 /* Compute the proportional, integral and derivative errors. */
192 err_prop = (pinfo->target - pf) << RC_PID_ARITH_SHIFT;
193
194 err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift;
195 spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop;
196 err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift;
197
198 err_der = (pf - spinfo->last_pf) *
199 (1 + pinfo->sharpen_factor * spinfo->sharp_cnt);
200 spinfo->last_pf = pf;
201 if (spinfo->sharp_cnt)
202 spinfo->sharp_cnt--;
203
204#ifdef CONFIG_MAC80211_DEBUGFS
205 rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int,
206 err_der);
207#endif
208
209 /* Compute the controller output. */
210 adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i
211 + err_der * pinfo->coeff_d);
212 adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT);
213
214 /* Change rate. */
215 if (adj)
216 rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo);
217}
218
219static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband,
220 struct ieee80211_sta *sta, void *priv_sta,
221 struct sk_buff *skb)
222{
223 struct rc_pid_info *pinfo = priv;
224 struct rc_pid_sta_info *spinfo = priv_sta;
225 unsigned long period;
226 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
227
228 if (!spinfo)
229 return;
230
231 /* Ignore all frames that were sent with a different rate than the rate
232 * we currently advise mac80211 to use. */
233 if (info->status.rates[0].idx != spinfo->txrate_idx)
234 return;
235
236 spinfo->tx_num_xmit++;
237
238#ifdef CONFIG_MAC80211_DEBUGFS
239 rate_control_pid_event_tx_status(&spinfo->events, info);
240#endif
241
242 /* We count frames that totally failed to be transmitted as two bad
243 * frames, those that made it out but had some retries as one good and
244 * one bad frame. */
245 if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
246 spinfo->tx_num_failed += 2;
247 spinfo->tx_num_xmit++;
248 } else if (info->status.rates[0].count > 1) {
249 spinfo->tx_num_failed++;
250 spinfo->tx_num_xmit++;
251 }
252
253 /* Update PID controller state. */
254 period = msecs_to_jiffies(pinfo->sampling_period);
255 if (time_after(jiffies, spinfo->last_sample + period))
256 rate_control_pid_sample(pinfo, sband, sta, spinfo);
257}
258
259static void
260rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta,
261 void *priv_sta,
262 struct ieee80211_tx_rate_control *txrc)
263{
264 struct sk_buff *skb = txrc->skb;
265 struct ieee80211_supported_band *sband = txrc->sband;
266 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
267 struct rc_pid_sta_info *spinfo = priv_sta;
268 int rateidx;
269
270 if (txrc->rts)
271 info->control.rates[0].count =
272 txrc->hw->conf.long_frame_max_tx_count;
273 else
274 info->control.rates[0].count =
275 txrc->hw->conf.short_frame_max_tx_count;
276
277 /* Send management frames and NO_ACK data using lowest rate. */
278 if (rate_control_send_low(sta, priv_sta, txrc))
279 return;
280
281 rateidx = spinfo->txrate_idx;
282
283 if (rateidx >= sband->n_bitrates)
284 rateidx = sband->n_bitrates - 1;
285
286 info->control.rates[0].idx = rateidx;
287
288#ifdef CONFIG_MAC80211_DEBUGFS
289 rate_control_pid_event_tx_rate(&spinfo->events,
290 rateidx, sband->bitrates[rateidx].bitrate);
291#endif
292}
293
294static void
295rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
296 struct cfg80211_chan_def *chandef,
297 struct ieee80211_sta *sta, void *priv_sta)
298{
299 struct rc_pid_sta_info *spinfo = priv_sta;
300 struct rc_pid_info *pinfo = priv;
301 struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
302 int i, j, tmp;
303 bool s;
304
305 /* TODO: This routine should consider using RSSI from previous packets
306 * as we need to have IEEE 802.1X auth succeed immediately after assoc..
307 * Until that method is implemented, we will use the lowest supported
308 * rate as a workaround. */
309
310 /* Sort the rates. This is optimized for the most common case (i.e.
311 * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
312 * mapping too. */
313 for (i = 0; i < sband->n_bitrates; i++) {
314 rinfo[i].index = i;
315 rinfo[i].rev_index = i;
316 if (RC_PID_FAST_START)
317 rinfo[i].diff = 0;
318 else
319 rinfo[i].diff = i * pinfo->norm_offset;
320 }
321 for (i = 1; i < sband->n_bitrates; i++) {
322 s = false;
323 for (j = 0; j < sband->n_bitrates - i; j++)
324 if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
325 sband->bitrates[rinfo[j + 1].index].bitrate)) {
326 tmp = rinfo[j].index;
327 rinfo[j].index = rinfo[j + 1].index;
328 rinfo[j + 1].index = tmp;
329 rinfo[rinfo[j].index].rev_index = j;
330 rinfo[rinfo[j + 1].index].rev_index = j + 1;
331 s = true;
332 }
333 if (!s)
334 break;
335 }
336
337 spinfo->txrate_idx = rate_lowest_index(sband, sta);
338}
339
340static void *rate_control_pid_alloc(struct ieee80211_hw *hw,
341 struct dentry *debugfsdir)
342{
343 struct rc_pid_info *pinfo;
344 struct rc_pid_rateinfo *rinfo;
345 struct ieee80211_supported_band *sband;
346 int i, max_rates = 0;
347#ifdef CONFIG_MAC80211_DEBUGFS
348 struct rc_pid_debugfs_entries *de;
349#endif
350
351 pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
352 if (!pinfo)
353 return NULL;
354
355 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
356 sband = hw->wiphy->bands[i];
357 if (sband && sband->n_bitrates > max_rates)
358 max_rates = sband->n_bitrates;
359 }
360
361 rinfo = kmalloc(sizeof(*rinfo) * max_rates, GFP_ATOMIC);
362 if (!rinfo) {
363 kfree(pinfo);
364 return NULL;
365 }
366
367 pinfo->target = RC_PID_TARGET_PF;
368 pinfo->sampling_period = RC_PID_INTERVAL;
369 pinfo->coeff_p = RC_PID_COEFF_P;
370 pinfo->coeff_i = RC_PID_COEFF_I;
371 pinfo->coeff_d = RC_PID_COEFF_D;
372 pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
373 pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
374 pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
375 pinfo->norm_offset = RC_PID_NORM_OFFSET;
376 pinfo->rinfo = rinfo;
377 pinfo->oldrate = 0;
378
379#ifdef CONFIG_MAC80211_DEBUGFS
380 de = &pinfo->dentries;
381 de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR,
382 debugfsdir, &pinfo->target);
383 de->sampling_period = debugfs_create_u32("sampling_period",
384 S_IRUSR | S_IWUSR, debugfsdir,
385 &pinfo->sampling_period);
386 de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR,
387 debugfsdir, (u32 *)&pinfo->coeff_p);
388 de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR,
389 debugfsdir, (u32 *)&pinfo->coeff_i);
390 de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR,
391 debugfsdir, (u32 *)&pinfo->coeff_d);
392 de->smoothing_shift = debugfs_create_u32("smoothing_shift",
393 S_IRUSR | S_IWUSR, debugfsdir,
394 &pinfo->smoothing_shift);
395 de->sharpen_factor = debugfs_create_u32("sharpen_factor",
396 S_IRUSR | S_IWUSR, debugfsdir,
397 &pinfo->sharpen_factor);
398 de->sharpen_duration = debugfs_create_u32("sharpen_duration",
399 S_IRUSR | S_IWUSR, debugfsdir,
400 &pinfo->sharpen_duration);
401 de->norm_offset = debugfs_create_u32("norm_offset",
402 S_IRUSR | S_IWUSR, debugfsdir,
403 &pinfo->norm_offset);
404#endif
405
406 return pinfo;
407}
408
409static void rate_control_pid_free(void *priv)
410{
411 struct rc_pid_info *pinfo = priv;
412#ifdef CONFIG_MAC80211_DEBUGFS
413 struct rc_pid_debugfs_entries *de = &pinfo->dentries;
414
415 debugfs_remove(de->norm_offset);
416 debugfs_remove(de->sharpen_duration);
417 debugfs_remove(de->sharpen_factor);
418 debugfs_remove(de->smoothing_shift);
419 debugfs_remove(de->coeff_d);
420 debugfs_remove(de->coeff_i);
421 debugfs_remove(de->coeff_p);
422 debugfs_remove(de->sampling_period);
423 debugfs_remove(de->target);
424#endif
425
426 kfree(pinfo->rinfo);
427 kfree(pinfo);
428}
429
430static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta,
431 gfp_t gfp)
432{
433 struct rc_pid_sta_info *spinfo;
434
435 spinfo = kzalloc(sizeof(*spinfo), gfp);
436 if (spinfo == NULL)
437 return NULL;
438
439 spinfo->last_sample = jiffies;
440
441#ifdef CONFIG_MAC80211_DEBUGFS
442 spin_lock_init(&spinfo->events.lock);
443 init_waitqueue_head(&spinfo->events.waitqueue);
444#endif
445
446 return spinfo;
447}
448
449static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta,
450 void *priv_sta)
451{
452 kfree(priv_sta);
453}
454
455static const struct rate_control_ops mac80211_rcpid = {
456 .name = "pid",
457 .tx_status = rate_control_pid_tx_status,
458 .get_rate = rate_control_pid_get_rate,
459 .rate_init = rate_control_pid_rate_init,
460 .alloc = rate_control_pid_alloc,
461 .free = rate_control_pid_free,
462 .alloc_sta = rate_control_pid_alloc_sta,
463 .free_sta = rate_control_pid_free_sta,
464#ifdef CONFIG_MAC80211_DEBUGFS
465 .add_sta_debugfs = rate_control_pid_add_sta_debugfs,
466 .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs,
467#endif
468};
469
470int __init rc80211_pid_init(void)
471{
472 return ieee80211_rate_control_register(&mac80211_rcpid);
473}
474
475void rc80211_pid_exit(void)
476{
477 ieee80211_rate_control_unregister(&mac80211_rcpid);
478}
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c
deleted file mode 100644
index 6ff134650a84..000000000000
--- a/net/mac80211/rc80211_pid_debugfs.c
+++ /dev/null
@@ -1,228 +0,0 @@
1/*
2 * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/sched.h>
10#include <linux/spinlock.h>
11#include <linux/poll.h>
12#include <linux/netdevice.h>
13#include <linux/types.h>
14#include <linux/skbuff.h>
15#include <linux/slab.h>
16#include <linux/export.h>
17
18#include <net/mac80211.h>
19#include "rate.h"
20
21#include "rc80211_pid.h"
22
23static void rate_control_pid_event(struct rc_pid_event_buffer *buf,
24 enum rc_pid_event_type type,
25 union rc_pid_event_data *data)
26{
27 struct rc_pid_event *ev;
28 unsigned long status;
29
30 spin_lock_irqsave(&buf->lock, status);
31 ev = &(buf->ring[buf->next_entry]);
32 buf->next_entry = (buf->next_entry + 1) % RC_PID_EVENT_RING_SIZE;
33
34 ev->timestamp = jiffies;
35 ev->id = buf->ev_count++;
36 ev->type = type;
37 ev->data = *data;
38
39 spin_unlock_irqrestore(&buf->lock, status);
40
41 wake_up_all(&buf->waitqueue);
42}
43
44void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
45 struct ieee80211_tx_info *stat)
46{
47 union rc_pid_event_data evd;
48
49 evd.flags = stat->flags;
50 memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info));
51 rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd);
52}
53
54void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf,
55 int index, int rate)
56{
57 union rc_pid_event_data evd;
58
59 evd.index = index;
60 evd.rate = rate;
61 rate_control_pid_event(buf, RC_PID_EVENT_TYPE_RATE_CHANGE, &evd);
62}
63
64void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf,
65 int index, int rate)
66{
67 union rc_pid_event_data evd;
68
69 evd.index = index;
70 evd.rate = rate;
71 rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_RATE, &evd);
72}
73
74void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf,
75 s32 pf_sample, s32 prop_err,
76 s32 int_err, s32 der_err)
77{
78 union rc_pid_event_data evd;
79
80 evd.pf_sample = pf_sample;
81 evd.prop_err = prop_err;
82 evd.int_err = int_err;
83 evd.der_err = der_err;
84 rate_control_pid_event(buf, RC_PID_EVENT_TYPE_PF_SAMPLE, &evd);
85}
86
87static int rate_control_pid_events_open(struct inode *inode, struct file *file)
88{
89 struct rc_pid_sta_info *sinfo = inode->i_private;
90 struct rc_pid_event_buffer *events = &sinfo->events;
91 struct rc_pid_events_file_info *file_info;
92 unsigned long status;
93
94 /* Allocate a state struct */
95 file_info = kmalloc(sizeof(*file_info), GFP_KERNEL);
96 if (file_info == NULL)
97 return -ENOMEM;
98
99 spin_lock_irqsave(&events->lock, status);
100
101 file_info->next_entry = events->next_entry;
102 file_info->events = events;
103
104 spin_unlock_irqrestore(&events->lock, status);
105
106 file->private_data = file_info;
107
108 return 0;
109}
110
111static int rate_control_pid_events_release(struct inode *inode,
112 struct file *file)
113{
114 struct rc_pid_events_file_info *file_info = file->private_data;
115
116 kfree(file_info);
117
118 return 0;
119}
120
121static unsigned int rate_control_pid_events_poll(struct file *file,
122 poll_table *wait)
123{
124 struct rc_pid_events_file_info *file_info = file->private_data;
125
126 poll_wait(file, &file_info->events->waitqueue, wait);
127
128 return POLLIN | POLLRDNORM;
129}
130
131#define RC_PID_PRINT_BUF_SIZE 64
132
133static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf,
134 size_t length, loff_t *offset)
135{
136 struct rc_pid_events_file_info *file_info = file->private_data;
137 struct rc_pid_event_buffer *events = file_info->events;
138 struct rc_pid_event *ev;
139 char pb[RC_PID_PRINT_BUF_SIZE];
140 int ret;
141 int p;
142 unsigned long status;
143
144 /* Check if there is something to read. */
145 if (events->next_entry == file_info->next_entry) {
146 if (file->f_flags & O_NONBLOCK)
147 return -EAGAIN;
148
149 /* Wait */
150 ret = wait_event_interruptible(events->waitqueue,
151 events->next_entry != file_info->next_entry);
152
153 if (ret)
154 return ret;
155 }
156
157 /* Write out one event per call. I don't care whether it's a little
158 * inefficient, this is debugging code anyway. */
159 spin_lock_irqsave(&events->lock, status);
160
161 /* Get an event */
162 ev = &(events->ring[file_info->next_entry]);
163 file_info->next_entry = (file_info->next_entry + 1) %
164 RC_PID_EVENT_RING_SIZE;
165
166 /* Print information about the event. Note that userspace needs to
167 * provide large enough buffers. */
168 length = length < RC_PID_PRINT_BUF_SIZE ?
169 length : RC_PID_PRINT_BUF_SIZE;
170 p = scnprintf(pb, length, "%u %lu ", ev->id, ev->timestamp);
171 switch (ev->type) {
172 case RC_PID_EVENT_TYPE_TX_STATUS:
173 p += scnprintf(pb + p, length - p, "tx_status %u %u",
174 !(ev->data.flags & IEEE80211_TX_STAT_ACK),
175 ev->data.tx_status.status.rates[0].idx);
176 break;
177 case RC_PID_EVENT_TYPE_RATE_CHANGE:
178 p += scnprintf(pb + p, length - p, "rate_change %d %d",
179 ev->data.index, ev->data.rate);
180 break;
181 case RC_PID_EVENT_TYPE_TX_RATE:
182 p += scnprintf(pb + p, length - p, "tx_rate %d %d",
183 ev->data.index, ev->data.rate);
184 break;
185 case RC_PID_EVENT_TYPE_PF_SAMPLE:
186 p += scnprintf(pb + p, length - p,
187 "pf_sample %d %d %d %d",
188 ev->data.pf_sample, ev->data.prop_err,
189 ev->data.int_err, ev->data.der_err);
190 break;
191 }
192 p += scnprintf(pb + p, length - p, "\n");
193
194 spin_unlock_irqrestore(&events->lock, status);
195
196 if (copy_to_user(buf, pb, p))
197 return -EFAULT;
198
199 return p;
200}
201
202#undef RC_PID_PRINT_BUF_SIZE
203
204static const struct file_operations rc_pid_fop_events = {
205 .owner = THIS_MODULE,
206 .read = rate_control_pid_events_read,
207 .poll = rate_control_pid_events_poll,
208 .open = rate_control_pid_events_open,
209 .release = rate_control_pid_events_release,
210 .llseek = noop_llseek,
211};
212
213void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
214 struct dentry *dir)
215{
216 struct rc_pid_sta_info *spinfo = priv_sta;
217
218 spinfo->events_entry = debugfs_create_file("rc_pid_events", S_IRUGO,
219 dir, spinfo,
220 &rc_pid_fop_events);
221}
222
223void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta)
224{
225 struct rc_pid_sta_info *spinfo = priv_sta;
226
227 debugfs_remove(spinfo->events_entry);
228}