From 5f0c04ea1e7394c2b28fa247c1722487f9a77523 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 13 Oct 2011 11:00:35 +0530 Subject: ath9k_hw: Improve fast channel change for AR9003 chips In order to reduce the overall scan time, fast channel change should be implemented properly. This patch adds fast channel change support across band switch or channel mode switch instead of doing full chip reset. During the fastcc, tx iqcal measurements are preserved and will be reloaded after successful the channel change. This patch also addressed fast channel issue where the STA can not see APs in higher than operating channel on 5GHz band after the association. Cc: Paul Stewart Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 58794a4e40ad..e51d93d33d5f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1394,6 +1394,14 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, struct ath_common *common = ath9k_hw_common(ah); u32 qnum; int r; + bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); + bool band_switch, mode_diff; + u8 ini_reloaded; + + band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) != + (ah->curchan->channelFlags & (CHANNEL_2GHZ | + CHANNEL_5GHZ)); + mode_diff = (chan->chanmode != ah->curchan->chanmode); for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { if (ath9k_hw_numtxpending(ah, qnum)) { @@ -1408,6 +1416,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return false; } + if (edma && (band_switch || mode_diff)) { + ath9k_hw_mark_phy_inactive(ah); + udelay(5); + + ath9k_hw_init_pll(ah, NULL); + + if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) { + ath_err(common, "Failed to do fast channel change\n"); + return false; + } + } + ath9k_hw_set_channel_regs(ah, chan); r = ath9k_hw_rf_set_freq(ah, chan); @@ -1424,6 +1444,16 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, ath9k_hw_spur_mitigate_freq(ah, chan); + if (edma && (band_switch || mode_diff)) { + if (band_switch || ini_reloaded) + ah->eep_ops->set_board_values(ah, chan); + + ath9k_hw_init_bb(ah, chan); + + if (band_switch || ini_reloaded) + ath9k_hw_init_cal(ah, chan); + } + return true; } @@ -1677,6 +1707,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_bb(ah, chan); + if (caldata) + caldata->done_txiqcal_once = false; if (!ath9k_hw_init_cal(ah, chan)) return -EIO; -- cgit v1.2.2