aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00link.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-12-20 04:54:54 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 15:58:35 -0500
commit5352ff6510422d9a9bf13b7272f865eb53247f4d (patch)
treeec85fd9933b3d79cf4ae844c36f0803168203f06 /drivers/net/wireless/rt2x00/rt2x00link.c
parenteb20b4e8a6998ca68d9ac0963ee36a1a36fe241d (diff)
rt2x00: Restrict interface between rt2x00link and drivers
Restrict drivers to only access link_qual structure during link tuning. The contents of these fields are for the drivers and all fields are allowed to be changed to values the driver considers correct. This means that some fields need to be moved outside of this structure to restrict access only to rt2x00link itself. This allows some code to be moved outside of the rt2x00.h header and into rt2x00link.c. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00link.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c145
1 files changed, 102 insertions, 43 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 0462d5ab6e97..ee08f1167f59 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -29,6 +29,71 @@
29#include "rt2x00.h" 29#include "rt2x00.h"
30#include "rt2x00lib.h" 30#include "rt2x00lib.h"
31 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/*
39 * When no TX/RX percentage could be calculated due to lack of
40 * frames on the air, we fallback to a percentage of 50%.
41 * This will assure we will get at least get some decent value
42 * when the link tuner starts.
43 * The value will be dropped and overwritten with the correct (measured)
44 * value anyway during the first run of the link tuner.
45 */
46#define DEFAULT_PERCENTAGE 50
47
48/*
49 * Small helper macro to work with moving/walking averages.
50 * When adding a value to the average value the following calculation
51 * is needed:
52 *
53 * avg_rssi = ((avg_rssi * 7) + rssi) / 8;
54 *
55 * The advantage of this approach is that we only need 1 variable
56 * to store the average in (No need for a count and a total).
57 * But more importantly, normal average values will over time
58 * move less and less towards newly added values this results
59 * that with link tuning, the device can have a very good RSSI
60 * for a few minutes but when the device is moved away from the AP
61 * the average will not decrease fast enough to compensate.
62 * The walking average compensates this and will move towards
63 * the new values correctly allowing a effective link tuning.
64 */
65#define MOVING_AVERAGE(__avg, __val, __samples) \
66 ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
67
68/*
69 * Small helper macro for percentage calculation
70 * This is a very simple macro with the only catch that it will
71 * produce a default value in case no total value was provided.
72 */
73#define PERCENTAGE(__value, __total) \
74 ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
75
76/*
77 * For calculating the Signal quality we have determined
78 * the total number of success and failed RX and TX frames.
79 * With the addition of the average RSSI value we can determine
80 * the link quality using the following algorithm:
81 *
82 * rssi_percentage = (avg_rssi * 100) / rssi_offset
83 * rx_percentage = (rx_success * 100) / rx_total
84 * tx_percentage = (tx_success * 100) / tx_total
85 * avg_signal = ((WEIGHT_RSSI * avg_rssi) +
86 * (WEIGHT_TX * tx_percentage) +
87 * (WEIGHT_RX * rx_percentage)) / 100
88 *
89 * This value should then be checked to not be greater then 100.
90 * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must
91 * sum up to 100 as well.
92 */
93#define WEIGHT_RSSI 20
94#define WEIGHT_RX 40
95#define WEIGHT_TX 40
96
32static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) 97static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
33{ 98{
34 struct link_ant *ant = &rt2x00dev->link.ant; 99 struct link_ant *ant = &rt2x00dev->link.ant;
@@ -191,6 +256,7 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
191 struct sk_buff *skb, 256 struct sk_buff *skb,
192 struct rxdone_entry_desc *rxdesc) 257 struct rxdone_entry_desc *rxdesc)
193{ 258{
259 struct link *link = &rt2x00dev->link;
194 struct link_qual *qual = &rt2x00dev->link.qual; 260 struct link_qual *qual = &rt2x00dev->link.qual;
195 struct link_ant *ant = &rt2x00dev->link.ant; 261 struct link_ant *ant = &rt2x00dev->link.ant;
196 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 262 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -215,9 +281,9 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
215 /* 281 /*
216 * Update global RSSI 282 * Update global RSSI
217 */ 283 */
218 if (qual->avg_rssi) 284 if (link->avg_rssi)
219 avg_rssi = MOVING_AVERAGE(qual->avg_rssi, rxdesc->rssi, 8); 285 avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8);
220 qual->avg_rssi = avg_rssi; 286 link->avg_rssi = avg_rssi;
221 287
222 /* 288 /*
223 * Update antenna RSSI 289 * Update antenna RSSI
@@ -229,21 +295,13 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
229 295
230static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) 296static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
231{ 297{
298 struct link *link = &rt2x00dev->link;
232 struct link_qual *qual = &rt2x00dev->link.qual; 299 struct link_qual *qual = &rt2x00dev->link.qual;
233 300
234 if (qual->rx_failed || qual->rx_success) 301 link->rx_percentage =
235 qual->rx_percentage = 302 PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success);
236 (qual->rx_success * 100) / 303 link->tx_percentage =
237 (qual->rx_failed + qual->rx_success); 304 PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success);
238 else
239 qual->rx_percentage = 50;
240
241 if (qual->tx_failed || qual->tx_success)
242 qual->tx_percentage =
243 (qual->tx_success * 100) /
244 (qual->tx_failed + qual->tx_success);
245 else
246 qual->tx_percentage = 50;
247 305
248 qual->rx_success = 0; 306 qual->rx_success = 0;
249 qual->rx_failed = 0; 307 qual->rx_failed = 0;
@@ -253,7 +311,7 @@ static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
253 311
254int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) 312int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi)
255{ 313{
256 struct link_qual *qual = &rt2x00dev->link.qual; 314 struct link *link = &rt2x00dev->link;
257 int rssi_percentage = 0; 315 int rssi_percentage = 0;
258 int signal; 316 int signal;
259 317
@@ -267,22 +325,22 @@ int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi)
267 * Calculate the different percentages, 325 * Calculate the different percentages,
268 * which will be used for the signal. 326 * which will be used for the signal.
269 */ 327 */
270 rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset; 328 rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset);
271 329
272 /* 330 /*
273 * Add the individual percentages and use the WEIGHT 331 * Add the individual percentages and use the WEIGHT
274 * defines to calculate the current link signal. 332 * defines to calculate the current link signal.
275 */ 333 */
276 signal = ((WEIGHT_RSSI * rssi_percentage) + 334 signal = ((WEIGHT_RSSI * rssi_percentage) +
277 (WEIGHT_TX * qual->tx_percentage) + 335 (WEIGHT_TX * link->tx_percentage) +
278 (WEIGHT_RX * qual->rx_percentage)) / 100; 336 (WEIGHT_RX * link->rx_percentage)) / 100;
279 337
280 return max_t(int, signal, 100); 338 return max_t(int, signal, 100);
281} 339}
282 340
283void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) 341void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
284{ 342{
285 struct link_qual *qual = &rt2x00dev->link.qual; 343 struct link *link = &rt2x00dev->link;
286 344
287 /* 345 /*
288 * Link tuning should only be performed when 346 * Link tuning should only be performed when
@@ -293,26 +351,13 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
293 if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) 351 if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
294 return; 352 return;
295 353
296 /* 354 link->rx_percentage = DEFAULT_PERCENTAGE;
297 * Clear all (possibly) pre-existing quality statistics. 355 link->tx_percentage = DEFAULT_PERCENTAGE;
298 */
299 memset(qual, 0, sizeof(*qual));
300
301 /*
302 * The RX and TX percentage should start at 50%
303 * this will assure we will get at least get some
304 * decent value when the link tuner starts.
305 * The value will be dropped and overwritten with
306 * the correct (measured) value anyway during the
307 * first run of the link tuner.
308 */
309 qual->rx_percentage = 50;
310 qual->tx_percentage = 50;
311 356
312 rt2x00link_reset_tuner(rt2x00dev, false); 357 rt2x00link_reset_tuner(rt2x00dev, false);
313 358
314 queue_delayed_work(rt2x00dev->hw->workqueue, 359 queue_delayed_work(rt2x00dev->hw->workqueue,
315 &rt2x00dev->link.work, LINK_TUNE_INTERVAL); 360 &link->work, LINK_TUNE_INTERVAL);
316} 361}
317 362
318void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) 363void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
@@ -322,6 +367,8 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
322 367
323void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) 368void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
324{ 369{
370 struct link_qual *qual = &rt2x00dev->link.qual;
371
325 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 372 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
326 return; 373 return;
327 374
@@ -334,12 +381,12 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
334 * first minute after being enabled. 381 * first minute after being enabled.
335 */ 382 */
336 rt2x00dev->link.count = 0; 383 rt2x00dev->link.count = 0;
337 rt2x00dev->link.vgc_level = 0; 384 memset(qual, 0, sizeof(*qual));
338 385
339 /* 386 /*
340 * Reset the link tuner. 387 * Reset the link tuner.
341 */ 388 */
342 rt2x00dev->ops->lib->reset_tuner(rt2x00dev); 389 rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
343 390
344 if (antenna) 391 if (antenna)
345 rt2x00link_antenna_reset(rt2x00dev); 392 rt2x00link_antenna_reset(rt2x00dev);
@@ -349,6 +396,7 @@ static void rt2x00link_tuner(struct work_struct *work)
349{ 396{
350 struct rt2x00_dev *rt2x00dev = 397 struct rt2x00_dev *rt2x00dev =
351 container_of(work, struct rt2x00_dev, link.work.work); 398 container_of(work, struct rt2x00_dev, link.work.work);
399 struct link *link = &rt2x00dev->link;
352 struct link_qual *qual = &rt2x00dev->link.qual; 400 struct link_qual *qual = &rt2x00dev->link.qual;
353 401
354 /* 402 /*
@@ -365,11 +413,22 @@ static void rt2x00link_tuner(struct work_struct *work)
365 rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; 413 rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
366 414
367 /* 415 /*
416 * Update quality RSSI for link tuning,
417 * when we have received some frames and we managed to
418 * collect the RSSI data we could use this. Otherwise we
419 * must fallback to the default RSSI value.
420 */
421 if (!link->avg_rssi || !qual->rx_success)
422 qual->rssi = DEFAULT_RSSI;
423 else
424 qual->rssi = link->avg_rssi;
425
426 /*
368 * Only perform the link tuning when Link tuning 427 * Only perform the link tuning when Link tuning
369 * has been enabled (This could have been disabled from the EEPROM). 428 * has been enabled (This could have been disabled from the EEPROM).
370 */ 429 */
371 if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) 430 if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
372 rt2x00dev->ops->lib->link_tuner(rt2x00dev); 431 rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
373 432
374 /* 433 /*
375 * Precalculate a portion of the link signal which is 434 * Precalculate a portion of the link signal which is
@@ -380,7 +439,7 @@ static void rt2x00link_tuner(struct work_struct *work)
380 /* 439 /*
381 * Send a signal to the led to update the led signal strength. 440 * Send a signal to the led to update the led signal strength.
382 */ 441 */
383 rt2x00leds_led_quality(rt2x00dev, qual->avg_rssi); 442 rt2x00leds_led_quality(rt2x00dev, link->avg_rssi);
384 443
385 /* 444 /*
386 * Evaluate antenna setup, make this the last step since this could 445 * Evaluate antenna setup, make this the last step since this could
@@ -391,9 +450,9 @@ static void rt2x00link_tuner(struct work_struct *work)
391 /* 450 /*
392 * Increase tuner counter, and reschedule the next link tuner run. 451 * Increase tuner counter, and reschedule the next link tuner run.
393 */ 452 */
394 rt2x00dev->link.count++; 453 link->count++;
395 queue_delayed_work(rt2x00dev->hw->workqueue, 454 queue_delayed_work(rt2x00dev->hw->workqueue,
396 &rt2x00dev->link.work, LINK_TUNE_INTERVAL); 455 &link->work, LINK_TUNE_INTERVAL);
397} 456}
398 457
399void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 458void rt2x00link_register(struct rt2x00_dev *rt2x00dev)