diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 64 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 267 |
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); | |||
1183 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | 1183 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); |
1184 | int ath5k_hw_on_hold(struct ath5k_hw *ah); | 1184 | int ath5k_hw_on_hold(struct ath5k_hw *ah); |
1185 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1185 | int 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); |
1187 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | 1187 | int 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); | |||
1324 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | 1324 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); |
1325 | /* Init function */ | 1325 | /* Init function */ |
1326 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 1326 | int 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"); | |||
80 | MODULE_LICENSE("Dual BSD/GPL"); | 80 | MODULE_LICENSE("Dual BSD/GPL"); |
81 | MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); | 81 | MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); |
82 | 82 | ||
83 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); | 83 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, |
84 | bool skip_pcu); | ||
84 | static int ath5k_beacon_update(struct ieee80211_hw *hw, | 85 | static int ath5k_beacon_update(struct ieee80211_hw *hw, |
85 | struct ieee80211_vif *vif); | 86 | struct ieee80211_vif *vif); |
86 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | 87 | static 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 | ||
502 | static void | 503 | static 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 | */ |
2508 | static int | 2509 | static int |
2509 | ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | 2510 | ath5k_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 | ||
3225 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3225 | int 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 | ||
940 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 940 | int 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); |