123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- From: Miaoqing Pan <miaoqing@codeaurora.org>
- Date: Fri, 5 Feb 2016 09:45:50 +0800
- Subject: [PATCH] ath9k: make NF load complete quickly and reliably
- Make NF load complete quickly and reliably. NF load execution
- is delayed by HW to end of frame if frame Rx or Tx is ongoing.
- Increasing timeout to max frame duration. If NF cal is ongoing
- before NF load, stop it before load, and restart it afterwards.
- Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
- ---
- --- a/drivers/net/wireless/ath/ath9k/calib.c
- +++ b/drivers/net/wireless/ath/ath9k/calib.c
- @@ -241,6 +241,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
- u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
- struct ath_common *common = ath9k_hw_common(ah);
- s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
- + u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL);
-
- if (ah->caldata)
- h = ah->caldata->nfCalHist;
- @@ -264,6 +265,16 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
- }
-
- /*
- + * stop NF cal if ongoing to ensure NF load completes immediately
- + * (or after end rx/tx frame if ongoing)
- + */
- + if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
- + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
- + REG_RMW_BUFFER_FLUSH(ah);
- + ENABLE_REG_RMW_BUFFER(ah);
- + }
- +
- + /*
- * Load software filtered NF value into baseband internal minCCApwr
- * variable.
- */
- @@ -276,18 +287,33 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
-
- /*
- * Wait for load to complete, should be fast, a few 10s of us.
- - * The max delay was changed from an original 250us to 10000us
- - * since 250us often results in NF load timeout and causes deaf
- - * condition during stress testing 12/12/2009
- + * The max delay was changed from an original 250us to 22.2 msec.
- + * This would increase timeout to the longest possible frame
- + * (11n max length 22.1 msec)
- */
- - for (j = 0; j < 10000; j++) {
- + for (j = 0; j < 22200; j++) {
- if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
- - AR_PHY_AGC_CONTROL_NF) == 0)
- + AR_PHY_AGC_CONTROL_NF) == 0)
- break;
- udelay(10);
- }
-
- /*
- + * Restart NF so it can continue.
- + */
- + if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
- + ENABLE_REG_RMW_BUFFER(ah);
- + if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF)
- + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
- + AR_PHY_AGC_CONTROL_ENABLE_NF);
- + if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF)
- + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
- + AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
- + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
- + REG_RMW_BUFFER_FLUSH(ah);
- + }
- +
- + /*
- * We timed out waiting for the noisefloor to load, probably due to an
- * in-progress rx. Simply return here and allow the load plenty of time
- * to complete before the next calibration interval. We need to avoid
- @@ -296,7 +322,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
- * here, the baseband nf cal will just be capped by our present
- * noisefloor until the next calibration timer.
- */
- - if (j == 10000) {
- + if (j == 22200) {
- ath_dbg(common, ANY,
- "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
- REG_READ(ah, AR_PHY_AGC_CONTROL));
|