aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-11-01 19:38:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-21 11:06:05 -0500
commit6d64360ac56cda95243f15738a06f2a123c663e5 (patch)
tree61005d0d992773ead469590e63477199f0e63f7e /drivers
parent8058409c4fb8e38632207d572ed29943d2585520 (diff)
rt2x00: Fix BUG_ON() with antenna handling
With the new configuration handling, and more specifically splitting the configuration of the antenna from the normal configuration steps allowed a BUG_ON() to be triggered in the driver because the SW_DIVERSITY was send to the driver. This fixes that by catching the value early in rt2x00config.c and replacing it with a sensible value. This also fixes a problem where the antenna is not being initialized at all when the radio is enabled. Since it no longer is part of the mac80211 configuration the only place where rt2x00 configured it was the SW diversity handler. Obviously this is broken for all non-diversity hardware and breaks SW diversity due to a broken initialization. When the radio is enabled the antenna will be configured once as soon as the config() callback function is called. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c35
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c13
5 files changed, 51 insertions, 24 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index f85eedbbad68..8fa971ccfddd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -723,8 +723,7 @@ struct rt2x00_dev {
723 723
724 /* 724 /*
725 * This is the default TX/RX antenna setup as indicated 725 * This is the default TX/RX antenna setup as indicated
726 * by the device's EEPROM. When mac80211 sets its 726 * by the device's EEPROM.
727 * antenna value to 0 we should be using these values.
728 */ 727 */
729 struct antenna_setup default_ant; 728 struct antenna_setup default_ant;
730 729
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 3e4eee3ab7d2..1059b4d1868f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -109,15 +109,32 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
109} 109}
110 110
111void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, 111void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
112 enum antenna rx, enum antenna tx) 112 struct antenna_setup *ant)
113{ 113{
114 struct antenna_setup ant; 114 /*
115 115 * Failsafe: Make sure we are not sending the
116 ant.rx = rx; 116 * ANTENNA_SW_DIVERSITY state to the driver.
117 ant.tx = tx; 117 * If that happes fallback to hardware default,
118 * or our own default.
119 */
120 if (ant->rx == ANTENNA_SW_DIVERSITY) {
121 if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
122 ant->rx = ANTENNA_B;
123 else
124 ant->rx = rt2x00dev->default_ant.rx;
125 }
126 if (ant->tx == ANTENNA_SW_DIVERSITY) {
127 if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
128 ant->tx = ANTENNA_B;
129 else
130 ant->tx = rt2x00dev->default_ant.tx;
131 }
118 132
119 if (rx == rt2x00dev->link.ant.active.rx && 133 /*
120 tx == rt2x00dev->link.ant.active.tx) 134 * Only reconfigure when something has changed.
135 */
136 if (ant->rx == rt2x00dev->link.ant.active.rx &&
137 ant->tx == rt2x00dev->link.ant.active.tx)
121 return; 138 return;
122 139
123 /* 140 /*
@@ -132,12 +149,12 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
132 * The latter is required since we need to recalibrate the 149 * The latter is required since we need to recalibrate the
133 * noise-sensitivity ratio for the new setup. 150 * noise-sensitivity ratio for the new setup.
134 */ 151 */
135 rt2x00dev->ops->lib->config_ant(rt2x00dev, &ant); 152 rt2x00dev->ops->lib->config_ant(rt2x00dev, ant);
136 153
137 rt2x00lib_reset_link_tuner(rt2x00dev); 154 rt2x00lib_reset_link_tuner(rt2x00dev);
138 rt2x00_reset_link_ant_rssi(&rt2x00dev->link); 155 rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
139 156
140 memcpy(&rt2x00dev->link.ant.active, &ant, sizeof(ant)); 157 memcpy(&rt2x00dev->link.ant.active, ant, sizeof(*ant));
141 158
142 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 159 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
143 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); 160 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index a8fee68a419e..e8ca1cbfeb90 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -176,13 +176,14 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
176 176
177static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) 177static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev)
178{ 178{
179 enum antenna rx = rt2x00dev->link.ant.active.rx; 179 struct antenna_setup ant;
180 enum antenna tx = rt2x00dev->link.ant.active.tx;
181 int sample_a = 180 int sample_a =
182 rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A); 181 rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A);
183 int sample_b = 182 int sample_b =
184 rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B); 183 rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B);
185 184
185 memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant));
186
186 /* 187 /*
187 * We are done sampling. Now we should evaluate the results. 188 * We are done sampling. Now we should evaluate the results.
188 */ 189 */
@@ -200,21 +201,22 @@ static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev)
200 return; 201 return;
201 202
202 if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) 203 if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
203 rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; 204 ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
204 205
205 if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) 206 if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
206 tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; 207 ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
207 208
208 rt2x00lib_config_antenna(rt2x00dev, rx, tx); 209 rt2x00lib_config_antenna(rt2x00dev, &ant);
209} 210}
210 211
211static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) 212static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev)
212{ 213{
213 enum antenna rx = rt2x00dev->link.ant.active.rx; 214 struct antenna_setup ant;
214 enum antenna tx = rt2x00dev->link.ant.active.tx;
215 int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link); 215 int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link);
216 int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr); 216 int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr);
217 217
218 memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant));
219
218 /* 220 /*
219 * Legacy driver indicates that we should swap antenna's 221 * Legacy driver indicates that we should swap antenna's
220 * when the difference in RSSI is greater that 5. This 222 * when the difference in RSSI is greater that 5. This
@@ -230,12 +232,12 @@ static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev)
230 rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; 232 rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE;
231 233
232 if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) 234 if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
233 rx = (rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; 235 ant.rx = (ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
234 236
235 if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) 237 if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
236 tx = (tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; 238 ant.tx = (ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
237 239
238 rt2x00lib_config_antenna(rt2x00dev, rx, tx); 240 rt2x00lib_config_antenna(rt2x00dev, &ant);
239} 241}
240 242
241static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) 243static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index c52ee218e4f5..0c3a3559ba48 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -93,7 +93,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
93 struct rt2x00_intf *intf, 93 struct rt2x00_intf *intf,
94 struct ieee80211_bss_conf *conf); 94 struct ieee80211_bss_conf *conf);
95void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, 95void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
96 enum antenna rx, enum antenna tx); 96 struct antenna_setup *ant);
97void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, 97void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
98 struct ieee80211_conf *conf, 98 struct ieee80211_conf *conf,
99 const unsigned int changed_flags); 99 const unsigned int changed_flags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 188f89177bd8..48636b0dd895 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -339,7 +339,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
339{ 339{
340 struct rt2x00_dev *rt2x00dev = hw->priv; 340 struct rt2x00_dev *rt2x00dev = hw->priv;
341 struct ieee80211_conf *conf = &hw->conf; 341 struct ieee80211_conf *conf = &hw->conf;
342 int radio_on;
343 int status; 342 int status;
344 343
345 /* 344 /*
@@ -356,7 +355,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
356 * some configuration parameters (e.g. channel and antenna values) can 355 * some configuration parameters (e.g. channel and antenna values) can
357 * only be set when the radio is enabled. 356 * only be set when the radio is enabled.
358 */ 357 */
359 radio_on = test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
360 if (conf->radio_enabled) { 358 if (conf->radio_enabled) {
361 /* For programming the values, we have to turn RX off */ 359 /* For programming the values, we have to turn RX off */
362 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); 360 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
@@ -372,6 +370,17 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
372 */ 370 */
373 rt2x00lib_config(rt2x00dev, conf, changed); 371 rt2x00lib_config(rt2x00dev, conf, changed);
374 372
373 /*
374 * The radio was enabled, configure the antenna to the
375 * default settings, the link tuner will later start
376 * continue configuring the antenna based on the software
377 * diversity. But for non-diversity configurations, we need
378 * to have configured the correct state now.
379 */
380 if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED)
381 rt2x00lib_config_antenna(rt2x00dev,
382 &rt2x00dev->default_ant);
383
375 /* Turn RX back on */ 384 /* Turn RX back on */
376 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); 385 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
377 } else { 386 } else {