+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
+
+ ath9k: fix ready time of the multicast buffer queue
+
+ qi->tqi_readyTime is written directly to registers that expect
+ microseconds as unit instead of TU.
+ When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so
+ convert it to microseconds before passing it to ath9k_hw.
+
+ This should hopefully fix some Tx DMA issues with buffered multicast
+ frames in AP mode.
+
+ Cc: stable@vger.kernel.org
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
commit fcb064fdd5a27bec8d24099bc0172468f34c97cb
Author: Felix Fietkau <nbd@openwrt.org>
Date: Sun Mar 9 09:43:09 2014 +0100
buffered = ath_tid_has_buffered(tid);
tid->sched = false;
+@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc
+
+ ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
+
+- qi.tqi_readyTime = (cur_conf->beacon_interval *
++ qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) *
+ ATH_CABQ_READY_TIME) / 100;
+ ath_txq_update(sc, qnum, &qi);
+
@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw
txq->stopped = true;
}
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");