aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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-21 14:50:01 -0500
commit573cfde7aaeaadb0fd356ff2a14bdf9238967661 (patch)
tree9be5fe3b98430e708a1d1b7581558c6a943be823 /drivers
parent28bec7b845e10b68e6ba1ade5de0fc566690fc61 (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 https://bugzilla.kernel.org/show_bug.cgi?id=27382 Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-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 c44111fc98b7..62ce2f4e8605 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 *
@@ -3238,6 +3266,13 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3238 /* Failed */ 3266 /* Failed */
3239 if (i >= 100) 3267 if (i >= 100)
3240 return -EIO; 3268 return -EIO;
3269
3270 /* Set channel and wait for synth */
3271 ret = ath5k_hw_channel(ah, channel);
3272 if (ret)
3273 return ret;
3274
3275 ath5k_hw_wait_for_synth(ah, channel);
3241 } 3276 }
3242 3277
3243 /* 3278 /*
@@ -3252,13 +3287,53 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3252 if (ret) 3287 if (ret)
3253 return ret; 3288 return ret;
3254 3289
3290 /* Write OFDM timings on 5212*/
3291 if (ah->ah_version == AR5K_AR5212 &&
3292 channel->hw_value & CHANNEL_OFDM) {
3293
3294 ret = ath5k_hw_write_ofdm_timings(ah, channel);
3295 if (ret)
3296 return ret;
3297
3298 /* Spur info is available only from EEPROM versions
3299 * greater than 5.3, but the EEPROM routines will use
3300 * static values for older versions */
3301 if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
3302 ath5k_hw_set_spur_mitigation_filter(ah,
3303 channel);
3304 }
3305
3306 /* If we used fast channel switching
3307 * we are done, release RF bus and
3308 * fire up NF calibration.
3309 *
3310 * Note: Only NF calibration due to
3311 * channel change, not AGC calibration
3312 * since AGC is still running !
3313 */
3314 if (fast) {
3315 /*
3316 * Release RF Bus grant
3317 */
3318 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
3319 AR5K_PHY_RFBUS_REQ_REQUEST);
3320
3321 /*
3322 * Start NF calibration
3323 */
3324 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
3325 AR5K_PHY_AGCCTL_NF);
3326
3327 return ret;
3328 }
3329
3255 /* 3330 /*
3256 * For 5210 we do all initialization using 3331 * For 5210 we do all initialization using
3257 * initvals, so we don't have to modify 3332 * initvals, so we don't have to modify
3258 * any settings (5210 also only supports 3333 * any settings (5210 also only supports
3259 * a/aturbo modes) 3334 * a/aturbo modes)
3260 */ 3335 */
3261 if ((ah->ah_version != AR5K_AR5210) && !fast) { 3336 if (ah->ah_version != AR5K_AR5210) {
3262 3337
3263 /* 3338 /*
3264 * Write initial RF gain settings 3339 * Write initial RF gain settings
@@ -3277,22 +3352,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3277 if (ret) 3352 if (ret)
3278 return ret; 3353 return ret;
3279 3354
3280 /* Write OFDM timings on 5212*/
3281 if (ah->ah_version == AR5K_AR5212 &&
3282 channel->hw_value & CHANNEL_OFDM) {
3283
3284 ret = ath5k_hw_write_ofdm_timings(ah, channel);
3285 if (ret)
3286 return ret;
3287
3288 /* Spur info is available only from EEPROM versions
3289 * greater than 5.3, but the EEPROM routines will use
3290 * static values for older versions */
3291 if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
3292 ath5k_hw_set_spur_mitigation_filter(ah,
3293 channel);
3294 }
3295
3296 /*Enable/disable 802.11b mode on 5111 3355 /*Enable/disable 802.11b mode on 5111
3297 (enable 2111 frequency converter + CCK)*/ 3356 (enable 2111 frequency converter + CCK)*/
3298 if (ah->ah_radio == AR5K_RF5111) { 3357 if (ah->ah_radio == AR5K_RF5111) {
@@ -3323,47 +3382,20 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3323 */ 3382 */
3324 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); 3383 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
3325 3384
3385 ath5k_hw_wait_for_synth(ah, channel);
3386
3326 /* 3387 /*
3327 * On 5211+ read activation -> rx delay 3388 * Perform ADC test to see if baseband is ready
3328 * and use it. 3389 * Set tx hold and check adc test register
3329 */ 3390 */
3330 if (ah->ah_version != AR5K_AR5210) { 3391 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
3331 u32 delay; 3392 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
3332 delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & 3393 for (i = 0; i <= 20; i++) {
3333 AR5K_PHY_RX_DELAY_M; 3394 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
3334 delay = (channel->hw_value & CHANNEL_CCK) ? 3395 break;
3335 ((delay << 2) / 22) : (delay / 10); 3396 udelay(200);
3336 if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
3337 delay = delay << 1;
3338 if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
3339 delay = delay << 2;
3340 /* XXX: /2 on turbo ? Let's be safe
3341 * for now */
3342 udelay(100 + delay);
3343 } else {
3344 mdelay(1);
3345 }
3346
3347 if (fast)
3348 /*
3349 * Release RF Bus grant
3350 */
3351 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
3352 AR5K_PHY_RFBUS_REQ_REQUEST);
3353 else {
3354 /*
3355 * Perform ADC test to see if baseband is ready
3356 * Set tx hold and check adc test register
3357 */
3358 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
3359 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
3360 for (i = 0; i <= 20; i++) {
3361 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
3362 break;
3363 udelay(200);
3364 }
3365 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
3366 } 3397 }
3398 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
3367 3399
3368 /* 3400 /*
3369 * Start automatic gain control calibration 3401 * Start automatic gain control calibration