From: Felix Fietkau Date: Thu, 1 Jul 2010 19:43:03 +0000 (+0000) Subject: ath9k: properly sanitize calibrated noise floor values on all hardware X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=1f278440b73633567ee4ef7be33d61d42ddb52d8;p=openwrt%2Fstaging%2Frobimarko.git ath9k: properly sanitize calibrated noise floor values on all hardware SVN-Revision: 22035 --- diff --git a/package/mac80211/patches/530-ath9k_nf_sanitize.patch b/package/mac80211/patches/530-ath9k_nf_sanitize.patch new file mode 100644 index 0000000000..db873921cb --- /dev/null +++ b/package/mac80211/patches/530-ath9k_nf_sanitize.patch @@ -0,0 +1,386 @@ +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -1678,6 +1678,15 @@ static void ar5008_hw_ani_cache_ini_regs + aniState->cycleCount = 0; + } + ++static void ar5008_hw_set_nf_limits(struct ath_hw *ah) ++{ ++ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; ++ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; ++ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; ++ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; ++ ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; ++ ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; ++} + + void ar5008_hw_attach_phy_ops(struct ath_hw *ah) + { +@@ -1715,4 +1724,6 @@ void ar5008_hw_attach_phy_ops(struct ath + priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; + else + priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; ++ ++ ar5008_hw_set_nf_limits(ah); + } +--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c +@@ -520,6 +520,30 @@ static void ar9002_hw_do_getnf(struct at + } + } + ++static void ar9002_hw_set_nf_limits(struct ath_hw *ah) ++{ ++ if (AR_SREV_9285(ah)) { ++ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ; ++ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ; ++ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ; ++ } else if (AR_SREV_9287(ah)) { ++ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ; ++ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ; ++ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ; ++ } else if (AR_SREV_9271(ah)) { ++ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ; ++ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ; ++ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ; ++ } else { ++ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ; ++ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ; ++ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ; ++ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ; ++ ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ; ++ ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ; ++ } ++} ++ + void ar9002_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +@@ -532,4 +556,6 @@ void ar9002_hw_attach_phy_ops(struct ath + priv_ops->olc_init = ar9002_olc_init; + priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; + priv_ops->do_getnf = ar9002_hw_do_getnf; ++ ++ ar9002_hw_set_nf_limits(ah); + } +--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h +@@ -576,4 +576,30 @@ + #define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 + #define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 + ++#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 ++ ++#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 ++ ++#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 ++ ++#define AR_PHY_CCA_NOM_VAL_9271_2GHZ -118 ++#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127 ++#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116 ++ ++#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120 ++#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127 ++#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110 ++ + #endif +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1015,52 +1015,6 @@ static bool ar9003_hw_ani_control(struct + return true; + } + +-static void ar9003_hw_nf_sanitize_2g(struct ath_hw *ah, s16 *nf) +-{ +- struct ath_common *common = ath9k_hw_common(ah); +- +- if (*nf > ah->nf_2g_max) { +- ath_print(common, ATH_DBG_CALIBRATE, +- "2 GHz NF (%d) > MAX (%d), " +- "correcting to MAX", +- *nf, ah->nf_2g_max); +- *nf = ah->nf_2g_max; +- } else if (*nf < ah->nf_2g_min) { +- ath_print(common, ATH_DBG_CALIBRATE, +- "2 GHz NF (%d) < MIN (%d), " +- "correcting to MIN", +- *nf, ah->nf_2g_min); +- *nf = ah->nf_2g_min; +- } +-} +- +-static void ar9003_hw_nf_sanitize_5g(struct ath_hw *ah, s16 *nf) +-{ +- struct ath_common *common = ath9k_hw_common(ah); +- +- if (*nf > ah->nf_5g_max) { +- ath_print(common, ATH_DBG_CALIBRATE, +- "5 GHz NF (%d) > MAX (%d), " +- "correcting to MAX", +- *nf, ah->nf_5g_max); +- *nf = ah->nf_5g_max; +- } else if (*nf < ah->nf_5g_min) { +- ath_print(common, ATH_DBG_CALIBRATE, +- "5 GHz NF (%d) < MIN (%d), " +- "correcting to MIN", +- *nf, ah->nf_5g_min); +- *nf = ah->nf_5g_min; +- } +-} +- +-static void ar9003_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) +-{ +- if (IS_CHAN_2GHZ(ah->curchan)) +- ar9003_hw_nf_sanitize_2g(ah, nf); +- else +- ar9003_hw_nf_sanitize_5g(ah, nf); +-} +- + static void ar9003_hw_do_getnf(struct ath_hw *ah, + int16_t nfarray[NUM_NF_READINGS]) + { +@@ -1070,7 +1024,6 @@ static void ar9003_hw_do_getnf(struct at + nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); +- ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; +@@ -1078,7 +1031,6 @@ static void ar9003_hw_do_getnf(struct at + nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); +- ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; +@@ -1086,7 +1038,6 @@ static void ar9003_hw_do_getnf(struct at + nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); +- ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; +@@ -1094,7 +1045,6 @@ static void ar9003_hw_do_getnf(struct at + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); +- ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; +@@ -1102,7 +1052,6 @@ static void ar9003_hw_do_getnf(struct at + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); +- ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; +@@ -1110,18 +1059,19 @@ static void ar9003_hw_do_getnf(struct at + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); +- ar9003_hw_nf_sanitize(ah, &nf); + ath_print(common, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + } + +-void ar9003_hw_set_nf_limits(struct ath_hw *ah) ++static void ar9003_hw_set_nf_limits(struct ath_hw *ah) + { +- ah->nf_2g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ; +- ah->nf_2g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ; +- ah->nf_5g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ; +- ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; ++ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ; ++ ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ; ++ ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ; ++ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ; ++ ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; ++ ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ; + } + + /* +@@ -1309,6 +1259,8 @@ void ar9003_hw_attach_phy_ops(struct ath + priv_ops->do_getnf = ar9003_hw_do_getnf; + priv_ops->loadnf = ar9003_hw_loadnf; + priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; ++ ++ ar9003_hw_set_nf_limits(ah); + } + + void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) +--- a/drivers/net/wireless/ath/ath9k/calib.c ++++ b/drivers/net/wireless/ath/ath9k/calib.c +@@ -74,13 +74,8 @@ static void ath9k_hw_update_nfcal_hist_b + h[i].currIndex = 0; + + if (h[i].invalidNFcount > 0) { +- if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || +- nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { +- h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; +- } else { +- h[i].invalidNFcount--; +- h[i].privNF = nfarray[i]; +- } ++ h[i].invalidNFcount--; ++ h[i].privNF = nfarray[i]; + } else { + h[i].privNF = + ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); +@@ -172,6 +167,35 @@ void ath9k_hw_start_nfcal(struct ath_hw + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + } + ++static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ struct ath_nf_limits *limit; ++ int i; ++ ++ if (IS_CHAN_2GHZ(ah->curchan)) ++ limit = &ah->nf_2g; ++ else ++ limit = &ah->nf_5g; ++ ++ for (i = 0; i < NUM_NF_READINGS; i++) { ++ if (!nf[i]) ++ continue; ++ ++ if (nf[i] > limit->max) { ++ ath_print(common, ATH_DBG_CALIBRATE, ++ "NF[%d] (%d) > MAX (%d), correcting to MAX", ++ i, nf[i], limit->max); ++ nf[i] = limit->max; ++ } else if (nf[i] < limit->min) { ++ ath_print(common, ATH_DBG_CALIBRATE, ++ "NF[%d] (%d) < MIN (%d), correcting to NOM", ++ i, nf[i], limit->min); ++ nf[i] = limit->nominal; ++ } ++ } ++} ++ + int16_t ath9k_hw_getnf(struct ath_hw *ah, + struct ath9k_channel *chan) + { +@@ -190,6 +214,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah + return chan->rawNoiseFloor; + } else { + ath9k_hw_do_getnf(ah, nfarray); ++ ath9k_hw_nf_sanitize(ah, nfarray); + nf = nfarray[0]; + if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) + && nf > nfThresh) { +@@ -211,25 +236,21 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah + + void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) + { ++ struct ath_nf_limits *limit; + int i, j; +- s16 noise_floor; + +- if (AR_SREV_9280(ah)) +- noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; +- else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) +- noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; +- else if (AR_SREV_9287(ah)) +- noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; ++ if (IS_CHAN_2GHZ(ah->curchan)) ++ limit = &ah->nf_2g; + else +- noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; ++ limit = &ah->nf_5g; + + for (i = 0; i < NUM_NF_READINGS; i++) { + ah->nfCalHist[i].currIndex = 0; +- ah->nfCalHist[i].privNF = noise_floor; ++ ah->nfCalHist[i].privNF = limit->nominal; + ah->nfCalHist[i].invalidNFcount = + AR_PHY_CCA_FILTERWINDOW_LENGTH; + for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { +- ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; ++ ah->nfCalHist[i].nfCalBuffer[j] = limit->nominal; + } + } + } +--- a/drivers/net/wireless/ath/ath9k/calib.h ++++ b/drivers/net/wireless/ath/ath9k/calib.h +@@ -19,12 +19,6 @@ + + #include "hw.h" + +-#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 +-#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 +-#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 +-#define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE -118 +-#define AR_PHY_CCA_MAX_HIGH_VALUE -62 +-#define AR_PHY_CCA_MIN_BAD_VALUE -140 + #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 + #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -621,9 +621,6 @@ static int __ath9k_hw_init(struct ath_hw + else + ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); + +- if (AR_SREV_9300_20_OR_LATER(ah)) +- ar9003_hw_set_nf_limits(ah); +- + ath9k_init_nfcal_hist_buffer(ah); + ah->bb_watchdog_timeout_ms = 25; + +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -630,6 +630,12 @@ struct ath_hw_ops { + void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan); + }; + ++struct ath_nf_limits { ++ s16 max; ++ s16 min; ++ s16 nominal; ++}; ++ + struct ath_hw { + struct ieee80211_hw *hw; + struct ath_common common; +@@ -651,10 +657,9 @@ struct ath_hw { + bool is_pciexpress; + bool need_an_top2_fixup; + u16 tx_trig_level; +- s16 nf_2g_max; +- s16 nf_2g_min; +- s16 nf_5g_max; +- s16 nf_5g_min; ++ ++ struct ath_nf_limits nf_2g; ++ struct ath_nf_limits nf_5g; + u16 rfsilent; + u32 rfkill_gpio; + u32 rfkill_polarity; +@@ -945,7 +950,6 @@ void ar9002_hw_enable_wep_aggregation(st + * Code specific to AR9003, we stuff these here to avoid callbacks + * for older families + */ +-void ar9003_hw_set_nf_limits(struct ath_hw *ah); + void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); + void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); + void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);