]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/rt2x00/rt2x00link.c
Merge remote-tracking branch 'net-next/master'
[karo-tx-linux.git] / drivers / net / wireless / rt2x00 / rt2x00link.c
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, write to the
17         Free Software Foundation, Inc.,
18         59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 /*
22         Module: rt2x00lib
23         Abstract: rt2x00 generic link tuning routines.
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28
29 #include "rt2x00.h"
30 #include "rt2x00lib.h"
31
32 /*
33  * When we lack RSSI information return something less then -80 to
34  * tell the driver to tune the device to maximum sensitivity.
35  */
36 #define DEFAULT_RSSI            -128
37
38 /* Constants for EWMA calculations. */
39 #define RT2X00_EWMA_FACTOR      1024
40 #define RT2X00_EWMA_WEIGHT      8
41
42 static inline int rt2x00link_get_avg_rssi(struct ewma *ewma)
43 {
44         unsigned long avg;
45
46         avg = ewma_read(ewma);
47         if (avg)
48                 return -avg;
49
50         return DEFAULT_RSSI;
51 }
52
53 static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
54 {
55         struct link_ant *ant = &rt2x00dev->link.ant;
56
57         if (rt2x00dev->link.qual.rx_success)
58                 return rt2x00link_get_avg_rssi(&ant->rssi_ant);
59
60         return DEFAULT_RSSI;
61 }
62
63 static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
64 {
65         struct link_ant *ant = &rt2x00dev->link.ant;
66
67         if (ant->rssi_history)
68                 return ant->rssi_history;
69         return DEFAULT_RSSI;
70 }
71
72 static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
73                                                    int rssi)
74 {
75         struct link_ant *ant = &rt2x00dev->link.ant;
76         ant->rssi_history = rssi;
77 }
78
79 static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
80 {
81         ewma_init(&rt2x00dev->link.ant.rssi_ant, RT2X00_EWMA_FACTOR,
82                   RT2X00_EWMA_WEIGHT);
83 }
84
85 static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
86 {
87         struct link_ant *ant = &rt2x00dev->link.ant;
88         struct antenna_setup new_ant;
89         int other_antenna;
90
91         int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
92         int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
93
94         memcpy(&new_ant, &ant->active, sizeof(new_ant));
95
96         /*
97          * We are done sampling. Now we should evaluate the results.
98          */
99         ant->flags &= ~ANTENNA_MODE_SAMPLE;
100
101         /*
102          * During the last period we have sampled the RSSI
103          * from both antennas. It now is time to determine
104          * which antenna demonstrated the best performance.
105          * When we are already on the antenna with the best
106          * performance, just create a good starting point
107          * for the history and we are done.
108          */
109         if (sample_current >= sample_other) {
110                 rt2x00link_antenna_update_rssi_history(rt2x00dev,
111                         sample_current);
112                 return;
113         }
114
115         other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
116
117         if (ant->flags & ANTENNA_RX_DIVERSITY)
118                 new_ant.rx = other_antenna;
119
120         if (ant->flags & ANTENNA_TX_DIVERSITY)
121                 new_ant.tx = other_antenna;
122
123         rt2x00lib_config_antenna(rt2x00dev, new_ant);
124 }
125
126 static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
127 {
128         struct link_ant *ant = &rt2x00dev->link.ant;
129         struct antenna_setup new_ant;
130         int rssi_curr;
131         int rssi_old;
132
133         memcpy(&new_ant, &ant->active, sizeof(new_ant));
134
135         /*
136          * Get current RSSI value along with the historical value,
137          * after that update the history with the current value.
138          */
139         rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
140         rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
141         rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
142
143         /*
144          * Legacy driver indicates that we should swap antenna's
145          * when the difference in RSSI is greater that 5. This
146          * also should be done when the RSSI was actually better
147          * then the previous sample.
148          * When the difference exceeds the threshold we should
149          * sample the rssi from the other antenna to make a valid
150          * comparison between the 2 antennas.
151          */
152         if (abs(rssi_curr - rssi_old) < 5)
153                 return;
154
155         ant->flags |= ANTENNA_MODE_SAMPLE;
156
157         if (ant->flags & ANTENNA_RX_DIVERSITY)
158                 new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
159
160         if (ant->flags & ANTENNA_TX_DIVERSITY)
161                 new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
162
163         rt2x00lib_config_antenna(rt2x00dev, new_ant);
164 }
165
166 static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
167 {
168         struct link_ant *ant = &rt2x00dev->link.ant;
169
170         /*
171          * Determine if software diversity is enabled for
172          * either the TX or RX antenna (or both).
173          */
174         if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
175             !(ant->flags & ANTENNA_TX_DIVERSITY)) {
176                 ant->flags = 0;
177                 return true;
178         }
179
180         /*
181          * If we have only sampled the data over the last period
182          * we should now harvest the data. Otherwise just evaluate
183          * the data. The latter should only be performed once
184          * every 2 seconds.
185          */
186         if (ant->flags & ANTENNA_MODE_SAMPLE) {
187                 rt2x00lib_antenna_diversity_sample(rt2x00dev);
188                 return true;
189         } else if (rt2x00dev->link.count & 1) {
190                 rt2x00lib_antenna_diversity_eval(rt2x00dev);
191                 return true;
192         }
193
194         return false;
195 }
196
197 void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
198                              struct sk_buff *skb,
199                              struct rxdone_entry_desc *rxdesc)
200 {
201         struct link *link = &rt2x00dev->link;
202         struct link_qual *qual = &rt2x00dev->link.qual;
203         struct link_ant *ant = &rt2x00dev->link.ant;
204         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
205
206         /*
207          * No need to update the stats for !=STA interfaces
208          */
209         if (!rt2x00dev->intf_sta_count)
210                 return;
211
212         /*
213          * Frame was received successfully since non-succesfull
214          * frames would have been dropped by the hardware.
215          */
216         qual->rx_success++;
217
218         /*
219          * We are only interested in quality statistics from
220          * beacons which came from the BSS which we are
221          * associated with.
222          */
223         if (!ieee80211_is_beacon(hdr->frame_control) ||
224             !(rxdesc->dev_flags & RXDONE_MY_BSS))
225                 return;
226
227         /*
228          * Update global RSSI
229          */
230         ewma_add(&link->avg_rssi, -rxdesc->rssi);
231
232         /*
233          * Update antenna RSSI
234          */
235         ewma_add(&ant->rssi_ant, -rxdesc->rssi);
236 }
237
238 void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
239 {
240         struct link *link = &rt2x00dev->link;
241
242         /*
243          * Link tuning should only be performed when
244          * an active sta interface exists. AP interfaces
245          * don't need link tuning and monitor mode interfaces
246          * should never have to work with link tuners.
247          */
248         if (!rt2x00dev->intf_sta_count)
249                 return;
250
251         /**
252          * While scanning, link tuning is disabled. By default
253          * the most sensitive settings will be used to make sure
254          * that all beacons and probe responses will be received
255          * during the scan.
256          */
257         if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
258                 return;
259
260         rt2x00link_reset_tuner(rt2x00dev, false);
261
262         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
263                 ieee80211_queue_delayed_work(rt2x00dev->hw,
264                                              &link->work, LINK_TUNE_INTERVAL);
265 }
266
267 void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
268 {
269         cancel_delayed_work_sync(&rt2x00dev->link.work);
270 }
271
272 void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
273 {
274         struct link_qual *qual = &rt2x00dev->link.qual;
275         u8 vgc_level = qual->vgc_level_reg;
276
277         if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
278                 return;
279
280         /*
281          * Reset link information.
282          * Both the currently active vgc level as well as
283          * the link tuner counter should be reset. Resetting
284          * the counter is important for devices where the
285          * device should only perform link tuning during the
286          * first minute after being enabled.
287          */
288         rt2x00dev->link.count = 0;
289         memset(qual, 0, sizeof(*qual));
290         ewma_init(&rt2x00dev->link.avg_rssi, RT2X00_EWMA_FACTOR,
291                   RT2X00_EWMA_WEIGHT);
292
293         /*
294          * Restore the VGC level as stored in the registers,
295          * the driver can use this to determine if the register
296          * must be updated during reset or not.
297          */
298         qual->vgc_level_reg = vgc_level;
299
300         /*
301          * Reset the link tuner.
302          */
303         rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
304
305         if (antenna)
306                 rt2x00link_antenna_reset(rt2x00dev);
307 }
308
309 static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
310 {
311         struct link_qual *qual = &rt2x00dev->link.qual;
312
313         qual->rx_success = 0;
314         qual->rx_failed = 0;
315         qual->tx_success = 0;
316         qual->tx_failed = 0;
317 }
318
319 static void rt2x00link_tuner(struct work_struct *work)
320 {
321         struct rt2x00_dev *rt2x00dev =
322             container_of(work, struct rt2x00_dev, link.work.work);
323         struct link *link = &rt2x00dev->link;
324         struct link_qual *qual = &rt2x00dev->link.qual;
325
326         /*
327          * When the radio is shutting down we should
328          * immediately cease all link tuning.
329          */
330         if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
331             test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
332                 return;
333
334         /*
335          * Update statistics.
336          */
337         rt2x00dev->ops->lib->link_stats(rt2x00dev, qual);
338         rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
339
340         /*
341          * Update quality RSSI for link tuning,
342          * when we have received some frames and we managed to
343          * collect the RSSI data we could use this. Otherwise we
344          * must fallback to the default RSSI value.
345          */
346         if (!qual->rx_success)
347                 qual->rssi = DEFAULT_RSSI;
348         else
349                 qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi);
350
351         /*
352          * Check if link tuning is supported by the hardware, some hardware
353          * do not support link tuning at all, while other devices can disable
354          * the feature from the EEPROM.
355          */
356         if (rt2x00_has_cap_link_tuning(rt2x00dev))
357                 rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
358
359         /*
360          * Send a signal to the led to update the led signal strength.
361          */
362         rt2x00leds_led_quality(rt2x00dev, qual->rssi);
363
364         /*
365          * Evaluate antenna setup, make this the last step when
366          * rt2x00lib_antenna_diversity made changes the quality
367          * statistics will be reset.
368          */
369         if (rt2x00lib_antenna_diversity(rt2x00dev))
370                 rt2x00link_reset_qual(rt2x00dev);
371
372         /*
373          * Increase tuner counter, and reschedule the next link tuner run.
374          */
375         link->count++;
376
377         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
378                 ieee80211_queue_delayed_work(rt2x00dev->hw,
379                                              &link->work, LINK_TUNE_INTERVAL);
380 }
381
382 void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
383 {
384         struct link *link = &rt2x00dev->link;
385
386         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
387             rt2x00dev->ops->lib->watchdog)
388                 ieee80211_queue_delayed_work(rt2x00dev->hw,
389                                              &link->watchdog_work,
390                                              WATCHDOG_INTERVAL);
391 }
392
393 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
394 {
395         cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
396 }
397
398 static void rt2x00link_watchdog(struct work_struct *work)
399 {
400         struct rt2x00_dev *rt2x00dev =
401             container_of(work, struct rt2x00_dev, link.watchdog_work.work);
402         struct link *link = &rt2x00dev->link;
403
404         /*
405          * When the radio is shutting down we should
406          * immediately cease the watchdog monitoring.
407          */
408         if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
409                 return;
410
411         rt2x00dev->ops->lib->watchdog(rt2x00dev);
412
413         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
414                 ieee80211_queue_delayed_work(rt2x00dev->hw,
415                                              &link->watchdog_work,
416                                              WATCHDOG_INTERVAL);
417 }
418
419 void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
420 {
421         struct link *link = &rt2x00dev->link;
422
423         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
424             rt2x00dev->ops->lib->gain_calibration)
425                 ieee80211_queue_delayed_work(rt2x00dev->hw,
426                                              &link->agc_work,
427                                              AGC_INTERVAL);
428 }
429
430 void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev)
431 {
432         struct link *link = &rt2x00dev->link;
433
434         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
435             rt2x00dev->ops->lib->vco_calibration)
436                 ieee80211_queue_delayed_work(rt2x00dev->hw,
437                                              &link->vco_work,
438                                              VCO_INTERVAL);
439 }
440
441 void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
442 {
443         cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
444 }
445
446 void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev)
447 {
448         cancel_delayed_work_sync(&rt2x00dev->link.vco_work);
449 }
450
451 static void rt2x00link_agc(struct work_struct *work)
452 {
453         struct rt2x00_dev *rt2x00dev =
454             container_of(work, struct rt2x00_dev, link.agc_work.work);
455         struct link *link = &rt2x00dev->link;
456
457         /*
458          * When the radio is shutting down we should
459          * immediately cease the watchdog monitoring.
460          */
461         if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
462                 return;
463
464         rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
465
466         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
467                 ieee80211_queue_delayed_work(rt2x00dev->hw,
468                                              &link->agc_work,
469                                              AGC_INTERVAL);
470 }
471
472 static void rt2x00link_vcocal(struct work_struct *work)
473 {
474         struct rt2x00_dev *rt2x00dev =
475             container_of(work, struct rt2x00_dev, link.vco_work.work);
476         struct link *link = &rt2x00dev->link;
477
478         /*
479          * When the radio is shutting down we should
480          * immediately cease the VCO calibration.
481          */
482         if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
483                 return;
484
485         rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
486
487         if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
488                 ieee80211_queue_delayed_work(rt2x00dev->hw,
489                                              &link->vco_work,
490                                              VCO_INTERVAL);
491 }
492
493 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
494 {
495         INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
496         if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
497                 INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);
498         INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
499         INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
500 }