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 * Link tuning should only be performed when 237 * an active sta interface exists. AP interfaces 238 * don't need link tuning and monitor mode interfaces 239 * should never have to work with link tuners. 240 */ 241 if (!rt2x00dev->intf_sta_count) 242 return; 243 244 /** 245 * While scanning, link tuning is disabled. By default 246 * the most sensitive settings will be used to make sure 247 * that all beacons and probe responses will be received 248 * during the scan. 249 */ 250 if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) 251 return; 252 253 rt2x00link_reset_tuner(rt2x00dev, false); 254 255 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 256 ieee80211_queue_delayed_work(rt2x00dev->hw, 257 &link->work, LINK_TUNE_INTERVAL); 258 } 259 260 void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) 261 { 262 cancel_delayed_work_sync(&rt2x00dev->link.work); 263 } 264 265 void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) 266 { 267 struct link_qual *qual = &rt2x00dev->link.qual; 268 u8 vgc_level = qual->vgc_level_reg; 269 270 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 271 return; 272 273 /* 274 * Reset link information. 275 * Both the currently active vgc level as well as 276 * the link tuner counter should be reset. Resetting 277 * the counter is important for devices where the 278 * device should only perform link tuning during the 279 * first minute after being enabled. 280 */ 281 rt2x00dev->link.count = 0; 282 memset(qual, 0, sizeof(*qual)); 283 ewma_rssi_init(&rt2x00dev->link.avg_rssi); 284 285 /* 286 * Restore the VGC level as stored in the registers, 287 * the driver can use this to determine if the register 288 * must be updated during reset or not. 289 */ 290 qual->vgc_level_reg = vgc_level; 291 292 /* 293 * Reset the link tuner. 294 */ 295 rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); 296 297 if (antenna) 298 rt2x00link_antenna_reset(rt2x00dev); 299 } 300 301 static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) 302 { 303 struct link_qual *qual = &rt2x00dev->link.qual; 304 305 qual->rx_success = 0; 306 qual->rx_failed = 0; 307 qual->tx_success = 0; 308 qual->tx_failed = 0; 309 } 310 311 static void rt2x00link_tuner(struct work_struct *work) 312 { 313 struct rt2x00_dev *rt2x00dev = 314 container_of(work, struct rt2x00_dev, link.work.work); 315 struct link *link = &rt2x00dev->link; 316 struct link_qual *qual = &rt2x00dev->link.qual; 317 318 /* 319 * When the radio is shutting down we should 320 * immediately cease all link tuning. 321 */ 322 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || 323 test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) 324 return; 325 326 /* 327 * Update statistics. 328 */ 329 rt2x00dev->ops->lib->link_stats(rt2x00dev, qual); 330 rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; 331 332 /* 333 * Update quality RSSI for link tuning, 334 * when we have received some frames and we managed to 335 * collect the RSSI data we could use this. Otherwise we 336 * must fallback to the default RSSI value. 337 */ 338 if (!qual->rx_success) 339 qual->rssi = DEFAULT_RSSI; 340 else 341 qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi); 342 343 /* 344 * Check if link tuning is supported by the hardware, some hardware 345 * do not support link tuning at all, while other devices can disable 346 * the feature from the EEPROM. 347 */ 348 if (rt2x00_has_cap_link_tuning(rt2x00dev)) 349 rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); 350 351 /* 352 * Send a signal to the led to update the led signal strength. 353 */ 354 rt2x00leds_led_quality(rt2x00dev, qual->rssi); 355 356 /* 357 * Evaluate antenna setup, make this the last step when 358 * rt2x00lib_antenna_diversity made changes the quality 359 * statistics will be reset. 360 */ 361 if (rt2x00lib_antenna_diversity(rt2x00dev)) 362 rt2x00link_reset_qual(rt2x00dev); 363 364 /* 365 * Increase tuner counter, and reschedule the next link tuner run. 366 */ 367 link->count++; 368 369 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 370 ieee80211_queue_delayed_work(rt2x00dev->hw, 371 &link->work, LINK_TUNE_INTERVAL); 372 } 373 374 void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) 375 { 376 struct link *link = &rt2x00dev->link; 377 378 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && 379 rt2x00dev->ops->lib->watchdog) 380 ieee80211_queue_delayed_work(rt2x00dev->hw, 381 &link->watchdog_work, 382 WATCHDOG_INTERVAL); 383 } 384 385 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) 386 { 387 cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work); 388 } 389 390 static void rt2x00link_watchdog(struct work_struct *work) 391 { 392 struct rt2x00_dev *rt2x00dev = 393 container_of(work, struct rt2x00_dev, link.watchdog_work.work); 394 struct link *link = &rt2x00dev->link; 395 396 /* 397 * When the radio is shutting down we should 398 * immediately cease the watchdog monitoring. 399 */ 400 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 401 return; 402 403 rt2x00dev->ops->lib->watchdog(rt2x00dev); 404 405 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 406 ieee80211_queue_delayed_work(rt2x00dev->hw, 407 &link->watchdog_work, 408 WATCHDOG_INTERVAL); 409 } 410 411 void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev) 412 { 413 struct link *link = &rt2x00dev->link; 414 415 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && 416 rt2x00dev->ops->lib->gain_calibration) 417 ieee80211_queue_delayed_work(rt2x00dev->hw, 418 &link->agc_work, 419 AGC_INTERVAL); 420 } 421 422 void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev) 423 { 424 struct link *link = &rt2x00dev->link; 425 426 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && 427 rt2x00dev->ops->lib->vco_calibration) 428 ieee80211_queue_delayed_work(rt2x00dev->hw, 429 &link->vco_work, 430 VCO_INTERVAL); 431 } 432 433 void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) 434 { 435 cancel_delayed_work_sync(&rt2x00dev->link.agc_work); 436 } 437 438 void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev) 439 { 440 cancel_delayed_work_sync(&rt2x00dev->link.vco_work); 441 } 442 443 static void rt2x00link_agc(struct work_struct *work) 444 { 445 struct rt2x00_dev *rt2x00dev = 446 container_of(work, struct rt2x00_dev, link.agc_work.work); 447 struct link *link = &rt2x00dev->link; 448 449 /* 450 * When the radio is shutting down we should 451 * immediately cease the watchdog monitoring. 452 */ 453 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 454 return; 455 456 rt2x00dev->ops->lib->gain_calibration(rt2x00dev); 457 458 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 459 ieee80211_queue_delayed_work(rt2x00dev->hw, 460 &link->agc_work, 461 AGC_INTERVAL); 462 } 463 464 static void rt2x00link_vcocal(struct work_struct *work) 465 { 466 struct rt2x00_dev *rt2x00dev = 467 container_of(work, struct rt2x00_dev, link.vco_work.work); 468 struct link *link = &rt2x00dev->link; 469 470 /* 471 * When the radio is shutting down we should 472 * immediately cease the VCO calibration. 473 */ 474 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 475 return; 476 477 rt2x00dev->ops->lib->vco_calibration(rt2x00dev); 478 479 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 480 ieee80211_queue_delayed_work(rt2x00dev->hw, 481 &link->vco_work, 482 VCO_INTERVAL); 483 } 484 485 void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 486 { 487 INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); 488 if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) 489 INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal); 490 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); 491 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); 492 } 493