summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2011-01-29 14:27:20 +0000
committeradrian <adrian@FreeBSD.org>2011-01-29 14:27:20 +0000
commit16700c0fc292f9cfa422807008c4b8a259567dc3 (patch)
tree569e740c27fed5b8c69b2568c29a7a16cd2eee4f /sys/dev
parent19235437178eac3f2b55f1839b6de731b49b1a4a (diff)
downloadFreeBSD-src-16700c0fc292f9cfa422807008c4b8a259567dc3.zip
FreeBSD-src-16700c0fc292f9cfa422807008c4b8a259567dc3.tar.gz
Bring over some NF calibration changes from ath9k.
Each different radio chipset has a different "good" range of CCA (clear channel access) parameters where, if you write something out of range, it's possible the radio will go deaf. Also, since apparently occasionally reading the NF calibration returns "wrong" values, so enforce those limits on what is being written into the CCA register. Write a default value if there's no history available. This isn't the case right now but it may be later on when "off-channel" scanning occurs without init'ing or changing the NF history buffer. (As each channel may have a different noise floor; so scanning or other off-channel activity shouldn't affect the NF history of the current channel.)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.h9
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_attach.c8
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal.c69
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416phy.h9
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9160_attach.c9
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280.h7
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_attach.c9
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285.h3
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_attach.c7
9 files changed, 128 insertions, 2 deletions
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h
index 8a9946e..695ccb3 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h
@@ -49,6 +49,12 @@ typedef struct {
#define AR5416_SPUR_RSSI_THRESH 40
+struct ar5416NfLimits {
+ int16_t max;
+ int16_t min;
+ int16_t nominal;
+};
+
struct ath_hal_5416 {
struct ath_hal_5212 ah_5212;
@@ -82,6 +88,9 @@ struct ath_hal_5416 {
uint32_t ah_tx_chainmask;
struct ar5416PerCal ah_cal; /* periodic calibration state */
+
+ struct ar5416NfLimits nf_2g;
+ struct ar5416NfLimits nf_5g;
};
#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah))
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
index d3f92be..5307cd7 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
@@ -356,6 +356,14 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc,
}
ar5416AniSetup(ah); /* Anti Noise Immunity */
+
+ AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;
+ AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;
+ AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;
+ AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;
+ AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;
+ AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
+
ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
index 7fab84e..422fad8 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
@@ -37,6 +37,9 @@ static void ar5416StartNFCal(struct ath_hal *ah);
static void ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *);
static int16_t ar5416GetNf(struct ath_hal *, struct ieee80211_channel *);
+static uint16_t ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan);
+static void ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf);
+
/*
* Determine if calibration is supported by device and channel flags
*/
@@ -548,6 +551,7 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
int i;
int32_t val;
uint8_t chainmask;
+ int16_t default_nf = ar5416GetDefaultNF(ah, chan);
/*
* Force NF calibration for all chains.
@@ -567,13 +571,24 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
* so we can load below.
*/
h = AH5416(ah)->ah_cal.nfCalHist;
- for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
+ HALDEBUG(ah, HAL_DEBUG_NFCAL, "CCA: ");
+ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
if (chainmask & (1 << i)) {
+ int16_t nf_val;
+
+ if (h)
+ nf_val = h[i].privNF;
+ else
+ nf_val = default_nf;
+
val = OS_REG_READ(ah, ar5416_cca_regs[i]);
val &= 0xFFFFFE00;
- val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
+ val |= (((uint32_t) nf_val << 1) & 0x1ff);
+ HALDEBUG(ah, HAL_DEBUG_NFCAL, "[%d: %d]", i, nf_val);
OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
}
+ }
+ HALDEBUG(ah, HAL_DEBUG_NFCAL, "\n");
/* Load software filtered NF value into baseband internal minCCApwr variable. */
OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
@@ -611,6 +626,11 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
}
}
+/*
+ * This just initialises the "good" values for AR5416 which
+ * may not be right; it'lll be overridden by ar5416SanitizeNF()
+ * to nominal values.
+ */
void
ar5416InitNfHistBuff(struct ar5212NfCalHist *h)
{
@@ -652,6 +672,50 @@ ar5416UpdateNFHistBuff(struct ar5212NfCalHist *h, int16_t *nfarray)
}
}
+static uint16_t
+ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ struct ar5416NfLimits *limit;
+
+ if (!chan || IEEE80211_IS_CHAN_2GHZ(chan))
+ limit = &AH5416(ah)->nf_2g;
+ else
+ limit = &AH5416(ah)->nf_5g;
+
+ return limit->nominal;
+}
+
+static void
+ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf)
+{
+
+ struct ar5416NfLimits *limit;
+ int i;
+
+ if (IEEE80211_IS_CHAN_2GHZ(AH_PRIVATE(ah)->ah_curchan))
+ limit = &AH5416(ah)->nf_2g;
+ else
+ limit = &AH5416(ah)->nf_5g;
+
+ for (i = 0; i < AR5416_NUM_NF_READINGS; i++) {
+ if (!nf[i])
+ continue;
+
+ if (nf[i] > limit->max) {
+ HALDEBUG(ah, HAL_DEBUG_NFCAL,
+ "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
+ i, nf[i], limit->max);
+ nf[i] = limit->max;
+ } else if (nf[i] < limit->min) {
+ HALDEBUG(ah, HAL_DEBUG_NFCAL,
+ "NF[%d] (%d) < MIN (%d), correcting to NOM\n",
+ i, nf[i], limit->min);
+ nf[i] = limit->nominal;
+ }
+ }
+}
+
+
/*
* Read the NF and check it against the noise floor threshhold
*/
@@ -672,6 +736,7 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan)
/* TODO - enhance for multiple chains and ext ch */
ath_hal_getNoiseFloor(ah, nfarray);
nf = nfarray[0];
+ ar5416SanitizeNF(ah, nfarray);
if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) {
if (nf > nfThresh) {
HALDEBUG(ah, HAL_DEBUG_ANY,
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
index 3e16225..ee6c0af 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
@@ -269,4 +269,13 @@
#define AR_PHY_CL_CAL_CTL 0xA358 /* carrier leak cal control */
#define AR_PHY_CL_CAL_ENABLE 0x00000002
#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
+
+/* empirically determined "good" CCA value ranges from atheros */
+#define AR_PHY_CCA_NOM_VAL_5416_2GHZ -90
+#define AR_PHY_CCA_NOM_VAL_5416_5GHZ -100
+#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ -100
+#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ -110
+#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ -80
+#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ -90
+
#endif /* _DEV_ATH_AR5416PHY_H_ */
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
index bae956b..7ea4467 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
@@ -250,6 +250,15 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc,
OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
ar9160AniSetup(ah); /* Anti Noise Immunity */
+
+ /* This just uses the AR5416 NF values */
+ AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;
+ AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;
+ AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;
+ AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;
+ AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;
+ AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
+
ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280.h b/sys/dev/ath/ath_hal/ar9002/ar9280.h
index 59039f0..2028667 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280.h
@@ -34,6 +34,13 @@ struct ath_hal_9280 {
#define AR9280_DEFAULT_TXCHAINMASK 1
#define AR9285_DEFAULT_TXCHAINMASK 1
+#define AR_PHY_CCA_NOM_VAL_9280_2GHZ -112
+#define AR_PHY_CCA_NOM_VAL_9280_5GHZ -112
+#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ -127
+#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ -122
+#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ -97
+#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ -102
+
HAL_BOOL ar9280RfAttach(struct ath_hal *, HAL_STATUS *);
struct ath_hal;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
index 2ad3020..8302f3d 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
@@ -280,6 +280,15 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc,
OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
ar9280AniSetup(ah); /* Anti Noise Immunity */
+
+ /* Setup noise floor min/max/nominal values */
+ AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
+ AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
+ AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
+ AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
+ AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
+ AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
+
ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285.h b/sys/dev/ath/ath_hal/ar9002/ar9285.h
index 1ee058b..9c83c35 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285.h
@@ -31,6 +31,9 @@ struct ath_hal_9285 {
#define AR9285_DEFAULT_RXCHAINMASK 1
#define AR9285_DEFAULT_TXCHAINMASK 1
+#define AR_PHY_CCA_NOM_VAL_9285_2GHZ -118
+#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ -108
HAL_BOOL ar9285SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
HAL_BOOL ar9285RfAttach(struct ath_hal *, HAL_STATUS *);
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
index 39dd4cd..f8383b8 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
@@ -281,6 +281,13 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc,
OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
ar9285AniSetup(ah); /* Anti Noise Immunity */
+
+ /* Setup noise floor min/max/nominal values */
+ AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
+ AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
+ AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
+ /* XXX no 5ghz values? */
+
ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
OpenPOWER on IntegriCloud