aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ericsson <Lars_Ericsson@telia.com>2009-08-08 17:54:24 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:52 -0400
commit193df183b15cda78f6b2373f576e243327ea0d8f (patch)
tree18e2eb38a90ed0ee07287c836aaff0c7be7873da
parent93354cbbcbfca920495377158c0f61c36be79e13 (diff)
rt2x00: Fix quality houskeeping for software diversity
Antanna quality statistics is not handled correctly, which leads to software diversity being shutdown completly. The main problem is that during antenna diversity statistics can be reset resulting in loosing the signal strength just before evaluation. rssi history is not updated correctly leading to incorrect comparison material for basing antenna switching on. 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.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c77
2 files changed, 38 insertions, 50 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index cbec91ef6f76..704e94474b1d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -245,14 +245,11 @@ struct link_ant {
245 struct antenna_setup active; 245 struct antenna_setup active;
246 246
247 /* 247 /*
248 * RSSI information for the different antennas. 248 * RSSI history information for the antenna.
249 * These statistics are used to determine when 249 * Used to determine when to switch antenna
250 * to switch antenna when using software diversity. 250 * when using software diversity.
251 *
252 * rssi[0] -> Antenna A RSSI
253 * rssi[1] -> Antenna B RSSI
254 */ 251 */
255 int rssi_history[2]; 252 int rssi_history;
256 253
257 /* 254 /*
258 * Current RSSI average of the currently active antenna. 255 * Current RSSI average of the currently active antenna.
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index fe951dc9bacf..dd68f3a57b6d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -103,39 +103,21 @@ static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
103 return DEFAULT_RSSI; 103 return DEFAULT_RSSI;
104} 104}
105 105
106static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev, 106static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
107 enum antenna antenna)
108{ 107{
109 struct link_ant *ant = &rt2x00dev->link.ant; 108 struct link_ant *ant = &rt2x00dev->link.ant;
110 109
111 if (ant->rssi_history[antenna - ANTENNA_A]) 110 if (ant->rssi_history)
112 return ant->rssi_history[antenna - ANTENNA_A]; 111 return ant->rssi_history;
113 return DEFAULT_RSSI; 112 return DEFAULT_RSSI;
114} 113}
115/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
116#define rt2x00link_antenna_get_rssi_rx_history(__dev) \
117 rt2x00link_antenna_get_rssi_history((__dev), \
118 (__dev)->link.ant.active.rx)
119#define rt2x00link_antenna_get_rssi_tx_history(__dev) \
120 rt2x00link_antenna_get_rssi_history((__dev), \
121 (__dev)->link.ant.active.tx)
122 114
123static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, 115static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
124 enum antenna antenna,
125 int rssi) 116 int rssi)
126{ 117{
127 struct link_ant *ant = &rt2x00dev->link.ant; 118 struct link_ant *ant = &rt2x00dev->link.ant;
128 ant->rssi_history[ant->active.rx - ANTENNA_A] = rssi; 119 ant->rssi_history = rssi;
129} 120}
130/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
131#define rt2x00link_antenna_update_rssi_rx_history(__dev, __rssi) \
132 rt2x00link_antenna_update_rssi_history((__dev), \
133 (__dev)->link.ant.active.rx, \
134 (__rssi))
135#define rt2x00link_antenna_update_rssi_tx_history(__dev, __rssi) \
136 rt2x00link_antenna_update_rssi_history((__dev), \
137 (__dev)->link.ant.active.tx, \
138 (__rssi))
139 121
140static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) 122static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
141{ 123{
@@ -146,8 +128,10 @@ static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
146{ 128{
147 struct link_ant *ant = &rt2x00dev->link.ant; 129 struct link_ant *ant = &rt2x00dev->link.ant;
148 struct antenna_setup new_ant; 130 struct antenna_setup new_ant;
149 int sample_a = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_A); 131 int other_antenna;
150 int sample_b = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_B); 132
133 int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
134 int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
151 135
152 memcpy(&new_ant, &ant->active, sizeof(new_ant)); 136 memcpy(&new_ant, &ant->active, sizeof(new_ant));
153 137
@@ -161,17 +145,22 @@ static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
161 * from both antennas. It now is time to determine 145 * from both antennas. It now is time to determine
162 * which antenna demonstrated the best performance. 146 * which antenna demonstrated the best performance.
163 * When we are already on the antenna with the best 147 * When we are already on the antenna with the best
164 * performance, then there really is nothing for us 148 * performance, just create a good starting point
165 * left to do. 149 * for the history and we are done.
166 */ 150 */
167 if (sample_a == sample_b) 151 if (sample_current >= sample_other) {
152 rt2x00link_antenna_update_rssi_history(rt2x00dev,
153 sample_current);
168 return; 154 return;
155 }
156
157 other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
169 158
170 if (ant->flags & ANTENNA_RX_DIVERSITY) 159 if (ant->flags & ANTENNA_RX_DIVERSITY)
171 new_ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; 160 new_ant.rx = other_antenna;
172 161
173 if (ant->flags & ANTENNA_TX_DIVERSITY) 162 if (ant->flags & ANTENNA_TX_DIVERSITY)
174 new_ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; 163 new_ant.tx = other_antenna;
175 164
176 rt2x00lib_config_antenna(rt2x00dev, new_ant); 165 rt2x00lib_config_antenna(rt2x00dev, new_ant);
177} 166}
@@ -190,8 +179,8 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
190 * after that update the history with the current value. 179 * after that update the history with the current value.
191 */ 180 */
192 rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev); 181 rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
193 rssi_old = rt2x00link_antenna_get_rssi_rx_history(rt2x00dev); 182 rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
194 rt2x00link_antenna_update_rssi_rx_history(rt2x00dev, rssi_curr); 183 rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
195 184
196 /* 185 /*
197 * Legacy driver indicates that we should swap antenna's 186 * Legacy driver indicates that we should swap antenna's
@@ -216,7 +205,7 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
216 rt2x00lib_config_antenna(rt2x00dev, new_ant); 205 rt2x00lib_config_antenna(rt2x00dev, new_ant);
217} 206}
218 207
219static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) 208static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
220{ 209{
221 struct link_ant *ant = &rt2x00dev->link.ant; 210 struct link_ant *ant = &rt2x00dev->link.ant;
222 unsigned int flags = ant->flags; 211 unsigned int flags = ant->flags;
@@ -238,7 +227,7 @@ static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
238 if (!(ant->flags & ANTENNA_RX_DIVERSITY) && 227 if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
239 !(ant->flags & ANTENNA_TX_DIVERSITY)) { 228 !(ant->flags & ANTENNA_TX_DIVERSITY)) {
240 ant->flags = 0; 229 ant->flags = 0;
241 return; 230 return true;
242 } 231 }
243 232
244 /* Update flags */ 233 /* Update flags */
@@ -250,10 +239,15 @@ static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
250 * the data. The latter should only be performed once 239 * the data. The latter should only be performed once
251 * every 2 seconds. 240 * every 2 seconds.
252 */ 241 */
253 if (ant->flags & ANTENNA_MODE_SAMPLE) 242 if (ant->flags & ANTENNA_MODE_SAMPLE) {
254 rt2x00lib_antenna_diversity_sample(rt2x00dev); 243 rt2x00lib_antenna_diversity_sample(rt2x00dev);
255 else if (rt2x00dev->link.count & 1) 244 return true;
245 } else if (rt2x00dev->link.count & 1) {
256 rt2x00lib_antenna_diversity_eval(rt2x00dev); 246 rt2x00lib_antenna_diversity_eval(rt2x00dev);
247 return true;
248 }
249
250 return false;
257} 251}
258 252
259void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, 253void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
@@ -451,15 +445,12 @@ static void rt2x00link_tuner(struct work_struct *work)
451 rt2x00leds_led_quality(rt2x00dev, link->avg_rssi); 445 rt2x00leds_led_quality(rt2x00dev, link->avg_rssi);
452 446
453 /* 447 /*
454 * Evaluate antenna setup, make this the last step since this could 448 * Evaluate antenna setup, make this the last step when
455 * possibly reset some statistics. 449 * rt2x00lib_antenna_diversity made changes the quality
456 */ 450 * statistics will be reset.
457 rt2x00lib_antenna_diversity(rt2x00dev);
458
459 /*
460 * Reset the quality counters which recounted during each period.
461 */ 451 */
462 rt2x00link_reset_qual(rt2x00dev); 452 if (rt2x00lib_antenna_diversity(rt2x00dev))
453 rt2x00link_reset_qual(rt2x00dev);
463 454
464 /* 455 /*
465 * Increase tuner counter, and reschedule the next link tuner run. 456 * Increase tuner counter, and reschedule the next link tuner run.