From d0eded920c4a29fb032bcd90e1b7c2fe11387a21 Mon Sep 17 00:00:00 2001 From: John W. Linville Date: Mon, 21 Mar 2011 13:44:49 -0400 Subject: [PATCH] Revert "ath5k: Support synth-only channel change for AR2413/AR5413" This reverts commit 8aec7af99b1e4594c4bb9e1c48005e6111f97e8e. Conflicts: drivers/net/wireless/ath/ath5k/ath5k.h drivers/net/wireless/ath/ath5k/base.c drivers/net/wireless/ath/ath5k/phy.c drivers/net/wireless/ath/ath5k/reset.c --- drivers/net/wireless/ath/ath5k/ath5k.h | 4 +- drivers/net/wireless/ath/ath5k/base.c | 17 +-- drivers/net/wireless/ath/ath5k/phy.c | 76 ++--------- drivers/net/wireless/ath/ath5k/reset.c | 220 +++++++++++++------------------- 4 files changed, 111 insertions(+), 206 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 8a06dbd..b0a8f56 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1193,7 +1193,7 @@ void ath5k_unregister_leds(struct ath5k_softc *sc); int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); int ath5k_hw_on_hold(struct ath5k_hw *ah); int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool fast, bool skip_pcu); + struct ieee80211_channel *channel, bool change_channel); int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set); /* Power management functions */ @@ -1336,7 +1336,7 @@ void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); /* Init function */ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 mode, bool fast); + u8 mode); /* * Functions used internaly diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 4d7f21e..8868363 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -80,8 +80,7 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); static int ath5k_init(struct ieee80211_hw *hw); -static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, - bool skip_pcu); +static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); @@ -439,7 +438,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - return ath5k_reset(sc, chan, true); + return ath5k_reset(sc, chan); } void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) @@ -2300,7 +2299,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work) if (needreset) { ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "TX queues stuck, resetting\n"); - ath5k_reset(sc, NULL, true); + ath5k_reset(sc, sc->curchan); } mutex_unlock(&sc->lock); @@ -2539,7 +2538,7 @@ ath5k_init_hw(struct ath5k_softc *sc) AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; - ret = ath5k_reset(sc, NULL, false); + ret = ath5k_reset(sc, NULL); if (ret) goto done; @@ -2638,8 +2637,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) * This should be called with sc->lock. */ static int -ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, - bool skip_pcu) +ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@ -2663,8 +2661,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, ath5k_drain_tx_buffs(sc); if (chan) sc->curchan = chan; - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, - skip_pcu); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); goto err; @@ -2718,7 +2715,7 @@ static void ath5k_reset_work(struct work_struct *work) reset_work); mutex_lock(&sc->lock); - ath5k_reset(sc, NULL, true); + ath5k_reset(sc, sc->curchan); mutex_unlock(&sc->lock); } diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 62ce2f4..60b2b8d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -3234,7 +3234,7 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) \*************/ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 mode, bool fast) + u8 mode) { struct ieee80211_channel *curr_channel; int ret, i; @@ -3242,40 +3242,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ret = 0; /* - * Sanity check for fast flag - * Don't try fast channel change when changing modulation - * mode/band. We check for chip compatibility on - * ath5k_hw_reset. - */ - curr_channel = ah->ah_current_channel; - if (fast && (channel->hw_value != curr_channel->hw_value)) - return -EINVAL; - - /* - * On fast channel change we only set the synth parameters - * while PHY is running, enable calibration and skip the rest. - */ - if (fast) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, - AR5K_PHY_RFBUS_REQ_REQUEST); - for (i = 0; i < 100; i++) { - if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) - break; - udelay(5); - } - /* 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); - } - - /* * Set TX power * * Note: We need to do that before we set @@ -3303,30 +3269,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, 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 @@ -3363,7 +3305,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, AR5K_TXCFG_B_MODE); } - } else if (ah->ah_version == AR5K_AR5210) { + } else { mdelay(1); /* Disable phy and wait */ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); @@ -3384,9 +3326,21 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ath5k_hw_wait_for_synth(ah, channel); + 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); + + udelay(100 + (2 * delay)); + } else { + mdelay(1); + } + /* * Perform ADC test to see if baseband is ready - * Set tx hold and check adc test register + * 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); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 8420689..206b42d 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1020,7 +1020,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, \*********************/ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool fast, bool skip_pcu) + struct ieee80211_channel *channel, bool change_channel) { u32 s_seq[10], s_led[3], tsf_up, tsf_lo; u8 mode; @@ -1030,20 +1030,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, tsf_lo = 0; mode = 0; - /* - * Sanity check for fast flag - * Fast channel change only available - * on AR2413/AR5413. - */ - if (fast && (ah->ah_radio != AR5K_RF2413) && - (ah->ah_radio != AR5K_RF5413)) - fast = 0; - - /* Disable sleep clock operation - * to avoid register access delay on certain - * PHY registers */ - if (ah->ah_version == AR5K_AR5212) - ath5k_hw_set_sleep_clock(ah, false); /* * Stop PCU @@ -1056,113 +1042,88 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * Note: If DMA didn't stop continue * since only a reset will fix it. */ - ret = ath5k_hw_dma_stop(ah); - - /* RF Bus grant won't work if we have pending - * frames */ - if (ret && fast) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, - "DMA didn't stop, falling back to normal reset\n"); - fast = 0; - /* Non fatal, just continue with - * normal reset */ - ret = 0; - } + ath5k_hw_dma_stop(ah); - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - mode = AR5K_MODE_11A; - break; - case CHANNEL_G: - - if (ah->ah_version <= AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "G mode not available on 5210/5211"); - return -EINVAL; - } - - mode = AR5K_MODE_11G; - break; - case CHANNEL_B: - - if (ah->ah_version < AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "B mode not available on 5210"); - return -EINVAL; - } + /* + * Save some registers before a reset + */ + /*DCU/Antenna selection not available on 5210*/ + if (ah->ah_version != AR5K_AR5210) { - mode = AR5K_MODE_11B; - break; - case CHANNEL_XR: - if (ah->ah_version == AR5K_AR5211) { + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + mode = AR5K_MODE_11A; + break; + case CHANNEL_G: + mode = AR5K_MODE_11G; + break; + case CHANNEL_B: + mode = AR5K_MODE_11B; + break; + case CHANNEL_XR: + if (ah->ah_version == AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "XR mode not available on 5211"); + return -EINVAL; + } + mode = AR5K_MODE_XR; + break; + default: ATH5K_ERR(ah->ah_sc, - "XR mode not available on 5211"); + "invalid channel: %d\n", channel->center_freq); return -EINVAL; } - mode = AR5K_MODE_XR; - break; - default: - ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); - return -EINVAL; - } - /* - * If driver requested fast channel change and DMA has stopped - * go on. If it fails continue with a normal reset. - */ - if (fast) { - ret = ath5k_hw_phy_init(ah, channel, mode, true); - if (ret) { - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, - "fast chan change failed, falling back to normal reset\n"); - /* Non fatal, can happen eg. - * on mode change */ - ret = 0; - } else - return 0; - } + if (change_channel) { + /* + * Save frame sequence count + * For revs. after Oahu, only save + * seq num for DCU 0 (Global seq num) + */ + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - /* - * Save some registers before a reset - */ - if (ah->ah_version != AR5K_AR5210) { - /* - * Save frame sequence count - * For revs. after Oahu, only save - * seq num for DCU 0 (Global seq num) - */ - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + for (i = 0; i < 10; i++) + s_seq[i] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(i)); - for (i = 0; i < 10; i++) - s_seq[i] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(i)); + } else { + s_seq[0] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(0)); + } - } else { - s_seq[0] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(0)); + /* TSF accelerates on AR5211 during reset + * As a workaround save it here and restore + * it later so that it's back in time after + * reset. This way it'll get re-synced on the + * next beacon without breaking ad-hoc. + * + * On AR5212 TSF is almost preserved across a + * reset so it stays back in time anyway and + * we don't have to save/restore it. + * + * XXX: Since this breaks power saving we have + * to disable power saving until we receive the + * next beacon, so we can resync beacon timers */ + if (ah->ah_version == AR5K_AR5211) { + tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); + } } - /* TSF accelerates on AR5211 during reset - * As a workaround save it here and restore - * it later so that it's back in time after - * reset. This way it'll get re-synced on the - * next beacon without breaking ad-hoc. - * - * On AR5212 TSF is almost preserved across a - * reset so it stays back in time anyway and - * we don't have to save/restore it. - * - * XXX: Since this breaks power saving we have - * to disable power saving until we receive the - * next beacon, so we can resync beacon timers */ - if (ah->ah_version == AR5K_AR5211) { - tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); + if (ah->ah_version == AR5K_AR5212) { + /* Restore normal 32/40MHz clock operation + * to avoid register access delay on certain + * PHY registers */ + ath5k_hw_set_sleep_clock(ah, false); + + /* Since we are going to write rf buffer + * check if we have any pending gain_F + * optimization settings */ + if (change_channel && ah->ah_rf_banks != NULL) + ath5k_hw_gainf_calibrate(ah); } } - /*GPIOs*/ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE; @@ -1170,17 +1131,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - /* - * Since we are going to write rf buffer - * check if we have any pending gain_F - * optimization settings - */ - if (ah->ah_version == AR5K_AR5212 && - (ah->ah_radio <= AR5K_RF5112)) { - if (!fast && ah->ah_rf_banks != NULL) - ath5k_hw_gainf_calibrate(ah); - } - /* Wakeup the device */ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); if (ret) @@ -1194,7 +1144,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, AR5K_PHY(0)); /* Write initial settings */ - ret = ath5k_hw_write_initvals(ah, mode, skip_pcu); + ret = ath5k_hw_write_initvals(ah, mode, change_channel); if (ret) return ret; @@ -1216,20 +1166,24 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * Restore saved values */ - /* Seqnum, TSF */ + /*DCU/Antenna selection not available on 5210*/ if (ah->ah_version != AR5K_AR5210) { - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - for (i = 0; i < 10; i++) - ath5k_hw_reg_write(ah, s_seq[i], - AR5K_QUEUE_DCU_SEQNUM(i)); - } else { - ath5k_hw_reg_write(ah, s_seq[0], - AR5K_QUEUE_DCU_SEQNUM(0)); - } - if (ah->ah_version == AR5K_AR5211) { - ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); - ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); + if (change_channel) { + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + for (i = 0; i < 10; i++) + ath5k_hw_reg_write(ah, s_seq[i], + AR5K_QUEUE_DCU_SEQNUM(i)); + } else { + ath5k_hw_reg_write(ah, s_seq[0], + AR5K_QUEUE_DCU_SEQNUM(0)); + } + + + if (ah->ah_version == AR5K_AR5211) { + ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); + ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); + } } } @@ -1248,7 +1202,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* * Initialize PHY */ - ret = ath5k_hw_phy_init(ah, channel, mode, false); + ret = ath5k_hw_phy_init(ah, channel, mode); if (ret) { ATH5K_ERR(ah->ah_sc, "failed to initialize PHY (%i) !\n", ret); -- 1.7.4