1 /* 2 Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> 3 <http://rt2x00.serialmonkey.com> 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 as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 /* 20 Module: rt2x00lib 21 Abstract: rt2x00 generic link tuning routines. 22 */ 23 24 #include <linux/kernel.h> 25 #include <linux/module.h> 26 27 #include "rt2x00.h" 28 #include "rt2x00lib.h" 29 30 /* 31 * When we lack RSSI information return something less then -80 to 32 * tell the driver to tune the device to maximum sensitivity. 33 */ 34 #define DEFAULT_RSSI -128 35 36 static inline int rt2x00link_get_avg_rssi(struct ewma_rssi *ewma) 37 { 38 unsigned long avg; 39 40 avg = ewma_rssi_read(ewma); 41 if (avg) 42 return -avg; 43 44 return DEFAULT_RSSI; 45 } 46 47 static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) 48 { 49 struct link_ant *ant = &rt2x00dev->link.ant; 50 51 if (rt2x00dev->link.qual.rx_success) 52 return rt2x00link_get_avg_rssi(&ant->rssi_ant); 53 54 return DEFAULT_RSSI; 55 } 56 57 static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev) 58 { 59 struct link_ant *ant = &rt2x00dev->link.ant; 60 61 if (ant->rssi_history) 62 return ant->rssi_history; 63 return DEFAULT_RSSI; 64 } 65 66 static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, 67 int rssi) 68 { 69 struct link_ant *ant = &rt2x00dev->link.ant; 70 ant->rssi_history = rssi; 71 } 72 73 static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) 74 { 75 ewma_rssi_init(&rt2x00dev->link.ant.rssi_ant); 76 } 77 78 static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) 79 { 80 struct link_ant *ant = &rt2x00dev->link.ant; 81 struct antenna_setup new_ant; 82 int other_antenna; 83 84 int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev); 85 int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev); 86 87 memcpy(&new_ant, &ant->active, sizeof(new_ant)); 88 89 /* 90 * We are done sampling. Now we should evaluate the results. 91 */ 92 ant->flags &= ~ANTENNA_MODE_SAMPLE; 93 94 /* 95 * During the last period we have sampled the RSSI 96 * from both antennas. It now is time to determine 97 * which antenna demonstrated the best performance. 98 * When we are already on the antenna with the best 99 * performance, just create a good starting point 100 * for the history and we are done. 101 */ 102 if (sample_current >= sample_other) { 103 rt2x00link_antenna_update_rssi_history(rt2x00dev, 104 sample_current); 105 return; 106 } 107 108 other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; 109 110 if (ant->flags & ANTENNA_RX_DIVERSITY) 111 new_ant.rx = other_antenna; 112 113 if (ant->flags & ANTENNA_TX_DIVERSITY) 114 new_ant.tx = other_antenna; 115 116 rt2x00lib_config_antenna(rt2x00dev, new_ant); 117 } 118 119 static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev) 120 { 121 struct link_ant *ant = &rt2x00dev->link.ant; 122 struct antenna_setup new_ant; 123 int rssi_curr; 124 int rssi_old; 125 126 memcpy(&new_ant, &ant->active, sizeof(new_ant)); 127 128 /* 129 * Get current RSSI value along with the historical value, 130 * after that update the history with the current value. 131 */ 132 rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev); 133 rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev); 134 rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr); 135 136 /* 137 * Legacy driver indicates that we should swap antenna's 138 * when the difference in RSSI is greater that 5. This 139 * also should be done when the RSSI was actually better 140 * then the previous sample. 141 * When the difference exceeds the threshold we should 142 * sample the rssi from the other antenna to make a valid 143 * comparison between the 2 antennas. 144 */ 145 if (abs(rssi_curr - rssi_old) < 5) 146 return; 147 148 ant->flags |= ANTENNA_MODE_SAMPLE; 149 150 if (ant->flags & ANTENNA_RX_DIVERSITY) 151 new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; 152 153 if (ant->flags & ANTENNA_TX_DIVERSITY) 154 new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; 155 156 rt2x00lib_config_antenna(rt2x00dev, new_ant); 157 } 158 159 static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) 160 { 161 struct link_ant *ant = &rt2x00dev->link.ant; 162 163 /* 164 * Determine if software diversity is enabled for 165 * either the TX or RX antenna (or both). 166 */ 167 if (!(ant->flags & ANTENNA_RX_DIVERSITY) && 168 !(ant->flags & ANTENNA_TX_DIVERSITY)) { 169 ant->flags = 0; 170 return true; 171 } 172 173 /* 174 * If we have only sampled the data over the last period 175 * we should now harvest the data. Otherwise just evaluate 176 * the data. The latter should only be performed once 177 * every 2 seconds. 178 */ 179 if (ant->flags & ANTENNA_MODE_SAMPLE) { 180 rt2x00lib_antenna_diversity_sample(rt2x00dev); 181 return true; 182 } else if (rt2x00dev->link.count & 1) { 183 rt2x00lib_antenna_diversity_eval(rt2x00dev); 184 return true; 185 } 186 187 return false; 188 } 189 190 void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, 191 struct sk_buff *skb, 192 struct rxdone_entry_desc *rxdesc) 193 { 194 struct link *link = &rt2x00dev->link; 195 struct link_qual *qual = &rt2x00dev->link.qual; 196 struct link_ant *ant = &rt2x00dev->link.ant; 197 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 198 199 /* 200 * No need to update the stats for !=STA interfaces 201 */ 202 if (!rt2x00dev->intf_sta_count) 203 return; 204 205 /* 206 * Frame was received successfully since non-succesfull 207 * frames would have been dropped by the hardware. 208 */ 209 qual->rx_success++; 210 211 /* 212 * We are only interested in quality statistics from 213 * beacons which came from the BSS which we are 214 * associated with. 215 */ 216 if (!ieee80211_is_beacon(hdr->frame_control) || 217 !(rxdesc->dev_flags & RXDONE_MY_BSS)) 218 return; 219 220 /* 221 * Update global RSSI 222 */ 223 ewma_rssi_add(&link->avg_rssi, -rxdesc->rssi); 224 225 /* 226 * Update antenna RSSI 227 */ 228 ewma_rssi_add(&ant->rssi_ant, -rxdesc->rssi); 229 } 230 231 void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) 232 { 233 struct link *link = &rt2x00dev->link; 234 235 /* 236 * Single monitor mode interfaces should never have 237 * work with link tuners. 238 */ 239 if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) 240 return; 241 242 /* 243 * While scanning, link tuning is disabled. By default 244 * the most sensitive settings will be used to make sure 245 * that all beacons and probe responses will be received 246 * during the scan. 247 */ 248 if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) 249 return; 250 251 rt2x00link_reset_tuner(rt2x00dev, false); 252 253 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 254 ieee80211_queue_delayed_work(rt2x00dev->hw, 255 &link->work, LINK_TUNE_INTERVAL); 256 } 257 258 void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) 259 { 260 cancel_delayed_work_sync(&rt2x00dev->link.work); 261 } 262 263 void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) 264 { 265 struct link_qual *qual = &rt2x00dev->link.qual; 266 u8 vgc_level = qual->vgc_level_reg; 267 268 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 269 return; 270 271 /* 272 * Reset link information. 273 * Both the currently active vgc level as well as 274 * the link tuner counter should be reset. Resetting 275 * the counter is important for devices where the 276 * device should only perform link tuning during the 277 * first minute after being enabled. 278 */ 279 rt2x00dev->link.count = 0; 280 memset(qual, 0, sizeof(*qual)); 281 ewma_rssi_init(&rt2x00dev->link.avg_rssi); 282 283 /* 284 * Restore the VGC level as stored in the registers, 285 * the driver can use this to determine if the register 286 * must be updated during reset or not. 287 */ 288 qual->vgc_level_reg = vgc_level; 289 290 /* 291 * Reset the link tuner. 292 */ 293 rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); 294 295 if (antenna) 296 rt2x00link_antenna_reset(rt2x00dev); 297 } 298 299 static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) 300 { 301 struct link_qual *qual = &rt2x00dev->link.qual; 302 303 qual->rx_success = 0; 304 qual->rx_failed = 0; 305 qual->tx_success = 0; 306 qual->tx_failed = 0; 307 } 308 309 static void rt2x00link_tuner_sta(struct rt2x00_dev *rt2x00dev, struct link *link) 310 { 311 struct link_qual *qual = &rt2x00dev->link.qual; 312 313 /* 314 * Update statistics. 315 */ 316 rt2x00dev->ops->lib->link_stats(rt2x00dev, qual); 317 rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; 318 319 /* 320 * Update quality RSSI for link tuning, 321 * when we have received some frames and we managed to 322 * collect the RSSI data we could use this. Otherwise we 323 * must fallback to the default RSSI value. 324 */ 325 if (!qual->rx_success) 326 qual->rssi = DEFAULT_RSSI; 327 else 328 qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi); 329 330 /* 331 * Check if link tuning is supported by the hardware, some hardware 332 * do not support link tuning at all, while other devices can disable 333 * the feature from the EEPROM. 334 */ 335 if (rt2x00_has_cap_link_tuning(rt2x00dev)) 336 rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); 337 338 /* 339 * Send a signal to the led to update the led signal strength. 340 */ 341 rt2x00leds_led_quality(rt2x00dev, qual->rssi); 342 343 /* 344 * Evaluate antenna setup, make this the last step when 345 * rt2x00lib_antenna_diversity made changes the quality 346 * statistics will be reset. 347 */ 348 if (rt2x00lib_antenna_diversity(rt2x00dev)) 349 rt2x00link_reset_qual(rt2x00dev); 350 } 351 352 static void rt2x00link_tuner(struct work_struct *work) 353 { 354 struct rt2x00_dev *rt2x00dev = 355 container_of(work, struct rt2x00_dev, link.work.work); 356 struct link *link = &rt2x00dev->link; 357 358 /* 359 * When the radio is shutting down we should 360 * immediately cease all link tuning. 361 */ 362 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || 363 test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) 364 return; 365 366 /* Do not race with rt2x00mac_config(). */ 367 mutex_lock(&rt2x00dev->conf_mutex); 368 369 if (rt2x00dev->intf_sta_count) 370 rt2x00link_tuner_sta(rt2x00dev, link); 371 372 if (rt2x00dev->ops->lib->gain_calibration && 373 (link->count % (AGC_SECONDS / LINK_TUNE_SECONDS)) == 0) 374 rt2x00dev->ops->lib->gain_calibration(rt2x00dev); 375 376 if (rt2x00dev->ops->lib->vco_calibration && 377 rt2x00_has_cap_vco_recalibration(rt2x00dev) && 378 (link->count % (VCO_SECONDS / LINK_TUNE_SECONDS)) == 0) 379 rt2x00dev->ops->lib->vco_calibration(rt2x00dev); 380 381 mutex_unlock(&rt2x00dev->conf_mutex); 382 383 /* 384 * Increase tuner counter, and reschedule the next link tuner run. 385 */ 386 link->count++; 387 388 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 389 ieee80211_queue_delayed_work(rt2x00dev->hw, 390 &link->work, LINK_TUNE_INTERVAL); 391 } 392 393 void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) 394 { 395 struct link *link = &rt2x00dev->link; 396 397 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && 398 rt2x00dev->ops->lib->watchdog) 399 ieee80211_queue_delayed_work(rt2x00dev->hw, 400 &link->watchdog_work, 401 WATCHDOG_INTERVAL); 402 } 403 404 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) 405 { 406 cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work); 407 } 408 409 static void rt2x00link_watchdog(struct work_struct *work) 410 { 411 struct rt2x00_dev *rt2x00dev = 412 container_of(work, struct rt2x00_dev, link.watchdog_work.work); 413 struct link *link = &rt2x00dev->link; 414 415 /* 416 * When the radio is shutting down we should 417 * immediately cease the watchdog monitoring. 418 */ 419 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 420 return; 421 422 rt2x00dev->ops->lib->watchdog(rt2x00dev); 423 424 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 425 ieee80211_queue_delayed_work(rt2x00dev->hw, 426 &link->watchdog_work, 427 WATCHDOG_INTERVAL); 428 } 429 430 void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 431 { 432 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); 433 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); 434 } 435