1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28
29#include "rt2x00.h"
30#include "rt2x00lib.h"
31
32
33
34
35
36#define DEFAULT_RSSI -128
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61#define AVG_SAMPLES 8
62#define AVG_FACTOR 1000
63#define MOVING_AVERAGE(__avg, __val) \
64({ \
65 struct avg_val __new; \
66 __new.avg_weight = \
67 (__avg).avg_weight ? \
68 ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \
69 ((__val) * (AVG_FACTOR))) / \
70 (AVG_SAMPLES)) : \
71 ((__val) * (AVG_FACTOR)); \
72 __new.avg = __new.avg_weight / (AVG_FACTOR); \
73 __new; \
74})
75
76static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
77{
78 struct link_ant *ant = &rt2x00dev->link.ant;
79
80 if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success)
81 return ant->rssi_ant.avg;
82 return DEFAULT_RSSI;
83}
84
85static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
86{
87 struct link_ant *ant = &rt2x00dev->link.ant;
88
89 if (ant->rssi_history)
90 return ant->rssi_history;
91 return DEFAULT_RSSI;
92}
93
94static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
95 int rssi)
96{
97 struct link_ant *ant = &rt2x00dev->link.ant;
98 ant->rssi_history = rssi;
99}
100
101static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
102{
103 rt2x00dev->link.ant.rssi_ant.avg = 0;
104 rt2x00dev->link.ant.rssi_ant.avg_weight = 0;
105}
106
107static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
108{
109 struct link_ant *ant = &rt2x00dev->link.ant;
110 struct antenna_setup new_ant;
111 int other_antenna;
112
113 int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
114 int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
115
116 memcpy(&new_ant, &ant->active, sizeof(new_ant));
117
118
119
120
121 ant->flags &= ~ANTENNA_MODE_SAMPLE;
122
123
124
125
126
127
128
129
130
131 if (sample_current >= sample_other) {
132 rt2x00link_antenna_update_rssi_history(rt2x00dev,
133 sample_current);
134 return;
135 }
136
137 other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
138
139 if (ant->flags & ANTENNA_RX_DIVERSITY)
140 new_ant.rx = other_antenna;
141
142 if (ant->flags & ANTENNA_TX_DIVERSITY)
143 new_ant.tx = other_antenna;
144
145 rt2x00lib_config_antenna(rt2x00dev, new_ant);
146}
147
148static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
149{
150 struct link_ant *ant = &rt2x00dev->link.ant;
151 struct antenna_setup new_ant;
152 int rssi_curr;
153 int rssi_old;
154
155 memcpy(&new_ant, &ant->active, sizeof(new_ant));
156
157
158
159
160
161 rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
162 rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
163 rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
164
165
166
167
168
169
170
171
172
173
174 if (abs(rssi_curr - rssi_old) < 5)
175 return;
176
177 ant->flags |= ANTENNA_MODE_SAMPLE;
178
179 if (ant->flags & ANTENNA_RX_DIVERSITY)
180 new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
181
182 if (ant->flags & ANTENNA_TX_DIVERSITY)
183 new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
184
185 rt2x00lib_config_antenna(rt2x00dev, new_ant);
186}
187
188static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
189{
190 struct link_ant *ant = &rt2x00dev->link.ant;
191
192
193
194
195
196 if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
197 !(ant->flags & ANTENNA_TX_DIVERSITY)) {
198 ant->flags = 0;
199 return true;
200 }
201
202
203
204
205
206
207
208 if (ant->flags & ANTENNA_MODE_SAMPLE) {
209 rt2x00lib_antenna_diversity_sample(rt2x00dev);
210 return true;
211 } else if (rt2x00dev->link.count & 1) {
212 rt2x00lib_antenna_diversity_eval(rt2x00dev);
213 return true;
214 }
215
216 return false;
217}
218
219void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
220 struct sk_buff *skb,
221 struct rxdone_entry_desc *rxdesc)
222{
223 struct link *link = &rt2x00dev->link;
224 struct link_qual *qual = &rt2x00dev->link.qual;
225 struct link_ant *ant = &rt2x00dev->link.ant;
226 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
227
228
229
230
231 if (!rt2x00dev->intf_sta_count)
232 return;
233
234
235
236
237
238 qual->rx_success++;
239
240
241
242
243
244
245 if (!ieee80211_is_beacon(hdr->frame_control) ||
246 !(rxdesc->dev_flags & RXDONE_MY_BSS))
247 return;
248
249
250
251
252 link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi);
253
254
255
256
257 ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi);
258}
259
260void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
261{
262 struct link *link = &rt2x00dev->link;
263
264
265
266
267
268
269
270 if (!rt2x00dev->intf_sta_count)
271 return;
272
273
274
275
276
277
278
279 if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
280 return;
281
282 rt2x00link_reset_tuner(rt2x00dev, false);
283
284 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
285 ieee80211_queue_delayed_work(rt2x00dev->hw,
286 &link->work, LINK_TUNE_INTERVAL);
287}
288
289void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
290{
291 cancel_delayed_work_sync(&rt2x00dev->link.work);
292}
293
294void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
295{
296 struct link_qual *qual = &rt2x00dev->link.qual;
297 u8 vgc_level = qual->vgc_level_reg;
298
299 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
300 return;
301
302
303
304
305
306
307
308
309
310 rt2x00dev->link.count = 0;
311 memset(qual, 0, sizeof(*qual));
312
313
314
315
316
317
318 qual->vgc_level_reg = vgc_level;
319
320
321
322
323 rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
324
325 if (antenna)
326 rt2x00link_antenna_reset(rt2x00dev);
327}
328
329static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
330{
331 struct link_qual *qual = &rt2x00dev->link.qual;
332
333 qual->rx_success = 0;
334 qual->rx_failed = 0;
335 qual->tx_success = 0;
336 qual->tx_failed = 0;
337}
338
339static void rt2x00link_tuner(struct work_struct *work)
340{
341 struct rt2x00_dev *rt2x00dev =
342 container_of(work, struct rt2x00_dev, link.work.work);
343 struct link *link = &rt2x00dev->link;
344 struct link_qual *qual = &rt2x00dev->link.qual;
345
346
347
348
349
350 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
351 test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
352 return;
353
354
355
356
357 rt2x00dev->ops->lib->link_stats(rt2x00dev, qual);
358 rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
359
360
361
362
363
364
365
366 if (!link->avg_rssi.avg || !qual->rx_success)
367 qual->rssi = DEFAULT_RSSI;
368 else
369 qual->rssi = link->avg_rssi.avg;
370
371
372
373
374
375
376 if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags))
377 rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
378
379
380
381
382 rt2x00leds_led_quality(rt2x00dev, qual->rssi);
383
384
385
386
387
388
389 if (rt2x00lib_antenna_diversity(rt2x00dev))
390 rt2x00link_reset_qual(rt2x00dev);
391
392
393
394
395 link->count++;
396
397 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
398 ieee80211_queue_delayed_work(rt2x00dev->hw,
399 &link->work, LINK_TUNE_INTERVAL);
400}
401
402void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
403{
404 struct link *link = &rt2x00dev->link;
405
406 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
407 rt2x00dev->ops->lib->watchdog)
408 ieee80211_queue_delayed_work(rt2x00dev->hw,
409 &link->watchdog_work,
410 WATCHDOG_INTERVAL);
411}
412
413void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
414{
415 cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
416}
417
418static void rt2x00link_watchdog(struct work_struct *work)
419{
420 struct rt2x00_dev *rt2x00dev =
421 container_of(work, struct rt2x00_dev, link.watchdog_work.work);
422 struct link *link = &rt2x00dev->link;
423
424
425
426
427
428 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
429 return;
430
431 rt2x00dev->ops->lib->watchdog(rt2x00dev);
432
433 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
434 ieee80211_queue_delayed_work(rt2x00dev->hw,
435 &link->watchdog_work,
436 WATCHDOG_INTERVAL);
437}
438
439void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
440{
441 struct link *link = &rt2x00dev->link;
442
443 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
444 rt2x00dev->ops->lib->gain_calibration)
445 ieee80211_queue_delayed_work(rt2x00dev->hw,
446 &link->agc_work,
447 AGC_INTERVAL);
448}
449
450void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev)
451{
452 struct link *link = &rt2x00dev->link;
453
454 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
455 rt2x00dev->ops->lib->vco_calibration)
456 ieee80211_queue_delayed_work(rt2x00dev->hw,
457 &link->vco_work,
458 VCO_INTERVAL);
459}
460
461void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
462{
463 cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
464}
465
466void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev)
467{
468 cancel_delayed_work_sync(&rt2x00dev->link.vco_work);
469}
470
471static void rt2x00link_agc(struct work_struct *work)
472{
473 struct rt2x00_dev *rt2x00dev =
474 container_of(work, struct rt2x00_dev, link.agc_work.work);
475 struct link *link = &rt2x00dev->link;
476
477
478
479
480
481 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
482 return;
483
484 rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
485
486 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
487 ieee80211_queue_delayed_work(rt2x00dev->hw,
488 &link->agc_work,
489 AGC_INTERVAL);
490}
491
492static void rt2x00link_vcocal(struct work_struct *work)
493{
494 struct rt2x00_dev *rt2x00dev =
495 container_of(work, struct rt2x00_dev, link.vco_work.work);
496 struct link *link = &rt2x00dev->link;
497
498
499
500
501
502 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
503 return;
504
505 rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
506
507 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
508 ieee80211_queue_delayed_work(rt2x00dev->hw,
509 &link->vco_work,
510 VCO_INTERVAL);
511}
512
513void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
514{
515 INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
516 if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags))
517 INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);
518 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
519 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
520}
521