2014-02-28 18:02:40

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 1/2] ath9k_hw: toggle weak signal detection in AP mode on older chipsets

The commit 80b4205b "ath9k: Fix OFDM weak signal detection for AP mode"
prevented weak signal detection changes from taking effect in AP mode on
all chipsets, claiming it is "not allowed".

The main reason for not disabling weak signal detection in AP mode is
that typically beacon RSSI is used to track whether it is needed to
boost range, and this is unavailable in AP mode for obvious reasons.

The problem with not disabling weak signal detection is that older
chipsets are very sensitive to high PHY error counts. When faced with
heavy noise, this can lead to an excessive amount of "Failed to stop
TX DMA" errors in the field.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/ani.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index d28923b..3227ee0 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -176,16 +176,18 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
if (ah->opmode == NL80211_IFTYPE_STATION &&
BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
weak_sig = true;
-
/*
- * OFDM Weak signal detection is always enabled for AP mode.
+ * Newer chipsets are better at dealing with high PHY error counts -
+ * keep weak signal detection enabled when no RSSI threshold is
+ * available to determine if it is needed (mode != STA)
*/
- if (ah->opmode != NL80211_IFTYPE_AP &&
- aniState->ofdmWeakSigDetect != weak_sig) {
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- entry_ofdm->ofdm_weak_signal_on);
- }
+ else if (AR_SREV_9300_20_OR_LATER(ah) &&
+ ah->opmode != NL80211_IFTYPE_STATION)
+ weak_sig = true;
+
+ if (aniState->ofdmWeakSigDetect != weak_sig)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ weak_sig);

if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
--
1.8.3.4 (Apple Git-47)



2014-02-28 20:54:13

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 2/2] ath9k_hw: tweak noise immunity thresholds for older chipsets

On 2014-02-28 19:52, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> Older chipsets are more sensitive to high PHY error counts, and the
>> current noise immunity thresholds were based on tests run at QCA with
>> newer chipsets.
>>
>> This patch brings back the values from the old ANI implementation for
>> old chipsets, and it also disables weak signal detection on an earlier
>> noise immunity level, to improve overall radio stability on affected
>> devices.
>
> Which devices ?
Reproduced on AR913x, suspected on AR928x, probably other affected
devices as well.

> Since the old values were used in the old ANI implementation, I am not sure
> how just retrofitting them into the new ANI algorithm can improve things...
Semantically, the values are compatible. The algorithm is similar enough
that this works just fine. The patch has gone through some testing that
showed a visible stability improvement.

- Felix

2014-02-28 20:52:37

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath9k_hw: toggle weak signal detection in AP mode on older chipsets

On 2014-02-28 19:43, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> - if (ah->opmode != NL80211_IFTYPE_AP &&
>> - aniState->ofdmWeakSigDetect != weak_sig) {
>> - ath9k_hw_ani_control(ah,
>> - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
>> - entry_ofdm->ofdm_weak_signal_on);
>> - }
>> + else if (AR_SREV_9300_20_OR_LATER(ah) &&
>> + ah->opmode != NL80211_IFTYPE_STATION)
>> + weak_sig = true;
>> +
>> + if (aniState->ofdmWeakSigDetect != weak_sig)
>> + ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
>> + weak_sig);
>
> Any reason why this has been changed to disregard the WS-DET parameter from
> ofdm_level_table[] ?
It doesn't disregard it - weak_sig is initialized to the value of that
parameter. Comparing aniState->ofdmWeakSigDetect against weak_sig, but
then passing entry_ofdm->ofdm_weak_signal_on is buggy.

- Felix

2014-02-28 18:52:37

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [PATCH 2/2] ath9k_hw: tweak noise immunity thresholds for older chipsets

Felix Fietkau wrote:
> Older chipsets are more sensitive to high PHY error counts, and the
> current noise immunity thresholds were based on tests run at QCA with
> newer chipsets.
>
> This patch brings back the values from the old ANI implementation for
> old chipsets, and it also disables weak signal detection on an earlier
> noise immunity level, to improve overall radio stability on affected
> devices.

Which devices ?

Since the old values were used in the old ANI implementation, I am not sure
how just retrofitting them into the new ANI algorithm can improve things...

Sujith

2014-02-28 18:44:30

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [PATCH 1/2] ath9k_hw: toggle weak signal detection in AP mode on older chipsets

Felix Fietkau wrote:
> - if (ah->opmode != NL80211_IFTYPE_AP &&
> - aniState->ofdmWeakSigDetect != weak_sig) {
> - ath9k_hw_ani_control(ah,
> - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
> - entry_ofdm->ofdm_weak_signal_on);
> - }
> + else if (AR_SREV_9300_20_OR_LATER(ah) &&
> + ah->opmode != NL80211_IFTYPE_STATION)
> + weak_sig = true;
> +
> + if (aniState->ofdmWeakSigDetect != weak_sig)
> + ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
> + weak_sig);

Any reason why this has been changed to disregard the WS-DET parameter from
ofdm_level_table[] ?

Sujith

2014-02-28 18:02:38

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 2/2] ath9k_hw: tweak noise immunity thresholds for older chipsets

Older chipsets are more sensitive to high PHY error counts, and the
current noise immunity thresholds were based on tests run at QCA with
newer chipsets.

This patch brings back the values from the old ANI implementation for
old chipsets, and it also disables weak signal detection on an earlier
noise immunity level, to improve overall radio stability on affected
devices.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath9k/ani.c | 23 +++++++++++++++++++----
drivers/net/wireless/ath/ath9k/ani.h | 4 ++++
2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 3227ee0..2ce5079 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -185,10 +185,18 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
ah->opmode != NL80211_IFTYPE_STATION)
weak_sig = true;

+ /* Older chipsets are more sensitive to high PHY error counts */
+ else if (!AR_SREV_9300_20_OR_LATER(ah) &&
+ aniState->ofdmNoiseImmunityLevel >= 8)
+ weak_sig = false;
+
if (aniState->ofdmWeakSigDetect != weak_sig)
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
weak_sig);

+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ return;
+
if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
@@ -485,10 +493,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah)

ath_dbg(common, ANI, "Initialize ANI\n");

- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
- ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
- ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
- ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
+ } else {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
+ }

ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index 21e7b83..c40965b 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -22,12 +22,16 @@
/* units are errors per second */
#define ATH9K_ANI_OFDM_TRIG_HIGH 3500
#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
+#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500

#define ATH9K_ANI_OFDM_TRIG_LOW 400
#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
+#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200

#define ATH9K_ANI_CCK_TRIG_HIGH 600
+#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
#define ATH9K_ANI_CCK_TRIG_LOW 300
+#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100

#define ATH9K_ANI_SPUR_IMMUNE_LVL 3
#define ATH9K_ANI_FIRSTEP_LVL 2
--
1.8.3.4 (Apple Git-47)