From c6c9d8c8eddd19db0064ca9e1c6e49bfdf863f87 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sat, 29 Jan 2011 14:27:20 +0000 Subject: [PATCH] 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.) --- sys/dev/ath/ath_hal/ar5416/ar5416.h | 9 +++ sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 8 +++ sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 69 +++++++++++++++++++++- sys/dev/ath/ath_hal/ar5416/ar5416phy.h | 9 +++ sys/dev/ath/ath_hal/ar9001/ar9160_attach.c | 9 +++ sys/dev/ath/ath_hal/ar9002/ar9280.h | 7 +++ sys/dev/ath/ath_hal/ar9002/ar9280_attach.c | 9 +++ sys/dev/ath/ath_hal/ar9002/ar9285.h | 3 + sys/dev/ath/ath_hal/ar9002/ar9285_attach.c | 7 +++ 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 8a9946e2bc5d..695ccb35dab1 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 d3f92be0338e..5307cd746d33 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 7fab84eb4b13..422fad830265 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 3e1622599fe8..ee6c0af9c182 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 bae956b6e9f6..7ea446712f5e 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 59039f0157ee..20286671522d 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 2ad3020c8546..8302f3d6bbe8 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 1ee058bf3120..9c83c35833ee 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 39dd4cd8ebee..f8383b8f06a1 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__);