blob: 4ea7b97d1af1406737e94f22b85c7c2de0679d99 [file] [log] [blame]
Mattias Nissler12446c62007-12-19 01:27:18 +01001/*
2 * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de>
Stefano Brivioca5fbca2007-12-23 04:40:32 +01003 * Copyright 2007, Stefano Brivio <stefano.brivio@polimi.it>
Mattias Nissler12446c62007-12-19 01:27:18 +01004 *
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
Stefano Brivio1b507e72007-12-23 17:49:00 +010013/* Sampling period for measuring percentage of failed frames in ms. */
14#define RC_PID_INTERVAL 125
Mattias Nissler12446c62007-12-19 01:27:18 +010015
16/* Exponential averaging smoothness (used for I part of PID controller) */
Stefano Briviod4398102007-12-23 04:44:56 +010017#define RC_PID_SMOOTHING_SHIFT 3
18#define RC_PID_SMOOTHING (1 << RC_PID_SMOOTHING_SHIFT)
Mattias Nissler12446c62007-12-19 01:27:18 +010019
20/* Sharpening factor (used for D part of PID controller) */
Stefano Briviod4398102007-12-23 04:44:56 +010021#define RC_PID_SHARPENING_FACTOR 0
22#define RC_PID_SHARPENING_DURATION 0
Mattias Nissler12446c62007-12-19 01:27:18 +010023
24/* Fixed point arithmetic shifting amount. */
Stefano Briviod4398102007-12-23 04:44:56 +010025#define RC_PID_ARITH_SHIFT 8
Mattias Nissler12446c62007-12-19 01:27:18 +010026
27/* Fixed point arithmetic factor. */
Stefano Briviod4398102007-12-23 04:44:56 +010028#define RC_PID_ARITH_FACTOR (1 << RC_PID_ARITH_SHIFT)
Mattias Nissler12446c62007-12-19 01:27:18 +010029
30/* Proportional PID component coefficient. */
Stefano Briviod4398102007-12-23 04:44:56 +010031#define RC_PID_COEFF_P 15
Mattias Nissler12446c62007-12-19 01:27:18 +010032/* Integral PID component coefficient. */
Stefano Briviod4398102007-12-23 04:44:56 +010033#define RC_PID_COEFF_I 9
Mattias Nissler12446c62007-12-19 01:27:18 +010034/* Derivative PID component coefficient. */
Stefano Briviod4398102007-12-23 04:44:56 +010035#define RC_PID_COEFF_D 15
Mattias Nissler12446c62007-12-19 01:27:18 +010036
37/* Target failed frames rate for the PID controller. NB: This effectively gives
38 * maximum failed frames percentage we're willing to accept. If the wireless
39 * link quality is good, the controller will fail to adjust failed frames
40 * percentage to the target. This is intentional.
41 */
Stefano Briviod4398102007-12-23 04:44:56 +010042#define RC_PID_TARGET_PF 14
Mattias Nissler12446c62007-12-19 01:27:18 +010043
44/* Rate behaviour normalization quantity over time. */
Stefano Briviod4398102007-12-23 04:44:56 +010045#define RC_PID_NORM_OFFSET 3
Mattias Nissler12446c62007-12-19 01:27:18 +010046
47/* Push high rates right after loading. */
Stefano Briviod4398102007-12-23 04:44:56 +010048#define RC_PID_FAST_START 0
Mattias Nissler12446c62007-12-19 01:27:18 +010049
50/* Arithmetic right shift for positive and negative values for ISO C. */
51#define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \
52 (x) < 0 ? -((-(x)) >> (y)) : (x) >> (y)
53
54enum rc_pid_event_type {
55 RC_PID_EVENT_TYPE_TX_STATUS,
56 RC_PID_EVENT_TYPE_RATE_CHANGE,
57 RC_PID_EVENT_TYPE_TX_RATE,
58 RC_PID_EVENT_TYPE_PF_SAMPLE,
59};
60
61union rc_pid_event_data {
62 /* RC_PID_EVENT_TX_STATUS */
63 struct {
64 struct ieee80211_tx_status tx_status;
65 };
66 /* RC_PID_EVENT_TYPE_RATE_CHANGE */
67 /* RC_PID_EVENT_TYPE_TX_RATE */
68 struct {
69 int index;
70 int rate;
71 };
72 /* RC_PID_EVENT_TYPE_PF_SAMPLE */
73 struct {
74 s32 pf_sample;
75 s32 prop_err;
76 s32 int_err;
77 s32 der_err;
78 };
79};
80
81struct rc_pid_event {
82 /* The time when the event occured */
83 unsigned long timestamp;
84
85 /* Event ID number */
86 unsigned int id;
87
88 /* Type of event */
89 enum rc_pid_event_type type;
90
91 /* type specific data */
92 union rc_pid_event_data data;
93};
94
95/* Size of the event ring buffer. */
96#define RC_PID_EVENT_RING_SIZE 32
97
98struct rc_pid_event_buffer {
99 /* Counter that generates event IDs */
100 unsigned int ev_count;
101
102 /* Ring buffer of events */
103 struct rc_pid_event ring[RC_PID_EVENT_RING_SIZE];
104
105 /* Index to the entry in events_buf to be reused */
106 unsigned int next_entry;
107
108 /* Lock that guards against concurrent access to this buffer struct */
109 spinlock_t lock;
110
111 /* Wait queue for poll/select and blocking I/O */
112 wait_queue_head_t waitqueue;
113};
114
115struct rc_pid_events_file_info {
116 /* The event buffer we read */
117 struct rc_pid_event_buffer *events;
118
119 /* The entry we have should read next */
120 unsigned int next_entry;
121};
122
Stefano Brivioca5fbca2007-12-23 04:40:32 +0100123/**
124 * struct rc_pid_debugfs_entries - tunable parameters
125 *
126 * Algorithm parameters, tunable via debugfs.
127 * @dir: the debugfs directory for a specific phy
128 * @target: target percentage for failed frames
129 * @sampling_period: error sampling interval in milliseconds
130 * @coeff_p: absolute value of the proportional coefficient
131 * @coeff_i: absolute value of the integral coefficient
132 * @coeff_d: absolute value of the derivative coefficient
133 * @smoothing_shift: absolute value of the integral smoothing factor (i.e.
134 * amount of smoothing introduced by the exponential moving average)
135 * @sharpen_factor: absolute value of the derivative sharpening factor (i.e.
136 * amount of emphasis given to the derivative term after low activity
137 * events)
138 * @sharpen_duration: duration of the sharpening effect after the detected low
139 * activity event, relative to sampling_period
140 * @norm_offset: amount of normalization periodically performed on the learnt
141 * rate behaviour values (lower means we should trust more what we learnt
142 * about behaviour of rates, higher means we should trust more the natural
143 * ordering of rates)
Stefano Brivioca5fbca2007-12-23 04:40:32 +0100144 */
Mattias Nissler1946b742007-12-20 13:27:26 +0100145struct rc_pid_debugfs_entries {
146 struct dentry *dir;
147 struct dentry *target;
148 struct dentry *sampling_period;
149 struct dentry *coeff_p;
150 struct dentry *coeff_i;
151 struct dentry *coeff_d;
152 struct dentry *smoothing_shift;
153 struct dentry *sharpen_factor;
154 struct dentry *sharpen_duration;
155 struct dentry *norm_offset;
Mattias Nissler1946b742007-12-20 13:27:26 +0100156};
157
Mattias Nissler12446c62007-12-19 01:27:18 +0100158void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
159 struct ieee80211_tx_status *stat);
160
161void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf,
162 int index, int rate);
163
164void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf,
165 int index, int rate);
166
167void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf,
168 s32 pf_sample, s32 prop_err,
169 s32 int_err, s32 der_err);
170
171void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
172 struct dentry *dir);
173
174void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta);
175
176struct rc_pid_sta_info {
177 unsigned long last_change;
178 unsigned long last_sample;
179
180 u32 tx_num_failed;
181 u32 tx_num_xmit;
182
183 /* Average failed frames percentage error (i.e. actual vs. target
184 * percentage), scaled by RC_PID_SMOOTHING. This value is computed
185 * using using an exponential weighted average technique:
186 *
187 * (RC_PID_SMOOTHING - 1) * err_avg_old + err
188 * err_avg = ------------------------------------------
189 * RC_PID_SMOOTHING
190 *
191 * where err_avg is the new approximation, err_avg_old the previous one
192 * and err is the error w.r.t. to the current failed frames percentage
193 * sample. Note that the bigger RC_PID_SMOOTHING the more weight is
194 * given to the previous estimate, resulting in smoother behavior (i.e.
195 * corresponding to a longer integration window).
196 *
197 * For computation, we actually don't use the above formula, but this
198 * one:
199 *
200 * err_avg_scaled = err_avg_old_scaled - err_avg_old + err
201 *
202 * where:
203 * err_avg_scaled = err * RC_PID_SMOOTHING
204 * err_avg_old_scaled = err_avg_old * RC_PID_SMOOTHING
205 *
206 * This avoids floating point numbers and the per_failed_old value can
207 * easily be obtained by shifting per_failed_old_scaled right by
208 * RC_PID_SMOOTHING_SHIFT.
209 */
210 s32 err_avg_sc;
211
212 /* Last framed failes percentage sample. */
213 u32 last_pf;
214
215 /* Sharpening needed. */
216 u8 sharp_cnt;
217
218#ifdef CONFIG_MAC80211_DEBUGFS
219 /* Event buffer */
220 struct rc_pid_event_buffer events;
221
222 /* Events debugfs file entry */
223 struct dentry *events_entry;
224#endif
225};
226
227/* Algorithm parameters. We keep them on a per-algorithm approach, so they can
228 * be tuned individually for each interface.
229 */
230struct rc_pid_rateinfo {
231
232 /* Map sorted rates to rates in ieee80211_hw_mode. */
233 int index;
234
235 /* Map rates in ieee80211_hw_mode to sorted rates. */
236 int rev_index;
237
238 /* Did we do any measurement on this rate? */
239 bool valid;
240
241 /* Comparison with the lowest rate. */
242 int diff;
243};
244
245struct rc_pid_info {
246
247 /* The failed frames percentage target. */
248 unsigned int target;
249
250 /* Rate at which failed frames percentage is sampled in 0.001s. */
251 unsigned int sampling_period;
252
253 /* P, I and D coefficients. */
254 int coeff_p;
255 int coeff_i;
256 int coeff_d;
257
258 /* Exponential averaging shift. */
259 unsigned int smoothing_shift;
260
Mattias Nissler1946b742007-12-20 13:27:26 +0100261 /* Sharpening factor and duration. */
262 unsigned int sharpen_factor;
Mattias Nissler12446c62007-12-19 01:27:18 +0100263 unsigned int sharpen_duration;
264
265 /* Normalization offset. */
266 unsigned int norm_offset;
267
Mattias Nissler12446c62007-12-19 01:27:18 +0100268 /* Rates information. */
269 struct rc_pid_rateinfo *rinfo;
270
271 /* Index of the last used rate. */
272 int oldrate;
Mattias Nissler1946b742007-12-20 13:27:26 +0100273
274#ifdef CONFIG_MAC80211_DEBUGFS
275 /* Debugfs entries created for the parameters above. */
276 struct rc_pid_debugfs_entries dentries;
277#endif
Mattias Nissler12446c62007-12-19 01:27:18 +0100278};
279
280#endif /* RC80211_PID_H */