aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kossifidis <mickflemm@gmail.com>2011-02-03 18:41:02 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-07 16:18:27 -0500
commitc210de8f88215db31cf3529c9763fc3124d6e09d (patch)
treea2aa3a4e5dc8a8998ac8349390ecf20c61a3544b
parent80b38fffab9a2d86c252addce5a520dcf8f2fc66 (diff)
ath5k: Fix fast channel switching
Fast channel change fixes: a) Always set OFDM timings b) Don't re-activate PHY c) Enable only NF calibration, not AGC Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c142
1 files changed, 87 insertions, 55 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 78c26fdccad1..d673ab2f6cda 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -282,6 +282,34 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah)
282 return 0; 282 return 0;
283} 283}
284 284
285/*
286 * Wait for synth to settle
287 */
288static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
289 struct ieee80211_channel *channel)
290{
291 /*
292 * On 5211+ read activation -> rx delay
293 * and use it (100ns steps).
294 */
295 if (ah->ah_version != AR5K_AR5210) {
296 u32 delay;
297 delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
298 AR5K_PHY_RX_DELAY_M;
299 delay = (channel->hw_value & CHANNEL_CCK) ?
300 ((delay << 2) / 22) : (delay / 10);
301 if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
302 delay = delay << 1;
303 if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
304 delay = delay << 2;
305 /* XXX: /2 on turbo ? Let's be safe
306 * for now */
307 udelay(100 + delay);
308 } else {
309 mdelay(1);
310 }
311}
312
285 313
286/**********************\ 314/**********************\
287* RF Gain optimization * 315* RF Gain optimization *
@@ -3237,6 +3265,13 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3237 /* Failed */ 3265 /* Failed */
3238 if (i >= 100) 3266 if (i >= 100)
3239 return -EIO; 3267 return -EIO;
3268
3269 /* Set channel and wait for synth */
3270 ret = ath5k_hw_channel(ah, channel);
3271 if (ret)
3272 return ret;
3273
3274 ath5k_hw_wait_for_synth(ah, channel);
3240 } 3275 }
3241 3276
3242 /* 3277 /*
@@ -3251,13 +3286,53 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3251 if (ret) 3286 if (ret)
3252 return ret; 3287 return ret;
3253 3288
3289 /* Write OFDM timings on 5212*/
3290 if (ah->ah_version == AR5K_AR5212 &&
3291 channel->hw_value & CHANNEL_OFDM) {
3292
3293 ret = ath5k_hw_write_ofdm_timings(ah, channel);
3294 if (ret)
3295 return ret;
3296
3297 /* Spur info is available only from EEPROM versions
3298 * greater than 5.3, but the EEPROM routines will use
3299 * static values for older versions */
3300 if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
3301 ath5k_hw_set_spur_mitigation_filter(ah,
3302 channel);
3303 }
3304
3305 /* If we used fast channel switching
3306 * we are done, release RF bus and
3307 * fire up NF calibration.
3308 *
3309 * Note: Only NF calibration due to
3310 * channel change, not AGC calibration
3311 * since AGC is still running !
3312 */
3313 if (fast) {
3314 /*
3315 * Release RF Bus grant
3316 */
3317 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
3318 AR5K_PHY_RFBUS_REQ_REQUEST);
3319
3320 /*
3321 * Start NF calibration
3322 */
3323 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
3324 AR5K_PHY_AGCCTL_NF);
3325
3326 return ret;
3327 }
3328
3254 /* 3329 /*
3255 * For 5210 we do all initialization using 3330 * For 5210 we do all initialization using
3256 * initvals, so we don't have to modify 3331 * initvals, so we don't have to modify
3257 * any settings (5210 also only supports 3332 * any settings (5210 also only supports
3258 * a/aturbo modes) 3333 * a/aturbo modes)
3259 */ 3334 */
3260 if ((ah->ah_version != AR5K_AR5210) && !fast) { 3335 if (ah->ah_version != AR5K_AR5210) {
3261 3336
3262 /* 3337 /*
3263 * Write initial RF gain settings 3338 * Write initial RF gain settings
@@ -3276,22 +3351,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3276 if (ret) 3351 if (ret)
3277 return ret; 3352 return ret;
3278 3353
3279 /* Write OFDM timings on 5212*/
3280 if (ah->ah_version == AR5K_AR5212 &&
3281 channel->hw_value & CHANNEL_OFDM) {
3282
3283 ret = ath5k_hw_write_ofdm_timings(ah, channel);
3284 if (ret)
3285 return ret;
3286
3287 /* Spur info is available only from EEPROM versions
3288 * greater than 5.3, but the EEPROM routines will use
3289 * static values for older versions */
3290 if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
3291 ath5k_hw_set_spur_mitigation_filter(ah,
3292 channel);
3293 }
3294
3295 /*Enable/disable 802.11b mode on 5111 3354 /*Enable/disable 802.11b mode on 5111
3296 (enable 2111 frequency converter + CCK)*/ 3355 (enable 2111 frequency converter + CCK)*/
3297 if (ah->ah_radio == AR5K_RF5111) { 3356 if (ah->ah_radio == AR5K_RF5111) {
@@ -3322,47 +3381,20 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3322 */ 3381 */
3323 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); 3382 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
3324 3383
3384 ath5k_hw_wait_for_synth(ah, channel);
3385
3325 /* 3386 /*
3326 * On 5211+ read activation -> rx delay 3387 * Perform ADC test to see if baseband is ready
3327 * and use it. 3388 * Set tx hold and check adc test register
3328 */ 3389 */
3329 if (ah->ah_version != AR5K_AR5210) { 3390 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
3330 u32 delay; 3391 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
3331 delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & 3392 for (i = 0; i <= 20; i++) {
3332 AR5K_PHY_RX_DELAY_M; 3393 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
3333 delay = (channel->hw_value & CHANNEL_CCK) ? 3394 break;
3334 ((delay << 2) / 22) : (delay / 10); 3395 udelay(200);
3335 if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
3336 delay = delay << 1;
3337 if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
3338 delay = delay << 2;
3339 /* XXX: /2 on turbo ? Let's be safe
3340 * for now */
3341 udelay(100 + delay);
3342 } else {
3343 mdelay(1);
3344 }
3345
3346 if (fast)
3347 /*
3348 * Release RF Bus grant
3349 */
3350 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
3351 AR5K_PHY_RFBUS_REQ_REQUEST);
3352 else {
3353 /*
3354 * Perform ADC test to see if baseband is ready
3355 * Set tx hold and check adc test register
3356 */
3357 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
3358 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
3359 for (i = 0; i <= 20; i++) {
3360 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
3361 break;
3362 udelay(200);
3363 }
3364 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
3365 } 3396 }
3397 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
3366 3398
3367 /* 3399 /*
3368 * Start automatic gain control calibration 3400 * Start automatic gain control calibration