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 /drivers/net/wireless/rt2x00 | |
| 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>
Diffstat (limited to 'drivers/net/wireless/rt2x00')
| -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 |
