diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-07-31 02:12:01 +0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-04 23:27:37 +0400 |
commit | 4254bc1c4d7b53ac10e558dfe015725fdd693da4 (patch) | |
tree | 51c95b3f0f24ff8e1fabf698524c9ddd9f069879 /drivers/net/wireless/ath/ath9k/ar9002_calib.c | |
parent | 20bd2a0952d01ba82a99b3f22d46e3832c255529 (diff) | |
download | linux-4254bc1c4d7b53ac10e558dfe015725fdd693da4.tar.xz |
ath9k_hw: fix a noise floor calibration related race condition
On AR5008-AR9002, other forms of calibration must not be started while
the noise floor calibration is running, as this can create invalid
readings which were sometimes not even recoverable by any further
calibration attempts.
This patch also ensures that the result of noise floor measurements
are processed faster and also allows the result of the initial
calibration on reset to make it into the NF history buffer
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9002_calib.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9002_calib.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index d28a8d37f01f..fe7418aefc4a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -687,8 +687,13 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, { bool iscaldone = true; struct ath9k_cal_list *currCal = ah->cal_list_curr; + bool nfcal, nfcal_pending = false; - if (currCal && + nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); + if (ah->caldata) + nfcal_pending = ah->caldata->nfcal_pending; + + if (currCal && !nfcal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { iscaldone = ar9002_hw_per_calibration(ah, chan, @@ -704,7 +709,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, } /* Do NF cal only at longer intervals */ - if (longcal) { + if (longcal || nfcal_pending) { /* Do periodic PAOffset Cal */ ar9002_hw_pa_cal(ah, false); ar9002_hw_olc_temp_compensation(ah); @@ -713,16 +718,18 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, * Get the value from the previous NF cal and update * history buffer. */ - ath9k_hw_getnf(ah, chan); - - /* - * Load the NF from history buffer of the current channel. - * NF is slow time-variant, so it is OK to use a historical - * value. - */ - ath9k_hw_loadnf(ah, ah->curchan); + if (ath9k_hw_getnf(ah, chan)) { + /* + * Load the NF from history buffer of the current + * channel. + * NF is slow time-variant, so it is OK to use a + * historical value. + */ + ath9k_hw_loadnf(ah, ah->curchan); + } - ath9k_hw_start_nfcal(ah, false); + if (longcal) + ath9k_hw_start_nfcal(ah, false); } return iscaldone; @@ -872,6 +879,9 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) /* Do NF Calibration after DC offset and other calibrations */ ath9k_hw_start_nfcal(ah, true); + if (ah->caldata) + ah->caldata->nfcal_pending = true; + ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; /* Enable IQ, ADC Gain and ADC DC offset CALs */ |