diff options
author | Lars Ericsson <Lars_Ericsson@telia.com> | 2009-08-08 17:54:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:13:52 -0400 |
commit | 66679a65efffffb62dc2650960b3aff758d575f9 (patch) | |
tree | 75f3f323331e89fd7c4a8cc87339cceb1959037b | |
parent | 193df183b15cda78f6b2373f576e243327ea0d8f (diff) |
rt2x00: Fix rounding errors in RSSI average calculation
Small changes in signal level was not detected up by the
MOVING_AVERAGE() due to a rounding error, using 'int' type.
rt2x00lib_antenna_diversity_eval:
rssi: -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62 -62
rssi_avg: -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57 -57
The signal level reported back could be significantly (5dBm)
different from the actual value. A level +3dBm is the same as
double the AP output power.
Signed-off-by: Lars Ericsson <Lars_Ericsson@telia.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00link.c | 65 |
2 files changed, 52 insertions, 28 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 704e94474b1d..e6e73be31e37 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -134,6 +134,17 @@ | |||
134 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) | 134 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) |
135 | 135 | ||
136 | /* | 136 | /* |
137 | * Structure for average calculation | ||
138 | * The avg field contains the actual average value, | ||
139 | * but avg_weight is internally used during calculations | ||
140 | * to prevent rounding errors. | ||
141 | */ | ||
142 | struct avg_val { | ||
143 | int avg; | ||
144 | int avg_weight; | ||
145 | }; | ||
146 | |||
147 | /* | ||
137 | * Chipset identification | 148 | * Chipset identification |
138 | * The chipset on the device is composed of a RT and RF chip. | 149 | * The chipset on the device is composed of a RT and RF chip. |
139 | * The chipset combination is important for determining device capabilities. | 150 | * The chipset combination is important for determining device capabilities. |
@@ -256,7 +267,7 @@ struct link_ant { | |||
256 | * Similar to the avg_rssi in the link_qual structure | 267 | * Similar to the avg_rssi in the link_qual structure |
257 | * this value is updated by using the walking average. | 268 | * this value is updated by using the walking average. |
258 | */ | 269 | */ |
259 | int rssi_ant; | 270 | struct avg_val rssi_ant; |
260 | }; | 271 | }; |
261 | 272 | ||
262 | /* | 273 | /* |
@@ -285,7 +296,7 @@ struct link { | |||
285 | /* | 296 | /* |
286 | * Currently active average RSSI value | 297 | * Currently active average RSSI value |
287 | */ | 298 | */ |
288 | int avg_rssi; | 299 | struct avg_val avg_rssi; |
289 | 300 | ||
290 | /* | 301 | /* |
291 | * Currently precalculated percentages of successful | 302 | * Currently precalculated percentages of successful |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index dd68f3a57b6d..c64db0ba7f40 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -46,7 +46,15 @@ | |||
46 | #define DEFAULT_PERCENTAGE 50 | 46 | #define DEFAULT_PERCENTAGE 50 |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * Small helper macro to work with moving/walking averages. | 49 | * Small helper macro for percentage calculation |
50 | * This is a very simple macro with the only catch that it will | ||
51 | * produce a default value in case no total value was provided. | ||
52 | */ | ||
53 | #define PERCENTAGE(__value, __total) \ | ||
54 | ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) ) | ||
55 | |||
56 | /* | ||
57 | * Helper struct and macro to work with moving/walking averages. | ||
50 | * When adding a value to the average value the following calculation | 58 | * When adding a value to the average value the following calculation |
51 | * is needed: | 59 | * is needed: |
52 | * | 60 | * |
@@ -60,18 +68,28 @@ | |||
60 | * for a few minutes but when the device is moved away from the AP | 68 | * for a few minutes but when the device is moved away from the AP |
61 | * the average will not decrease fast enough to compensate. | 69 | * the average will not decrease fast enough to compensate. |
62 | * The walking average compensates this and will move towards | 70 | * The walking average compensates this and will move towards |
63 | * the new values correctly allowing a effective link tuning. | 71 | * the new values correctly allowing a effective link tuning, |
72 | * the speed of the average moving towards other values depends | ||
73 | * on the value for the number of samples. The higher the number | ||
74 | * of samples, the slower the average will move. | ||
75 | * We use two variables to keep track of the average value to | ||
76 | * compensate for the rounding errors. This can be a significant | ||
77 | * error (>5dBm) if the factor is too low. | ||
64 | */ | 78 | */ |
65 | #define MOVING_AVERAGE(__avg, __val, __samples) \ | 79 | #define AVG_SAMPLES 8 |
66 | ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) | 80 | #define AVG_FACTOR 1000 |
67 | 81 | #define MOVING_AVERAGE(__avg, __val) \ | |
68 | /* | 82 | ({ \ |
69 | * Small helper macro for percentage calculation | 83 | struct avg_val __new; \ |
70 | * This is a very simple macro with the only catch that it will | 84 | __new.avg_weight = \ |
71 | * produce a default value in case no total value was provided. | 85 | (__avg).avg_weight ? \ |
72 | */ | 86 | ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ |
73 | #define PERCENTAGE(__value, __total) \ | 87 | ((__val) * (AVG_FACTOR))) / \ |
74 | ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) ) | 88 | (AVG_SAMPLES) ) : \ |
89 | ((__val) * (AVG_FACTOR)); \ | ||
90 | __new.avg = __new.avg_weight / (AVG_FACTOR); \ | ||
91 | __new; \ | ||
92 | }) | ||
75 | 93 | ||
76 | /* | 94 | /* |
77 | * For calculating the Signal quality we have determined | 95 | * For calculating the Signal quality we have determined |
@@ -98,8 +116,8 @@ static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) | |||
98 | { | 116 | { |
99 | struct link_ant *ant = &rt2x00dev->link.ant; | 117 | struct link_ant *ant = &rt2x00dev->link.ant; |
100 | 118 | ||
101 | if (ant->rssi_ant && rt2x00dev->link.qual.rx_success) | 119 | if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success) |
102 | return ant->rssi_ant; | 120 | return ant->rssi_ant.avg; |
103 | return DEFAULT_RSSI; | 121 | return DEFAULT_RSSI; |
104 | } | 122 | } |
105 | 123 | ||
@@ -121,7 +139,8 @@ static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, | |||
121 | 139 | ||
122 | static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) | 140 | static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) |
123 | { | 141 | { |
124 | rt2x00dev->link.ant.rssi_ant = 0; | 142 | rt2x00dev->link.ant.rssi_ant.avg = 0; |
143 | rt2x00dev->link.ant.rssi_ant.avg_weight = 0; | ||
125 | } | 144 | } |
126 | 145 | ||
127 | static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) | 146 | static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) |
@@ -258,8 +277,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, | |||
258 | struct link_qual *qual = &rt2x00dev->link.qual; | 277 | struct link_qual *qual = &rt2x00dev->link.qual; |
259 | struct link_ant *ant = &rt2x00dev->link.ant; | 278 | struct link_ant *ant = &rt2x00dev->link.ant; |
260 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 279 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
261 | int avg_rssi = rxdesc->rssi; | ||
262 | int ant_rssi = rxdesc->rssi; | ||
263 | 280 | ||
264 | /* | 281 | /* |
265 | * Frame was received successfully since non-succesfull | 282 | * Frame was received successfully since non-succesfull |
@@ -279,16 +296,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, | |||
279 | /* | 296 | /* |
280 | * Update global RSSI | 297 | * Update global RSSI |
281 | */ | 298 | */ |
282 | if (link->avg_rssi) | 299 | link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi); |
283 | avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8); | ||
284 | link->avg_rssi = avg_rssi; | ||
285 | 300 | ||
286 | /* | 301 | /* |
287 | * Update antenna RSSI | 302 | * Update antenna RSSI |
288 | */ | 303 | */ |
289 | if (ant->rssi_ant) | 304 | ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi); |
290 | ant_rssi = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi, 8); | ||
291 | ant->rssi_ant = ant_rssi; | ||
292 | } | 305 | } |
293 | 306 | ||
294 | static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) | 307 | static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) |
@@ -421,10 +434,10 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
421 | * collect the RSSI data we could use this. Otherwise we | 434 | * collect the RSSI data we could use this. Otherwise we |
422 | * must fallback to the default RSSI value. | 435 | * must fallback to the default RSSI value. |
423 | */ | 436 | */ |
424 | if (!link->avg_rssi || !qual->rx_success) | 437 | if (!link->avg_rssi.avg || !qual->rx_success) |
425 | qual->rssi = DEFAULT_RSSI; | 438 | qual->rssi = DEFAULT_RSSI; |
426 | else | 439 | else |
427 | qual->rssi = link->avg_rssi; | 440 | qual->rssi = link->avg_rssi.avg; |
428 | 441 | ||
429 | /* | 442 | /* |
430 | * Only perform the link tuning when Link tuning | 443 | * Only perform the link tuning when Link tuning |
@@ -442,7 +455,7 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
442 | /* | 455 | /* |
443 | * Send a signal to the led to update the led signal strength. | 456 | * Send a signal to the led to update the led signal strength. |
444 | */ | 457 | */ |
445 | rt2x00leds_led_quality(rt2x00dev, link->avg_rssi); | 458 | rt2x00leds_led_quality(rt2x00dev, qual->rssi); |
446 | 459 | ||
447 | /* | 460 | /* |
448 | * Evaluate antenna setup, make this the last step when | 461 | * Evaluate antenna setup, make this the last step when |