diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-08-02 00:08:55 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2010-08-02 00:08:55 +0000 |
commit | 9d2aa5f66f037a462888027eec13855ddff61c60 (patch) | |
tree | ce1a1ca7204a571ca148a2cb5235236c1566c396 /package/mac80211/patches/542-ath9k_bstuck_nf_calibrate.patch | |
parent | 6978c1cb831490a58573294532c2f8b3e4d02886 (diff) | |
download | mtk-20170518-9d2aa5f66f037a462888027eec13855ddff61c60.zip mtk-20170518-9d2aa5f66f037a462888027eec13855ddff61c60.tar.gz mtk-20170518-9d2aa5f66f037a462888027eec13855ddff61c60.tar.bz2 |
ath9k: improve stuck beacon recovery and noise floor handling. significantly improves stability under strong interference in ap mode
SVN-Revision: 22460
Diffstat (limited to 'package/mac80211/patches/542-ath9k_bstuck_nf_calibrate.patch')
-rw-r--r-- | package/mac80211/patches/542-ath9k_bstuck_nf_calibrate.patch | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/package/mac80211/patches/542-ath9k_bstuck_nf_calibrate.patch b/package/mac80211/patches/542-ath9k_bstuck_nf_calibrate.patch new file mode 100644 index 0000000..35db2cb --- /dev/null +++ b/package/mac80211/patches/542-ath9k_bstuck_nf_calibrate.patch @@ -0,0 +1,127 @@ +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -362,6 +362,7 @@ void ath_beacon_tasklet(unsigned long da + ath_print(common, ATH_DBG_BSTUCK, + "missed %u consecutive beacons\n", + sc->beacon.bmisscnt); ++ ath9k_hw_bstuck_nfcal(ah); + } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { + ath_print(common, ATH_DBG_BSTUCK, + "beacon is officially stuck\n"); +--- a/drivers/net/wireless/ath/ath9k/calib.c ++++ b/drivers/net/wireless/ath/ath9k/calib.c +@@ -65,12 +65,16 @@ static s16 ath9k_hw_get_default_nf(struc + + + static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, +- struct ath9k_nfcal_hist *h, ++ struct ath9k_hw_cal_data *cal, + int16_t *nfarray) + { ++ struct ath_common *common = ath9k_hw_common(ah); + struct ath_nf_limits *limit; ++ struct ath9k_nfcal_hist *h; ++ bool high_nf_mid = false; + int i; + ++ h = cal->nfCalHist; + limit = ath9k_hw_get_nf_limits(ah, ah->curchan); + + for (i = 0; i < NUM_NF_READINGS; i++) { +@@ -87,9 +91,38 @@ static void ath9k_hw_update_nfcal_hist_b + ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); + } + +- if (h[i].privNF > limit->max) +- h[i].privNF = limit->max; ++ if (!h[i].privNF) ++ continue; ++ ++ if (h[i].privNF > limit->max) { ++ high_nf_mid = true; ++ ++ ath_print(common, ATH_DBG_CALIBRATE, ++ "NFmid[%d] (%d) > MAX (%d), %s\n", ++ i, h[i].privNF, limit->max, ++ (cal->nfcal_interference ? ++ "not corrected (due to interference)" : ++ "correcting to MAX")); ++ ++ /* ++ * Normally we limit the average noise floor by the ++ * hardware specific maximum here. However if we have ++ * encountered stuck beacons because of interference, ++ * we bypass this limit here in order to better deal ++ * with our environment. ++ */ ++ if (!cal->nfcal_interference) ++ h[i].privNF = limit->max; ++ } + } ++ ++ /* ++ * If the noise floor seems normal for all chains, assume that ++ * there is no significant interference in the environment anymore. ++ * Re-enable the enforcement of the NF maximum again. ++ */ ++ if (!high_nf_mid) ++ cal->nfcal_interference = false; + } + + static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, +@@ -339,7 +372,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s + + h = caldata->nfCalHist; + caldata->nfcal_pending = false; +- ath9k_hw_update_nfcal_hist_buffer(ah, h, nfarray); ++ ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); + caldata->rawNoiseFloor = h[0].privNF; + return true; + } +@@ -374,3 +407,26 @@ s16 ath9k_hw_getchan_noise(struct ath_hw + return ah->caldata->rawNoiseFloor; + } + EXPORT_SYMBOL(ath9k_hw_getchan_noise); ++ ++void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) ++{ ++ struct ath9k_hw_cal_data *caldata = ah->caldata; ++ ++ if (unlikely(!caldata)) ++ return; ++ ++ /* ++ * If beacons are stuck, the most likely cause is interference. ++ * Triggering a noise floor calibration at this point helps the ++ * hardware adapt to a noisy environment much faster. ++ * To ensure that we recover from stuck beacons quickly, let ++ * the baseband update the internal NF value itself, similar to ++ * what is being done after a full reset. ++ */ ++ if (!caldata->nfcal_pending) ++ ath9k_hw_start_nfcal(ah, true); ++ ++ caldata->nfcal_interference = true; ++} ++EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); ++ +--- a/drivers/net/wireless/ath/ath9k/calib.h ++++ b/drivers/net/wireless/ath/ath9k/calib.h +@@ -113,6 +113,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, + bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); + void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, + struct ath9k_channel *chan); ++void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); + s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); + void ath9k_hw_reset_calibration(struct ath_hw *ah, + struct ath9k_cal_list *currCal); +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -355,6 +355,7 @@ struct ath9k_hw_cal_data { + int16_t rawNoiseFloor; + bool paprd_done; + bool nfcal_pending; ++ bool nfcal_interference; + u16 small_signal_gain[AR9300_MAX_CHAINS]; + u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; + struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |