| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> | 
| Stefano Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 3 | * Copyright 2007, Stefano Brivio <stefano.brivio@polimi.it> | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 |  | 
| Stefano Brivio | 1b507e7 | 2007-12-23 17:49:00 +0100 | [diff] [blame] | 13 | /* Sampling period for measuring percentage of failed frames in ms. */ | 
|  | 14 | #define RC_PID_INTERVAL			125 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 15 |  | 
|  | 16 | /* Exponential averaging smoothness (used for I part of PID controller) */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 17 | #define RC_PID_SMOOTHING_SHIFT		3 | 
|  | 18 | #define RC_PID_SMOOTHING		(1 << RC_PID_SMOOTHING_SHIFT) | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 19 |  | 
|  | 20 | /* Sharpening factor (used for D part of PID controller) */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 21 | #define RC_PID_SHARPENING_FACTOR	0 | 
|  | 22 | #define RC_PID_SHARPENING_DURATION	0 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 23 |  | 
|  | 24 | /* Fixed point arithmetic shifting amount. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 25 | #define RC_PID_ARITH_SHIFT		8 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 26 |  | 
|  | 27 | /* Fixed point arithmetic factor. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 28 | #define RC_PID_ARITH_FACTOR		(1 << RC_PID_ARITH_SHIFT) | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 29 |  | 
|  | 30 | /* Proportional PID component coefficient. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 31 | #define RC_PID_COEFF_P			15 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 32 | /* Integral PID component coefficient. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 33 | #define RC_PID_COEFF_I			9 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 34 | /* Derivative PID component coefficient. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 35 | #define RC_PID_COEFF_D			15 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 36 |  | 
|  | 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 Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 42 | #define RC_PID_TARGET_PF		14 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 43 |  | 
|  | 44 | /* Rate behaviour normalization quantity over time. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 45 | #define RC_PID_NORM_OFFSET		3 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 46 |  | 
|  | 47 | /* Push high rates right after loading. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 48 | #define RC_PID_FAST_START		0 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 49 |  | 
|  | 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 |  | 
|  | 54 | enum 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 |  | 
|  | 61 | union rc_pid_event_data { | 
|  | 62 | /* RC_PID_EVENT_TX_STATUS */ | 
|  | 63 | struct { | 
| Johannes Berg | e039fa4 | 2008-05-15 12:55:29 +0200 | [diff] [blame] | 64 | struct ieee80211_tx_info tx_status; | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 |  | 
|  | 81 | struct 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 |  | 
|  | 98 | struct 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 |  | 
|  | 115 | struct 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 Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 123 | /** | 
|  | 124 | * struct rc_pid_debugfs_entries - tunable parameters | 
|  | 125 | * | 
|  | 126 | * Algorithm parameters, tunable via debugfs. | 
| Stefano Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 127 | * @target: target percentage for failed frames | 
|  | 128 | * @sampling_period: error sampling interval in milliseconds | 
|  | 129 | * @coeff_p: absolute value of the proportional coefficient | 
|  | 130 | * @coeff_i: absolute value of the integral coefficient | 
|  | 131 | * @coeff_d: absolute value of the derivative coefficient | 
|  | 132 | * @smoothing_shift: absolute value of the integral smoothing factor (i.e. | 
|  | 133 | *	amount of smoothing introduced by the exponential moving average) | 
|  | 134 | * @sharpen_factor: absolute value of the derivative sharpening factor (i.e. | 
|  | 135 | *	amount of emphasis given to the derivative term after low activity | 
|  | 136 | *	events) | 
|  | 137 | * @sharpen_duration: duration of the sharpening effect after the detected low | 
|  | 138 | *	activity event, relative to sampling_period | 
|  | 139 | * @norm_offset: amount of normalization periodically performed on the learnt | 
|  | 140 | *	rate behaviour values (lower means we should trust more what we learnt | 
|  | 141 | *	about behaviour of rates, higher means we should trust more the natural | 
|  | 142 | *	ordering of rates) | 
| Stefano Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 143 | */ | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 144 | struct rc_pid_debugfs_entries { | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 145 | struct dentry *target; | 
|  | 146 | struct dentry *sampling_period; | 
|  | 147 | struct dentry *coeff_p; | 
|  | 148 | struct dentry *coeff_i; | 
|  | 149 | struct dentry *coeff_d; | 
|  | 150 | struct dentry *smoothing_shift; | 
|  | 151 | struct dentry *sharpen_factor; | 
|  | 152 | struct dentry *sharpen_duration; | 
|  | 153 | struct dentry *norm_offset; | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 154 | }; | 
|  | 155 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 156 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, | 
| Johannes Berg | e039fa4 | 2008-05-15 12:55:29 +0200 | [diff] [blame] | 157 | struct ieee80211_tx_info *stat); | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 158 |  | 
|  | 159 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, | 
|  | 160 | int index, int rate); | 
|  | 161 |  | 
|  | 162 | void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf, | 
|  | 163 | int index, int rate); | 
|  | 164 |  | 
|  | 165 | void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf, | 
|  | 166 | s32 pf_sample, s32 prop_err, | 
|  | 167 | s32 int_err, s32 der_err); | 
|  | 168 |  | 
|  | 169 | void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta, | 
|  | 170 | struct dentry *dir); | 
|  | 171 |  | 
|  | 172 | void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta); | 
|  | 173 |  | 
|  | 174 | struct rc_pid_sta_info { | 
|  | 175 | unsigned long last_change; | 
|  | 176 | unsigned long last_sample; | 
|  | 177 |  | 
|  | 178 | u32 tx_num_failed; | 
|  | 179 | u32 tx_num_xmit; | 
|  | 180 |  | 
| Johannes Berg | ae17e98 | 2008-09-11 03:04:36 +0200 | [diff] [blame] | 181 | int txrate_idx; | 
|  | 182 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 | */ | 
|  | 230 | struct 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 |  | 
|  | 245 | struct 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 Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 261 | /* Sharpening factor and duration. */ | 
|  | 262 | unsigned int sharpen_factor; | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 263 | unsigned int sharpen_duration; | 
|  | 264 |  | 
|  | 265 | /* Normalization offset. */ | 
|  | 266 | unsigned int norm_offset; | 
|  | 267 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 268 | /* Rates information. */ | 
|  | 269 | struct rc_pid_rateinfo *rinfo; | 
|  | 270 |  | 
|  | 271 | /* Index of the last used rate. */ | 
|  | 272 | int oldrate; | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 273 |  | 
|  | 274 | #ifdef CONFIG_MAC80211_DEBUGFS | 
|  | 275 | /* Debugfs entries created for the parameters above. */ | 
|  | 276 | struct rc_pid_debugfs_entries dentries; | 
|  | 277 | #endif | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 278 | }; | 
|  | 279 |  | 
|  | 280 | #endif /* RC80211_PID_H */ |