| 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 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 27 | /* Proportional PID component coefficient. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 28 | #define RC_PID_COEFF_P			15 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 29 | /* Integral PID component coefficient. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 30 | #define RC_PID_COEFF_I			9 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 31 | /* Derivative PID component coefficient. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 32 | #define RC_PID_COEFF_D			15 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 |  */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 39 | #define RC_PID_TARGET_PF		14 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 40 |  | 
 | 41 | /* Rate behaviour normalization quantity over time. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 42 | #define RC_PID_NORM_OFFSET		3 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 43 |  | 
 | 44 | /* Push high rates right after loading. */ | 
| Stefano Brivio | d439810 | 2007-12-23 04:44:56 +0100 | [diff] [blame] | 45 | #define RC_PID_FAST_START		0 | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 46 |  | 
 | 47 | /* Arithmetic right shift for positive and negative values for ISO C. */ | 
 | 48 | #define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \ | 
| Johannes Berg | c6a1fa1 | 2008-10-07 12:04:32 +0200 | [diff] [blame] | 49 | 	((x) < 0 ? -((-(x)) >> (y)) : (x) >> (y)) | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 50 |  | 
 | 51 | enum 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 |  | 
 | 58 | union rc_pid_event_data { | 
 | 59 | 	/* RC_PID_EVENT_TX_STATUS */ | 
 | 60 | 	struct { | 
| Johannes Berg | e6a9854 | 2008-10-21 12:40:02 +0200 | [diff] [blame] | 61 | 		u32 flags; | 
| Johannes Berg | e039fa4 | 2008-05-15 12:55:29 +0200 | [diff] [blame] | 62 | 		struct ieee80211_tx_info tx_status; | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 |  | 
 | 79 | struct rc_pid_event { | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 80 | 	/* The time when the event occurred */ | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 |  | 
 | 96 | struct 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 |  | 
 | 113 | struct 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 |  | 
| Stefano Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 121 | /** | 
 | 122 |  * struct rc_pid_debugfs_entries - tunable parameters | 
 | 123 |  * | 
 | 124 |  * Algorithm parameters, tunable via debugfs. | 
| Stefano Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 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) | 
| Stefano Brivio | ca5fbca | 2007-12-23 04:40:32 +0100 | [diff] [blame] | 141 |  */ | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 142 | struct rc_pid_debugfs_entries { | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 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; | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 152 | }; | 
 | 153 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 154 | 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] | 155 | 				      struct ieee80211_tx_info *stat); | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 156 |  | 
 | 157 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, | 
 | 158 | 					       int index, int rate); | 
 | 159 |  | 
 | 160 | void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf, | 
 | 161 | 					   int index, int rate); | 
 | 162 |  | 
 | 163 | void 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 |  | 
 | 167 | void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta, | 
 | 168 | 					     struct dentry *dir); | 
 | 169 |  | 
 | 170 | void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta); | 
 | 171 |  | 
 | 172 | struct 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 |  | 
| Johannes Berg | ae17e98 | 2008-09-11 03:04:36 +0200 | [diff] [blame] | 179 | 	int txrate_idx; | 
 | 180 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 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 |  */ | 
 | 228 | struct 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 |  | 
 | 243 | struct 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 |  | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 259 | 	/* Sharpening factor and duration. */ | 
 | 260 | 	unsigned int sharpen_factor; | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 261 | 	unsigned int sharpen_duration; | 
 | 262 |  | 
 | 263 | 	/* Normalization offset. */ | 
 | 264 | 	unsigned int norm_offset; | 
 | 265 |  | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 266 | 	/* Rates information. */ | 
 | 267 | 	struct rc_pid_rateinfo *rinfo; | 
 | 268 |  | 
 | 269 | 	/* Index of the last used rate. */ | 
 | 270 | 	int oldrate; | 
| Mattias Nissler | 1946b74 | 2007-12-20 13:27:26 +0100 | [diff] [blame] | 271 |  | 
 | 272 | #ifdef CONFIG_MAC80211_DEBUGFS | 
 | 273 | 	/* Debugfs entries created for the parameters above. */ | 
 | 274 | 	struct rc_pid_debugfs_entries dentries; | 
 | 275 | #endif | 
| Mattias Nissler | 12446c6 | 2007-12-19 01:27:18 +0100 | [diff] [blame] | 276 | }; | 
 | 277 |  | 
 | 278 | #endif /* RC80211_PID_H */ |