+commit 3a0f984b1cdcd6a9f8c441635ef3b05d58547f4e
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Tue Mar 11 14:03:32 2014 +0100
+
+ ath9k_hw: set ANI firstep as absolute values instead of relative
+
+ On older chips, the INI value differ in similar ways as cycpwr_thr1, so
+ convert it to absolute values as well.
+
+ Since the ANI algorithm is different here compared to the old
+ implementation (fewer steps, controlled at a different point in time),
+ it makes sense to use values similar to what would be applied for newer
+ chips, just without relying on INI defaults.
+
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 91d70d40400c569b49605b78fd7c43e9405694f4
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Tue Mar 11 14:00:37 2014 +0100
+
+ ath9k_hw: set ANI cycpwr_thr1 as absolute values instead of relative
+
+ The table was copied from the ANI implementation of AR9300. It assumes
+ that the INI values contain a baseline value that is usable as reference
+ from which to increase/decrease based on the noise immunity value.
+
+ On older chips, the differences are bigger and especially AR5008/AR9001
+ are configured to much more sensitive values than what is useful.
+
+ Improve ANI behavior by reverting to the absolute values used in the
+ previous implementation (expressed as a simple formula instead of the
+ old table).
+
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit c977493766310a825f406836636ffd66e1447783
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Mon Mar 10 19:52:56 2014 +0100
+
+ ath9k_hw: remove ANI function restrictions for AP mode
+
+ The primary purpose of this piece of code was to selectively disable
+ OFDM weak signal detection. The checks for this are elsewhere, and an
+ earlier commit relaxed the restrictions for older chips, which are more
+ sensitive to interference.
+
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 8d804f1af11e4e058b1e8453327777d73a585cb8
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Sun Mar 9 11:25:43 2014 +0100
+
+ ath9k: clean up and enhance ANI debugfs file
+
+ Unify scnprintf calls and include the current OFDM/CCK immunity level.
+
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
commit 22e298b5a3a8a49e33805d4e351965123dede35b
Author: Felix Fietkau <nbd@openwrt.org>
Date: Sun Mar 9 10:58:47 2014 +0100
schedule_delayed_work(®_timeout, msecs_to_jiffies(3142));
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -866,6 +866,12 @@ static ssize_t read_file_reset(struct fi
+@@ -138,43 +138,41 @@ static ssize_t read_file_ani(struct file
+ unsigned int len = 0, size = 1024;
+ ssize_t retval = 0;
+ char *buf;
++ int i;
++ struct {
++ const char *name;
++ unsigned int val;
++ } ani_info[] = {
++ { "ANI RESET", ah->stats.ast_ani_reset },
++ { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel },
++ { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel },
++ { "SPUR UP", ah->stats.ast_ani_spurup },
++ { "SPUR DOWN", ah->stats.ast_ani_spurup },
++ { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon },
++ { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff },
++ { "MRC-CCK ON", ah->stats.ast_ani_ccklow },
++ { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh },
++ { "FIR-STEP UP", ah->stats.ast_ani_stepup },
++ { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown },
++ { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero },
++ { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs },
++ { "CCK ERRORS", ah->stats.ast_ani_cckerrs },
++ };
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+- if (common->disable_ani) {
+- len += scnprintf(buf + len, size - len, "%s: %s\n",
+- "ANI", "DISABLED");
++ len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI",
++ common->disable_ani ? "DISABLED" : "ENABLED");
++
++ if (common->disable_ani)
+ goto exit;
+- }
+
+- len += scnprintf(buf + len, size - len, "%15s: %s\n",
+- "ANI", "ENABLED");
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "ANI RESET", ah->stats.ast_ani_reset);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "SPUR UP", ah->stats.ast_ani_spurup);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "SPUR DOWN", ah->stats.ast_ani_spurup);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "MRC-CCK ON", ah->stats.ast_ani_ccklow);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "MRC-CCK OFF", ah->stats.ast_ani_cckhigh);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "FIR-STEP UP", ah->stats.ast_ani_stepup);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "FIR-STEP DOWN", ah->stats.ast_ani_stepdown);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs);
+- len += scnprintf(buf + len, size - len, "%15s: %u\n",
+- "CCK ERRORS", ah->stats.ast_ani_cckerrs);
++ for (i = 0; i < ARRAY_SIZE(ani_info); i++)
++ len += scnprintf(buf + len, size - len, "%15s: %u\n",
++ ani_info[i].name, ani_info[i].val);
++
+ exit:
+ if (len > size)
+ len = size;
+@@ -866,6 +864,12 @@ static ssize_t read_file_reset(struct fi
"%17s: %2d\n", "PLL RX Hang",
sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
len += scnprintf(buf + len, sizeof(buf) - len,
if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
-@@ -483,10 +493,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah
+@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah,
+ BUG_ON(aniState == NULL);
+ ah->stats.ast_ani_reset++;
+
+- /* only allow a subset of functions in AP mode */
+- if (ah->opmode == NL80211_IFTYPE_AP) {
+- if (IS_CHAN_2GHZ(chan)) {
+- ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
+- ATH9K_ANI_FIRSTEP_LEVEL);
+- if (AR_SREV_9300_20_OR_LATER(ah))
+- ah->ani_function |= ATH9K_ANI_MRC_CCK;
+- } else
+- ah->ani_function = 0;
+- }
+-
+ ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
+ aniState->ofdmNoiseImmunityLevel);
+ cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
+@@ -483,10 +482,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah
ath_dbg(common, ANI, "Initialize ANI\n");
#define ATH9K_ANI_SPUR_IMMUNE_LVL 3
#define ATH9K_ANI_FIRSTEP_LVL 2
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -26,10 +26,6 @@ static const int firstep_table[] =
+ /* level: 0 1 2 3 4 5 6 7 8 */
+ { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
+
+-static const int cycpwrThr1_table[] =
+-/* level: 0 1 2 3 4 5 6 7 8 */
+- { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
+-
+ /*
+ * register values to turn OFDM weak signal detection OFF
+ */
+@@ -921,7 +917,7 @@ static bool ar5008_hw_ani_control_new(st
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &ah->ani;
+- s32 value, value2;
++ s32 value;
+
+ switch (cmd & ah->ani_function) {
+ case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+@@ -1008,42 +1004,11 @@ static bool ar5008_hw_ani_control_new(st
+ case ATH9K_ANI_FIRSTEP_LEVEL:{
+ u32 level = param;
+
+- if (level >= ARRAY_SIZE(firstep_table)) {
+- ath_dbg(common, ANI,
+- "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
+- level, ARRAY_SIZE(firstep_table));
+- return false;
+- }
+-
+- /*
+- * make register setting relative to default
+- * from INI file & cap value
+- */
+- value = firstep_table[level] -
+- firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+- aniState->iniDef.firstep;
+- if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+- value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+- if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+- value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
++ value = level * 2;
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+- AR_PHY_FIND_SIG_FIRSTEP,
+- value);
+- /*
+- * we need to set first step low register too
+- * make register setting relative to default
+- * from INI file & cap value
+- */
+- value2 = firstep_table[level] -
+- firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+- aniState->iniDef.firstepLow;
+- if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+- value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+- if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+- value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+-
++ AR_PHY_FIND_SIG_FIRSTEP, value);
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+- AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
++ AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
+
+ if (level != aniState->firstepLevel) {
+ ath_dbg(common, ANI,
+@@ -1060,7 +1025,7 @@ static bool ar5008_hw_ani_control_new(st
+ aniState->firstepLevel,
+ level,
+ ATH9K_ANI_FIRSTEP_LVL,
+- value2,
++ value,
+ aniState->iniDef.firstepLow);
+ if (level > aniState->firstepLevel)
+ ah->stats.ast_ani_stepup++;
+@@ -1073,41 +1038,13 @@ static bool ar5008_hw_ani_control_new(st
+ case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+ u32 level = param;
+
+- if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
+- ath_dbg(common, ANI,
+- "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
+- level, ARRAY_SIZE(cycpwrThr1_table));
+- return false;
+- }
+- /*
+- * make register setting relative to default
+- * from INI file & cap value
+- */
+- value = cycpwrThr1_table[level] -
+- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+- aniState->iniDef.cycpwrThr1;
+- if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+- value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+- if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+- value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
++ value = (level + 1) * 2;
+ REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+- AR_PHY_TIMING5_CYCPWR_THR1,
+- value);
++ AR_PHY_TIMING5_CYCPWR_THR1, value);
+
+- /*
+- * set AR_PHY_EXT_CCA for extension channel
+- * make register setting relative to default
+- * from INI file & cap value
+- */
+- value2 = cycpwrThr1_table[level] -
+- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+- aniState->iniDef.cycpwrThr1Ext;
+- if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+- if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+- AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
++ if (IS_CHAN_HT40(ah->curchan))
++ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
++ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
+
+ if (level != aniState->spurImmunityLevel) {
+ ath_dbg(common, ANI,
+@@ -1124,7 +1061,7 @@ static bool ar5008_hw_ani_control_new(st
+ aniState->spurImmunityLevel,
+ level,
+ ATH9K_ANI_SPUR_IMMUNE_LVL,
+- value2,
++ value,
+ aniState->iniDef.cycpwrThr1Ext);
+ if (level > aniState->spurImmunityLevel)
+ ah->stats.ast_ani_spurup++;