diff options
| author | Nick Kossifidis <mickflemm@gmail.com> | 2011-02-03 18:41:02 -0500 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-02-21 14:50:01 -0500 |
| commit | 573cfde7aaeaadb0fd356ff2a14bdf9238967661 (patch) | |
| tree | 9be5fe3b98430e708a1d1b7581558c6a943be823 | |
| parent | 28bec7b845e10b68e6ba1ade5de0fc566690fc61 (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>
| -rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 142 |
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 | */ | ||
| 288 | static 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 |
