From: Felix Fietkau <nbd@openwrt.org>
To: linux-wireless@vger.kernel.org
Cc: linville@tuxdriver.com, lrodriguez@atheros.com
Subject: [PATCH 3/3] ath9k_hw: fix a noise floor calibration related race condition
Date: Wed, 28 Jul 2010 19:45:51 +0200 [thread overview]
Message-ID: <1280339151-37084-3-git-send-email-nbd@openwrt.org> (raw)
In-Reply-To: <1280339151-37084-2-git-send-email-nbd@openwrt.org>
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>
---
drivers/net/wireless/ath/ath9k/ar9002_calib.c | 32 ++++++++++++++++--------
drivers/net/wireless/ath/ath9k/calib.c | 15 ++++++-----
drivers/net/wireless/ath/ath9k/calib.h | 3 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
4 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 4a7bcfa..916cde7 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);
+ if (longcal)
+ ath9k_hw_start_nfcal(ah);
}
return iscaldone;
@@ -873,6 +880,9 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
+ 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 */
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 52460bc..787657b 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -156,6 +156,9 @@ EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
void ath9k_hw_start_nfcal(struct ath_hw *ah)
{
+ if (ah->caldata)
+ ah->caldata->nfcal_pending = true;
+
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_ENABLE_NF);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
@@ -282,8 +285,7 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
}
}
-int16_t ath9k_hw_getnf(struct ath_hw *ah,
- struct ath9k_channel *chan)
+bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
int16_t nf, nfThresh;
@@ -293,7 +295,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
struct ath9k_hw_cal_data *caldata = ah->caldata;
if (!caldata)
- return ath9k_hw_get_default_nf(ah, chan);
+ return false;
chan->channelFlags &= (~CHANNEL_CW_INT);
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
@@ -301,7 +303,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
"NF did not complete in calibration window\n");
nf = 0;
caldata->rawNoiseFloor = nf;
- return caldata->rawNoiseFloor;
+ return false;
} else {
ath9k_hw_do_getnf(ah, nfarray);
ath9k_hw_nf_sanitize(ah, nfarray);
@@ -317,11 +319,10 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
}
h = caldata->nfCalHist;
-
+ caldata->nfcal_pending = false;
ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
caldata->rawNoiseFloor = h[0].privNF;
-
- return ah->caldata->rawNoiseFloor;
+ return true;
}
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 09a0ed2..8381e81 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -110,8 +110,7 @@ struct ath9k_pacal_info{
bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
void ath9k_hw_start_nfcal(struct ath_hw *ah);
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
-int16_t ath9k_hw_getnf(struct ath_hw *ah,
- struct ath9k_channel *chan);
+bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_channel *chan);
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index c1b7011..399f7c1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -354,6 +354,7 @@ struct ath9k_hw_cal_data {
int8_t qCoff;
int16_t rawNoiseFloor;
bool paprd_done;
+ bool nfcal_pending;
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
--
1.6.4.2
next prev parent reply other threads:[~2010-07-28 17:45 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-28 17:45 [PATCH 1/3] ath9k: prevent calibration during off-channel activity Felix Fietkau
2010-07-28 17:45 ` [PATCH 2/3] ath9k_hw: clean up per-channel calibration data Felix Fietkau
2010-07-28 17:45 ` Felix Fietkau [this message]
2010-07-28 20:52 ` Luis R. Rodriguez
2010-07-28 21:10 ` Felix Fietkau
2010-07-28 21:21 ` Luis R. Rodriguez
2010-07-28 21:30 ` Felix Fietkau
2010-07-28 21:40 ` Luis R. Rodriguez
2010-07-28 22:03 ` Felix Fietkau
2010-07-28 20:43 ` [PATCH 1/3] ath9k: prevent calibration during off-channel activity Luis R. Rodriguez
2010-07-28 21:08 ` Felix Fietkau
2010-07-28 22:12 ` Luis R. Rodriguez
2010-07-28 22:28 ` Felix Fietkau
2010-07-28 22:47 ` Luis R. Rodriguez
2010-07-28 22:48 ` Luis R. Rodriguez
2010-07-29 16:58 ` wireless-next-2.6 rebase -- " John W. Linville
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1280339151-37084-3-git-send-email-nbd@openwrt.org \
--to=nbd@openwrt.org \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
--cc=lrodriguez@atheros.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).