diff options
Diffstat (limited to 'net/mac80211/rc80211_pid.h')
-rw-r--r-- | net/mac80211/rc80211_pid.h | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h new file mode 100644 index 000000000000..5d0056c1513b --- /dev/null +++ b/net/mac80211/rc80211_pid.h | |||
@@ -0,0 +1,242 @@ | |||
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 | #ifndef RC80211_PID_H | ||
10 | #define RC80211_PID_H | ||
11 | |||
12 | /* Sampling period for measuring percentage of failed frames. */ | ||
13 | #define RC_PID_INTERVAL (HZ / 8) | ||
14 | |||
15 | /* Exponential averaging smoothness (used for I part of PID controller) */ | ||
16 | #define RC_PID_SMOOTHING_SHIFT 3 | ||
17 | #define RC_PID_SMOOTHING (1 << RC_PID_SMOOTHING_SHIFT) | ||
18 | |||
19 | /* Sharpening factor (used for D part of PID controller) */ | ||
20 | #define RC_PID_SHARPENING_FACTOR 0 | ||
21 | #define RC_PID_SHARPENING_DURATION 0 | ||
22 | |||
23 | /* Fixed point arithmetic shifting amount. */ | ||
24 | #define RC_PID_ARITH_SHIFT 8 | ||
25 | |||
26 | /* Fixed point arithmetic factor. */ | ||
27 | #define RC_PID_ARITH_FACTOR (1 << RC_PID_ARITH_SHIFT) | ||
28 | |||
29 | /* Proportional PID component coefficient. */ | ||
30 | #define RC_PID_COEFF_P 15 | ||
31 | /* Integral PID component coefficient. */ | ||
32 | #define RC_PID_COEFF_I 9 | ||
33 | /* Derivative PID component coefficient. */ | ||
34 | #define RC_PID_COEFF_D 15 | ||
35 | |||
36 | /* Target failed frames rate for the PID controller. NB: This effectively gives | ||
37 | * maximum failed frames percentage we're willing to accept. If the wireless | ||
38 | * link quality is good, the controller will fail to adjust failed frames | ||
39 | * percentage to the target. This is intentional. | ||
40 | */ | ||
41 | #define RC_PID_TARGET_PF (11 << RC_PID_ARITH_SHIFT) | ||
42 | |||
43 | /* Rate behaviour normalization quantity over time. */ | ||
44 | #define RC_PID_NORM_OFFSET 3 | ||
45 | |||
46 | /* Push high rates right after loading. */ | ||
47 | #define RC_PID_FAST_START 0 | ||
48 | |||
49 | /* Arithmetic right shift for positive and negative values for ISO C. */ | ||
50 | #define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \ | ||
51 | (x) < 0 ? -((-(x)) >> (y)) : (x) >> (y) | ||
52 | |||
53 | enum rc_pid_event_type { | ||
54 | RC_PID_EVENT_TYPE_TX_STATUS, | ||
55 | RC_PID_EVENT_TYPE_RATE_CHANGE, | ||
56 | RC_PID_EVENT_TYPE_TX_RATE, | ||
57 | RC_PID_EVENT_TYPE_PF_SAMPLE, | ||
58 | }; | ||
59 | |||
60 | union rc_pid_event_data { | ||
61 | /* RC_PID_EVENT_TX_STATUS */ | ||
62 | struct { | ||
63 | struct ieee80211_tx_status tx_status; | ||
64 | }; | ||
65 | /* RC_PID_EVENT_TYPE_RATE_CHANGE */ | ||
66 | /* RC_PID_EVENT_TYPE_TX_RATE */ | ||
67 | struct { | ||
68 | int index; | ||
69 | int rate; | ||
70 | }; | ||
71 | /* RC_PID_EVENT_TYPE_PF_SAMPLE */ | ||
72 | struct { | ||
73 | s32 pf_sample; | ||
74 | s32 prop_err; | ||
75 | s32 int_err; | ||
76 | s32 der_err; | ||
77 | }; | ||
78 | }; | ||
79 | |||
80 | struct rc_pid_event { | ||
81 | /* The time when the event occured */ | ||
82 | unsigned long timestamp; | ||
83 | |||
84 | /* Event ID number */ | ||
85 | unsigned int id; | ||
86 | |||
87 | /* Type of event */ | ||
88 | enum rc_pid_event_type type; | ||
89 | |||
90 | /* type specific data */ | ||
91 | union rc_pid_event_data data; | ||
92 | }; | ||
93 | |||
94 | /* Size of the event ring buffer. */ | ||
95 | #define RC_PID_EVENT_RING_SIZE 32 | ||
96 | |||
97 | struct rc_pid_event_buffer { | ||
98 | /* Counter that generates event IDs */ | ||
99 | unsigned int ev_count; | ||
100 | |||
101 | /* Ring buffer of events */ | ||
102 | struct rc_pid_event ring[RC_PID_EVENT_RING_SIZE]; | ||
103 | |||
104 | /* Index to the entry in events_buf to be reused */ | ||
105 | unsigned int next_entry; | ||
106 | |||
107 | /* Lock that guards against concurrent access to this buffer struct */ | ||
108 | spinlock_t lock; | ||
109 | |||
110 | /* Wait queue for poll/select and blocking I/O */ | ||
111 | wait_queue_head_t waitqueue; | ||
112 | }; | ||
113 | |||
114 | struct rc_pid_events_file_info { | ||
115 | /* The event buffer we read */ | ||
116 | struct rc_pid_event_buffer *events; | ||
117 | |||
118 | /* The entry we have should read next */ | ||
119 | unsigned int next_entry; | ||
120 | }; | ||
121 | |||
122 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, | ||
123 | struct ieee80211_tx_status *stat); | ||
124 | |||
125 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, | ||
126 | int index, int rate); | ||
127 | |||
128 | void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf, | ||
129 | int index, int rate); | ||
130 | |||
131 | void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf, | ||
132 | s32 pf_sample, s32 prop_err, | ||
133 | s32 int_err, s32 der_err); | ||
134 | |||
135 | void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta, | ||
136 | struct dentry *dir); | ||
137 | |||
138 | void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta); | ||
139 | |||
140 | struct rc_pid_sta_info { | ||
141 | unsigned long last_change; | ||
142 | unsigned long last_sample; | ||
143 | |||
144 | u32 tx_num_failed; | ||
145 | u32 tx_num_xmit; | ||
146 | |||
147 | /* Average failed frames percentage error (i.e. actual vs. target | ||
148 | * percentage), scaled by RC_PID_SMOOTHING. This value is computed | ||
149 | * using using an exponential weighted average technique: | ||
150 | * | ||
151 | * (RC_PID_SMOOTHING - 1) * err_avg_old + err | ||
152 | * err_avg = ------------------------------------------ | ||
153 | * RC_PID_SMOOTHING | ||
154 | * | ||
155 | * where err_avg is the new approximation, err_avg_old the previous one | ||
156 | * and err is the error w.r.t. to the current failed frames percentage | ||
157 | * sample. Note that the bigger RC_PID_SMOOTHING the more weight is | ||
158 | * given to the previous estimate, resulting in smoother behavior (i.e. | ||
159 | * corresponding to a longer integration window). | ||
160 | * | ||
161 | * For computation, we actually don't use the above formula, but this | ||
162 | * one: | ||
163 | * | ||
164 | * err_avg_scaled = err_avg_old_scaled - err_avg_old + err | ||
165 | * | ||
166 | * where: | ||
167 | * err_avg_scaled = err * RC_PID_SMOOTHING | ||
168 | * err_avg_old_scaled = err_avg_old * RC_PID_SMOOTHING | ||
169 | * | ||
170 | * This avoids floating point numbers and the per_failed_old value can | ||
171 | * easily be obtained by shifting per_failed_old_scaled right by | ||
172 | * RC_PID_SMOOTHING_SHIFT. | ||
173 | */ | ||
174 | s32 err_avg_sc; | ||
175 | |||
176 | /* Last framed failes percentage sample. */ | ||
177 | u32 last_pf; | ||
178 | |||
179 | /* Sharpening needed. */ | ||
180 | u8 sharp_cnt; | ||
181 | |||
182 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
183 | /* Event buffer */ | ||
184 | struct rc_pid_event_buffer events; | ||
185 | |||
186 | /* Events debugfs file entry */ | ||
187 | struct dentry *events_entry; | ||
188 | #endif | ||
189 | }; | ||
190 | |||
191 | /* Algorithm parameters. We keep them on a per-algorithm approach, so they can | ||
192 | * be tuned individually for each interface. | ||
193 | */ | ||
194 | struct rc_pid_rateinfo { | ||
195 | |||
196 | /* Map sorted rates to rates in ieee80211_hw_mode. */ | ||
197 | int index; | ||
198 | |||
199 | /* Map rates in ieee80211_hw_mode to sorted rates. */ | ||
200 | int rev_index; | ||
201 | |||
202 | /* Did we do any measurement on this rate? */ | ||
203 | bool valid; | ||
204 | |||
205 | /* Comparison with the lowest rate. */ | ||
206 | int diff; | ||
207 | }; | ||
208 | |||
209 | struct rc_pid_info { | ||
210 | |||
211 | /* The failed frames percentage target. */ | ||
212 | unsigned int target; | ||
213 | |||
214 | /* Rate at which failed frames percentage is sampled in 0.001s. */ | ||
215 | unsigned int sampling_period; | ||
216 | |||
217 | /* P, I and D coefficients. */ | ||
218 | int coeff_p; | ||
219 | int coeff_i; | ||
220 | int coeff_d; | ||
221 | |||
222 | /* Exponential averaging shift. */ | ||
223 | unsigned int smoothing_shift; | ||
224 | |||
225 | /* Sharpening shift and duration. */ | ||
226 | unsigned int sharpen_shift; | ||
227 | unsigned int sharpen_duration; | ||
228 | |||
229 | /* Normalization offset. */ | ||
230 | unsigned int norm_offset; | ||
231 | |||
232 | /* Fast starst parameter. */ | ||
233 | unsigned int fast_start; | ||
234 | |||
235 | /* Rates information. */ | ||
236 | struct rc_pid_rateinfo *rinfo; | ||
237 | |||
238 | /* Index of the last used rate. */ | ||
239 | int oldrate; | ||
240 | }; | ||
241 | |||
242 | #endif /* RC80211_PID_H */ | ||