ath5k: Fix fast channel switching
Nick Kossifidis
maintainerPATCH 1/1 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 <[email protected]>
--- drivers/net/wireless/ath/ath5k/phy.c | 142 +++++++++++++++++++++------------- 1 files changed, 87 insertions(+), 55 deletions(-)
drivers/net/wireless/ath/ath5k/phy.c +87 -55
@@ -282,6 +282,34 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah)return 0 ; } +/* +* Wait for synth to settle +*/ +static void ath5k_hw_wait_for_synth (struct ath5k_hw *ah, +struct ieee80211_channel *channel) +{ +/* +* On 5211+ read activation -> rx delay +* and use it (100ns steps). +*/ +if (ah->ah_version !=AR5K_AR5210 ) { +u32 delay; + delay =ath5k_hw_reg_read (ah,AR5K_PHY_RX_DELAY ) & +AR5K_PHY_RX_DELAY_M ; + delay = (channel->hw_value &CHANNEL_CCK ) ? + ((delay <<2 ) /22 ) : (delay /10 ); +if (ah->ah_bwmode ==AR5K_BWMODE_10MHZ ) + delay = delay <<1 ; +if (ah->ah_bwmode ==AR5K_BWMODE_5MHZ ) + delay = delay <<2 ; +/* XXX: /2 on turbo ? Let's be safe +* for now */ +udelay (100 + delay); + }else { +mdelay (1 ); + } +} +/**********************\ * RF Gain optimization *
@@ -3237,6 +3265,13 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,/* Failed */ if (i >=100 )return -EIO ; + +/* Set channel and wait for synth */ + ret =ath5k_hw_channel (ah, channel); +if (ret) +return ret; + +ath5k_hw_wait_for_synth (ah, channel); }/*
@@ -3251,13 +3286,53 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,if (ret)return ret; +/* Write OFDM timings on 5212*/ +if (ah->ah_version ==AR5K_AR5212 && + channel->hw_value &CHANNEL_OFDM ) { + + ret =ath5k_hw_write_ofdm_timings (ah, channel); +if (ret) +return ret; + +/* Spur info is available only from EEPROM versions +* greater than 5.3, but the EEPROM routines will use +* static values for older versions */ +if (ah->ah_mac_srev >=AR5K_SREV_AR5424 ) +ath5k_hw_set_spur_mitigation_filter (ah, + channel); + } + +/* If we used fast channel switching +* we are done, release RF bus and +* fire up NF calibration. +* +* Note: Only NF calibration due to +* channel change, not AGC calibration +* since AGC is still running ! +*/ +if (fast) { +/* +* Release RF Bus grant +*/ +AR5K_REG_DISABLE_BITS (ah,AR5K_PHY_RFBUS_REQ , +AR5K_PHY_RFBUS_REQ_REQUEST ); + +/* +* Start NF calibration +*/ +AR5K_REG_ENABLE_BITS (ah,AR5K_PHY_AGCCTL , +AR5K_PHY_AGCCTL_NF ); + +return ret; + } +/* * For 5210 we do all initialization using * initvals, so we don't have to modify * any settings (5210 also only supports * a/aturbo modes) */ -if ((ah->ah_version !=AR5K_AR5210 ) && !fast) { +if (ah->ah_version !=AR5K_AR5210 ) {/* * Write initial RF gain settings
@@ -3276,22 +3351,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,if (ret)return ret; -/* Write OFDM timings on 5212*/ -if (ah->ah_version ==AR5K_AR5212 && - channel->hw_value &CHANNEL_OFDM ) { - - ret =ath5k_hw_write_ofdm_timings (ah, channel); -if (ret) -return ret; - -/* Spur info is available only from EEPROM versions -* greater than 5.3, but the EEPROM routines will use -* static values for older versions */ -if (ah->ah_mac_srev >=AR5K_SREV_AR5424 ) -ath5k_hw_set_spur_mitigation_filter (ah, - channel); - } -/*Enable/disable 802.11b mode on 5111 (enable 2111 frequency converter + CCK)*/ if (ah->ah_radio ==AR5K_RF5111 ) {
@@ -3322,47 +3381,20 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,*/ ath5k_hw_reg_write (ah,AR5K_PHY_ACT_ENABLE ,AR5K_PHY_ACT ); +ath5k_hw_wait_for_synth (ah, channel); +/* -* On 5211+ read activation -> rx delay -* and use it. +* Perform ADC test to see if baseband is ready +* Set tx hold and check adc test register */ -if (ah->ah_version !=AR5K_AR5210 ) { -u32 delay; - delay =ath5k_hw_reg_read (ah,AR5K_PHY_RX_DELAY ) & -AR5K_PHY_RX_DELAY_M ; - delay = (channel->hw_value &CHANNEL_CCK ) ? - ((delay <<2 ) /22 ) : (delay /10 ); -if (ah->ah_bwmode ==AR5K_BWMODE_10MHZ ) - delay = delay <<1 ; -if (ah->ah_bwmode ==AR5K_BWMODE_5MHZ ) - delay = delay <<2 ; -/* XXX: /2 on turbo ? Let's be safe -* for now */ -udelay (100 + delay); - }else { -mdelay (1 ); - } - -if (fast) -/* -* Release RF Bus grant -*/ -AR5K_REG_DISABLE_BITS (ah,AR5K_PHY_RFBUS_REQ , -AR5K_PHY_RFBUS_REQ_REQUEST ); -else { -/* -* Perform ADC test to see if baseband is ready -* Set tx hold and check adc test register -*/ - phy_tst1 =ath5k_hw_reg_read (ah,AR5K_PHY_TST1 ); -ath5k_hw_reg_write (ah,AR5K_PHY_TST1_TXHOLD ,AR5K_PHY_TST1 ); -for (i =0 ; i <=20 ; i++) { -if (!(ath5k_hw_reg_read (ah,AR5K_PHY_ADC_TEST ) &0x10 )) -break ; -udelay (200 ); - } -ath5k_hw_reg_write (ah, phy_tst1,AR5K_PHY_TST1 ); + phy_tst1 =ath5k_hw_reg_read (ah,AR5K_PHY_TST1 ); +ath5k_hw_reg_write (ah,AR5K_PHY_TST1_TXHOLD ,AR5K_PHY_TST1 ); +for (i =0 ; i <=20 ; i++) { +if (!(ath5k_hw_reg_read (ah,AR5K_PHY_ADC_TEST ) &0x10 )) +break ; +udelay (200 ); } +ath5k_hw_reg_write (ah, phy_tst1,AR5K_PHY_TST1 );/* * Start automatic gain control calibration