aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorNick Kossifidis <mickflemm@gmail.com>2010-11-23 14:39:28 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-30 13:53:43 -0500
commit8aec7af99b1e4594c4bb9e1c48005e6111f97e8e (patch)
treeb89d4466afda78ba949d03f32d0efb8f3c75ecd6 /drivers/net
parent4c57581d939fd0f8f244b9730812069f4dac308a (diff)
ath5k: Support synth-only channel change for AR2413/AR5413
* Add synth-only channel change for AR2413/5413. When we call ath5k_reset with a channel ath5k_hw_reset will first try to set channel on PHY while PHY is running instead of doing a normal full reset. To do this phy_init has to change to implement this functionality. * Clean up change_channel flag, what it really did was skip PCU registers when setting initvals. This is done because on reset PCU registers are not affected (except the registers we set in pcu init and -due to hw problems- TSF). Use a new skip_pcu flag that's not misleading instead. In the future we might use that to also skip PCU reset and save us the TSF etc problems (needs testing because standard practice is to reset everything). * Use fast channel change only when setting channel, and set skip_pcu to false only on init. When we reset the card due to DMA or PHY problems skip pcu but never do a fast channel change. Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c17
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c64
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c267
4 files changed, 218 insertions, 134 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index e2588308e67..385b91911ab 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1183,7 +1183,7 @@ void ath5k_unregister_leds(struct ath5k_softc *sc);
1183int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); 1183int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
1184int ath5k_hw_on_hold(struct ath5k_hw *ah); 1184int ath5k_hw_on_hold(struct ath5k_hw *ah);
1185int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, 1185int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1186 struct ieee80211_channel *channel, bool change_channel); 1186 struct ieee80211_channel *channel, bool fast, bool skip_pcu);
1187int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, 1187int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
1188 bool is_set); 1188 bool is_set);
1189/* Power management functions */ 1189/* Power management functions */
@@ -1324,7 +1324,7 @@ void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode);
1324int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); 1324int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
1325/* Init function */ 1325/* Init function */
1326int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, 1326int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
1327 u8 mode, u8 ee_mode, u8 freq); 1327 u8 mode, u8 ee_mode, u8 freq, bool fast);
1328 1328
1329/* 1329/*
1330 * Functions used internaly 1330 * Functions used internaly
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 526d8bc412c..33cd1bc4a71 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -80,7 +80,8 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
80MODULE_LICENSE("Dual BSD/GPL"); 80MODULE_LICENSE("Dual BSD/GPL");
81MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); 81MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
82 82
83static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); 83static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
84 bool skip_pcu);
84static int ath5k_beacon_update(struct ieee80211_hw *hw, 85static int ath5k_beacon_update(struct ieee80211_hw *hw,
85 struct ieee80211_vif *vif); 86 struct ieee80211_vif *vif);
86static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); 87static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
@@ -496,7 +497,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
496 * hardware at the new frequency, and then re-enable 497 * hardware at the new frequency, and then re-enable
497 * the relevant bits of the h/w. 498 * the relevant bits of the h/w.
498 */ 499 */
499 return ath5k_reset(sc, chan); 500 return ath5k_reset(sc, chan, true);
500} 501}
501 502
502static void 503static void
@@ -2327,7 +2328,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
2327 if (needreset) { 2328 if (needreset) {
2328 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, 2329 ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
2329 "TX queues stuck, resetting\n"); 2330 "TX queues stuck, resetting\n");
2330 ath5k_reset(sc, sc->curchan); 2331 ath5k_reset(sc, NULL, true);
2331 } 2332 }
2332 2333
2333 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 2334 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2407,7 +2408,7 @@ ath5k_init(struct ath5k_softc *sc)
2407 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | 2408 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
2408 AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; 2409 AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
2409 2410
2410 ret = ath5k_reset(sc, NULL); 2411 ret = ath5k_reset(sc, NULL, false);
2411 if (ret) 2412 if (ret)
2412 goto done; 2413 goto done;
2413 2414
@@ -2506,7 +2507,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2506 * This should be called with sc->lock. 2507 * This should be called with sc->lock.
2507 */ 2508 */
2508static int 2509static int
2509ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) 2510ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
2511 bool skip_pcu)
2510{ 2512{
2511 struct ath5k_hw *ah = sc->ah; 2513 struct ath5k_hw *ah = sc->ah;
2512 int ret; 2514 int ret;
@@ -2523,7 +2525,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
2523 sc->curchan = chan; 2525 sc->curchan = chan;
2524 sc->curband = &sc->sbands[chan->band]; 2526 sc->curband = &sc->sbands[chan->band];
2525 } 2527 }
2526 ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); 2528 ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
2529 skip_pcu);
2527 if (ret) { 2530 if (ret) {
2528 ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); 2531 ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
2529 goto err; 2532 goto err;
@@ -2569,7 +2572,7 @@ static void ath5k_reset_work(struct work_struct *work)
2569 reset_work); 2572 reset_work);
2570 2573
2571 mutex_lock(&sc->lock); 2574 mutex_lock(&sc->lock);
2572 ath5k_reset(sc, sc->curchan); 2575 ath5k_reset(sc, NULL, true);
2573 mutex_unlock(&sc->lock); 2576 mutex_unlock(&sc->lock);
2574} 2577}
2575 2578
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 9392320eb30..1b6fcf9e097 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -3223,7 +3223,7 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
3223\*************/ 3223\*************/
3224 3224
3225int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, 3225int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3226 u8 mode, u8 ee_mode, u8 freq) 3226 u8 mode, u8 ee_mode, u8 freq, bool fast)
3227{ 3227{
3228 struct ieee80211_channel *curr_channel; 3228 struct ieee80211_channel *curr_channel;
3229 int ret, i; 3229 int ret, i;
@@ -3232,11 +3232,37 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3232 ret = 0; 3232 ret = 0;
3233 3233
3234 /* 3234 /*
3235 * Sanity check for fast flag
3236 * Don't try fast channel change when changing modulation
3237 * mode/band. We check for chip compatibility on
3238 * ath5k_hw_reset.
3239 */
3240 curr_channel = ah->ah_current_channel;
3241 if (fast && (channel->hw_value != curr_channel->hw_value))
3242 return -EINVAL;
3243
3244 /*
3245 * On fast channel change we only set the synth parameters
3246 * while PHY is running, enable calibration and skip the rest.
3247 */
3248 if (fast) {
3249 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
3250 AR5K_PHY_RFBUS_REQ_REQUEST);
3251 for (i = 0; i < 100; i++) {
3252 if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT))
3253 break;
3254 udelay(5);
3255 }
3256 /* Failed */
3257 if (i >= 100)
3258 return -EIO;
3259 }
3260
3261 /*
3235 * If we don't change channel/mode skip 3262 * If we don't change channel/mode skip
3236 * tx powertable calculation and use the 3263 * tx powertable calculation and use the
3237 * cached one. 3264 * cached one.
3238 */ 3265 */
3239 curr_channel = ah->ah_current_channel;
3240 if ((channel->hw_value == curr_channel->hw_value) && 3266 if ((channel->hw_value == curr_channel->hw_value) &&
3241 (channel->center_freq == curr_channel->center_freq)) 3267 (channel->center_freq == curr_channel->center_freq))
3242 fast_txp = true; 3268 fast_txp = true;
@@ -3262,7 +3288,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3262 * any settings (5210 also only supports 3288 * any settings (5210 also only supports
3263 * a/aturbo modes) 3289 * a/aturbo modes)
3264 */ 3290 */
3265 if (ah->ah_version != AR5K_AR5210) { 3291 if ((ah->ah_version != AR5K_AR5210) && !fast) {
3266 3292
3267 /* 3293 /*
3268 * Write initial RF gain settings 3294 * Write initial RF gain settings
@@ -3308,7 +3334,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3308 AR5K_TXCFG_B_MODE); 3334 AR5K_TXCFG_B_MODE);
3309 } 3335 }
3310 3336
3311 } else { 3337 } else if (ah->ah_version == AR5K_AR5210) {
3312 mdelay(1); 3338 mdelay(1);
3313 /* Disable phy and wait */ 3339 /* Disable phy and wait */
3314 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); 3340 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
@@ -3345,18 +3371,26 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3345 mdelay(1); 3371 mdelay(1);
3346 } 3372 }
3347 3373
3348 /* 3374 if (fast)
3349 * Perform ADC test to see if baseband is ready 3375 /*
3350 * Set TX hold and check ADC test register 3376 * Release RF Bus grant
3351 */ 3377 */
3352 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); 3378 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
3353 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); 3379 AR5K_PHY_RFBUS_REQ_REQUEST);
3354 for (i = 0; i <= 20; i++) { 3380 else {
3355 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) 3381 /*
3356 break; 3382 * Perform ADC test to see if baseband is ready
3357 udelay(200); 3383 * Set tx hold and check adc test register
3384 */
3385 phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
3386 ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
3387 for (i = 0; i <= 20; i++) {
3388 if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
3389 break;
3390 udelay(200);
3391 }
3392 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
3358 } 3393 }
3359 ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
3360 3394
3361 /* 3395 /*
3362 * Start automatic gain control calibration 3396 * Start automatic gain control calibration
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index ec013103a6a..e02bcbbd7a8 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -938,7 +938,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
938\*********************/ 938\*********************/
939 939
940int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, 940int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
941 struct ieee80211_channel *channel, bool change_channel) 941 struct ieee80211_channel *channel, bool fast, bool skip_pcu)
942{ 942{
943 struct ath_common *common = ath5k_hw_common(ah); 943 struct ath_common *common = ath5k_hw_common(ah);
944 u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; 944 u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo;
@@ -952,6 +952,20 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
952 freq = 0; 952 freq = 0;
953 mode = 0; 953 mode = 0;
954 954
955 /*
956 * Sanity check for fast flag
957 * Fast channel change only available
958 * on AR2413/AR5413.
959 */
960 if (fast && (ah->ah_radio != AR5K_RF2413) &&
961 (ah->ah_radio != AR5K_RF5413))
962 fast = 0;
963
964 /* Disable sleep clock operation
965 * to avoid register access delay on certain
966 * PHY registers */
967 if (ah->ah_version == AR5K_AR5212)
968 ath5k_hw_set_sleep_clock(ah, false);
955 969
956 /* 970 /*
957 * Stop PCU 971 * Stop PCU
@@ -964,111 +978,137 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
964 * Note: If DMA didn't stop continue 978 * Note: If DMA didn't stop continue
965 * since only a reset will fix it. 979 * since only a reset will fix it.
966 */ 980 */
967 ath5k_hw_dma_stop(ah); 981 ret = ath5k_hw_dma_stop(ah);
982
983 /* RF Bus grant won't work if we have pending
984 * frames */
985 if (ret && fast) {
986 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
987 "DMA didn't stop, falling back to normal reset\n");
988 fast = 0;
989 /* Non fatal, just continue with
990 * normal reset */
991 ret = 0;
992 }
968 993
969 /* 994 switch (channel->hw_value & CHANNEL_MODES) {
970 * Save some registers before a reset 995 case CHANNEL_A:
971 */ 996 mode = AR5K_MODE_11A;
972 /*DCU/Antenna selection not available on 5210*/ 997 freq = AR5K_INI_RFGAIN_5GHZ;
973 if (ah->ah_version != AR5K_AR5210) { 998 ee_mode = AR5K_EEPROM_MODE_11A;
999 break;
1000 case CHANNEL_G:
974 1001
975 switch (channel->hw_value & CHANNEL_MODES) { 1002 if (ah->ah_version <= AR5K_AR5211) {
976 case CHANNEL_A:
977 mode = AR5K_MODE_11A;
978 freq = AR5K_INI_RFGAIN_5GHZ;
979 ee_mode = AR5K_EEPROM_MODE_11A;
980 break;
981 case CHANNEL_G:
982 mode = AR5K_MODE_11G;
983 freq = AR5K_INI_RFGAIN_2GHZ;
984 ee_mode = AR5K_EEPROM_MODE_11G;
985 break;
986 case CHANNEL_B:
987 mode = AR5K_MODE_11B;
988 freq = AR5K_INI_RFGAIN_2GHZ;
989 ee_mode = AR5K_EEPROM_MODE_11B;
990 break;
991 case CHANNEL_T:
992 mode = AR5K_MODE_11A_TURBO;
993 freq = AR5K_INI_RFGAIN_5GHZ;
994 ee_mode = AR5K_EEPROM_MODE_11A;
995 break;
996 case CHANNEL_TG:
997 if (ah->ah_version == AR5K_AR5211) {
998 ATH5K_ERR(ah->ah_sc,
999 "TurboG mode not available on 5211");
1000 return -EINVAL;
1001 }
1002 mode = AR5K_MODE_11G_TURBO;
1003 freq = AR5K_INI_RFGAIN_2GHZ;
1004 ee_mode = AR5K_EEPROM_MODE_11G;
1005 break;
1006 case CHANNEL_XR:
1007 if (ah->ah_version == AR5K_AR5211) {
1008 ATH5K_ERR(ah->ah_sc,
1009 "XR mode not available on 5211");
1010 return -EINVAL;
1011 }
1012 mode = AR5K_MODE_XR;
1013 freq = AR5K_INI_RFGAIN_5GHZ;
1014 ee_mode = AR5K_EEPROM_MODE_11A;
1015 break;
1016 default:
1017 ATH5K_ERR(ah->ah_sc, 1003 ATH5K_ERR(ah->ah_sc,
1018 "invalid channel: %d\n", channel->center_freq); 1004 "G mode not available on 5210/5211");
1019 return -EINVAL; 1005 return -EINVAL;
1020 } 1006 }
1021 1007
1022 if (change_channel) { 1008 mode = AR5K_MODE_11G;
1023 /* 1009 freq = AR5K_INI_RFGAIN_2GHZ;
1024 * Save frame sequence count 1010 ee_mode = AR5K_EEPROM_MODE_11G;
1025 * For revs. after Oahu, only save 1011 break;
1026 * seq num for DCU 0 (Global seq num) 1012 case CHANNEL_B:
1027 */
1028 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
1029
1030 for (i = 0; i < 10; i++)
1031 s_seq[i] = ath5k_hw_reg_read(ah,
1032 AR5K_QUEUE_DCU_SEQNUM(i));
1033 1013
1034 } else { 1014 if (ah->ah_version < AR5K_AR5211) {
1035 s_seq[0] = ath5k_hw_reg_read(ah, 1015 ATH5K_ERR(ah->ah_sc,
1036 AR5K_QUEUE_DCU_SEQNUM(0)); 1016 "B mode not available on 5210");
1037 } 1017 return -EINVAL;
1018 }
1038 1019
1039 /* TSF accelerates on AR5211 during reset 1020 mode = AR5K_MODE_11B;
1040 * As a workaround save it here and restore 1021 freq = AR5K_INI_RFGAIN_2GHZ;
1041 * it later so that it's back in time after 1022 ee_mode = AR5K_EEPROM_MODE_11B;
1042 * reset. This way it'll get re-synced on the 1023 break;
1043 * next beacon without breaking ad-hoc. 1024 case CHANNEL_T:
1044 * 1025 mode = AR5K_MODE_11A_TURBO;
1045 * On AR5212 TSF is almost preserved across a 1026 freq = AR5K_INI_RFGAIN_5GHZ;
1046 * reset so it stays back in time anyway and 1027 ee_mode = AR5K_EEPROM_MODE_11A;
1047 * we don't have to save/restore it. 1028 break;
1048 * 1029 case CHANNEL_TG:
1049 * XXX: Since this breaks power saving we have 1030 if (ah->ah_version == AR5K_AR5211) {
1050 * to disable power saving until we receive the 1031 ATH5K_ERR(ah->ah_sc,
1051 * next beacon, so we can resync beacon timers */ 1032 "TurboG mode not available on 5211");
1052 if (ah->ah_version == AR5K_AR5211) { 1033 return -EINVAL;
1053 tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
1054 tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
1055 }
1056 } 1034 }
1035 mode = AR5K_MODE_11G_TURBO;
1036 freq = AR5K_INI_RFGAIN_2GHZ;
1037 ee_mode = AR5K_EEPROM_MODE_11G;
1038 break;
1039 case CHANNEL_XR:
1040 if (ah->ah_version == AR5K_AR5211) {
1041 ATH5K_ERR(ah->ah_sc,
1042 "XR mode not available on 5211");
1043 return -EINVAL;
1044 }
1045 mode = AR5K_MODE_XR;
1046 freq = AR5K_INI_RFGAIN_5GHZ;
1047 ee_mode = AR5K_EEPROM_MODE_11A;
1048 break;
1049 default:
1050 ATH5K_ERR(ah->ah_sc,
1051 "invalid channel: %d\n", channel->center_freq);
1052 return -EINVAL;
1053 }
1057 1054
1058 if (ah->ah_version == AR5K_AR5212) { 1055 /*
1059 /* Restore normal 32/40MHz clock operation 1056 * If driver requested fast channel change and DMA has stopped
1060 * to avoid register access delay on certain 1057 * go on. If it fails continue with a normal reset.
1061 * PHY registers */ 1058 */
1062 ath5k_hw_set_sleep_clock(ah, false); 1059 if (fast) {
1060 ret = ath5k_hw_phy_init(ah, channel, mode,
1061 ee_mode, freq, true);
1062 if (ret) {
1063 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
1064 "fast chan change failed, falling back to normal reset\n");
1065 /* Non fatal, can happen eg.
1066 * on mode change */
1067 ret = 0;
1068 } else
1069 return 0;
1070 }
1063 1071
1064 /* Since we are going to write rf buffer 1072 /*
1065 * check if we have any pending gain_F 1073 * Save some registers before a reset
1066 * optimization settings */ 1074 */
1067 if (change_channel && ah->ah_rf_banks != NULL) 1075 if (ah->ah_version != AR5K_AR5210) {
1068 ath5k_hw_gainf_calibrate(ah); 1076 /*
1077 * Save frame sequence count
1078 * For revs. after Oahu, only save
1079 * seq num for DCU 0 (Global seq num)
1080 */
1081 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
1082
1083 for (i = 0; i < 10; i++)
1084 s_seq[i] = ath5k_hw_reg_read(ah,
1085 AR5K_QUEUE_DCU_SEQNUM(i));
1086
1087 } else {
1088 s_seq[0] = ath5k_hw_reg_read(ah,
1089 AR5K_QUEUE_DCU_SEQNUM(0));
1090 }
1091
1092 /* TSF accelerates on AR5211 during reset
1093 * As a workaround save it here and restore
1094 * it later so that it's back in time after
1095 * reset. This way it'll get re-synced on the
1096 * next beacon without breaking ad-hoc.
1097 *
1098 * On AR5212 TSF is almost preserved across a
1099 * reset so it stays back in time anyway and
1100 * we don't have to save/restore it.
1101 *
1102 * XXX: Since this breaks power saving we have
1103 * to disable power saving until we receive the
1104 * next beacon, so we can resync beacon timers */
1105 if (ah->ah_version == AR5K_AR5211) {
1106 tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
1107 tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
1069 } 1108 }
1070 } 1109 }
1071 1110
1111
1072 /*GPIOs*/ 1112 /*GPIOs*/
1073 s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & 1113 s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
1074 AR5K_PCICFG_LEDSTATE; 1114 AR5K_PCICFG_LEDSTATE;
@@ -1085,6 +1125,17 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1085 AR5K_STA_ID1_BASE_RATE_11B | 1125 AR5K_STA_ID1_BASE_RATE_11B |
1086 AR5K_STA_ID1_SELFGEN_DEF_ANT); 1126 AR5K_STA_ID1_SELFGEN_DEF_ANT);
1087 1127
1128 /*
1129 * Since we are going to write rf buffer
1130 * check if we have any pending gain_F
1131 * optimization settings
1132 */
1133 if (ah->ah_version == AR5K_AR5212 &&
1134 (ah->ah_radio <= AR5K_RF5112)) {
1135 if (!fast && ah->ah_rf_banks != NULL)
1136 ath5k_hw_gainf_calibrate(ah);
1137 }
1138
1088 /* Wakeup the device */ 1139 /* Wakeup the device */
1089 ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); 1140 ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
1090 if (ret) 1141 if (ret)
@@ -1098,7 +1149,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1098 AR5K_PHY(0)); 1149 AR5K_PHY(0));
1099 1150
1100 /* Write initial settings */ 1151 /* Write initial settings */
1101 ret = ath5k_hw_write_initvals(ah, mode, change_channel); 1152 ret = ath5k_hw_write_initvals(ah, mode, skip_pcu);
1102 if (ret) 1153 if (ret)
1103 return ret; 1154 return ret;
1104 1155
@@ -1120,24 +1171,20 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1120 * Restore saved values 1171 * Restore saved values
1121 */ 1172 */
1122 1173
1123 /*DCU/Antenna selection not available on 5210*/ 1174 /* Seqnum, TSF */
1124 if (ah->ah_version != AR5K_AR5210) { 1175 if (ah->ah_version != AR5K_AR5210) {
1176 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
1177 for (i = 0; i < 10; i++)
1178 ath5k_hw_reg_write(ah, s_seq[i],
1179 AR5K_QUEUE_DCU_SEQNUM(i));
1180 } else {
1181 ath5k_hw_reg_write(ah, s_seq[0],
1182 AR5K_QUEUE_DCU_SEQNUM(0));
1183 }
1125 1184
1126 if (change_channel) { 1185 if (ah->ah_version == AR5K_AR5211) {
1127 if (ah->ah_mac_srev < AR5K_SREV_AR5211) { 1186 ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
1128 for (i = 0; i < 10; i++) 1187 ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
1129 ath5k_hw_reg_write(ah, s_seq[i],
1130 AR5K_QUEUE_DCU_SEQNUM(i));
1131 } else {
1132 ath5k_hw_reg_write(ah, s_seq[0],
1133 AR5K_QUEUE_DCU_SEQNUM(0));
1134 }
1135
1136
1137 if (ah->ah_version == AR5K_AR5211) {
1138 ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
1139 ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
1140 }
1141 } 1188 }
1142 } 1189 }
1143 1190
@@ -1165,7 +1212,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1165 /* 1212 /*
1166 * Initialize PHY 1213 * Initialize PHY
1167 */ 1214 */
1168 ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq); 1215 ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq, false);
1169 if (ret) { 1216 if (ret) {
1170 ATH5K_ERR(ah->ah_sc, 1217 ATH5K_ERR(ah->ah_sc,
1171 "failed to initialize PHY (%i) !\n", ret); 1218 "failed to initialize PHY (%i) !\n", ret);