2013-12-14 14:16:28

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH] ath9k: Fix interrupt handling for the AR9002 family

From: Sujith Manoharan <[email protected]>

This patch adds a driver workaround for a HW issue.

A race condition in the HW results in missing interrupts,
which can be avoided by a read/write with the ISR register.
All chips in the AR9002 series are affected by this bug - AR9003
and above do not have this problem.

Cc: [email protected]
Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9002_mac.c | 44 +++++++++++++++++++++++++----
1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 8d78253..0337de7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
mask2 |= ATH9K_INT_CST;
if (isr2 & AR_ISR_S2_TSFOOR)
mask2 |= ATH9K_INT_TSFOOR;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR_S2, isr2);
+ isr &= ~AR_ISR_BCNMISC;
+ }
}

- isr = REG_READ(ah, AR_ISR_RAC);
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+ isr = REG_READ(ah, AR_ISR_RAC);
+
if (isr == 0xffffffff) {
*masked = 0;
return false;
@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)

*masked |= ATH9K_INT_TX;

- s0_s = REG_READ(ah, AR_ISR_S0_S);
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+ s0_s = REG_READ(ah, AR_ISR_S0_S);
+ s1_s = REG_READ(ah, AR_ISR_S1_S);
+ } else {
+ s0_s = REG_READ(ah, AR_ISR_S0);
+ REG_WRITE(ah, AR_ISR_S0, s0_s);
+ s1_s = REG_READ(ah, AR_ISR_S1);
+ REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+ isr &= ~(AR_ISR_TXOK |
+ AR_ISR_TXDESC |
+ AR_ISR_TXERR |
+ AR_ISR_TXEOL);
+ }
+
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
- s1_s = REG_READ(ah, AR_ISR_S1_S);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
}
@@ -120,7 +139,12 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
if (isr & AR_ISR_GENTMR) {
u32 s5_s;

- s5_s = REG_READ(ah, AR_ISR_S5_S);
+ if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+ s5_s = REG_READ(ah, AR_ISR_S5_S);
+ } else {
+ s5_s = REG_READ(ah, AR_ISR_S5);
+ }
+
ah->intr_gen_timer_trigger =
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);

@@ -133,6 +157,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
*masked |= ATH9K_INT_TIM_TIMER;
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR_S5, s5_s);
+ isr &= ~AR_ISR_GENTMR;
+ }
+ }
+
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR, isr);
+ REG_READ(ah, AR_ISR);
}

if (sync_cause) {
--
1.8.5.1



2013-12-15 20:19:28

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH] ath9k: Fix interrupt handling for the AR9002 family

On 2013-12-15 21:13, Felix Fietkau wrote:
> On 2013-12-14 15:11, Sujith Manoharan wrote:
>> From: Sujith Manoharan <[email protected]>
>>
>> This patch adds a driver workaround for a HW issue.
>>
>> A race condition in the HW results in missing interrupts,
>> which can be avoided by a read/write with the ISR register.
>> All chips in the AR9002 series are affected by this bug - AR9003
>> and above do not have this problem.
>>
>> Cc: [email protected]
>> Signed-off-by: Sujith Manoharan <[email protected]>
> Please don't apply this patch just yet, it seems to be causing interrupt
> storms. I'm currently looking into it.
This change on top of it should fix the interrupt storms (which were
observed on AR913x):
---
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -133,6 +133,11 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
*masked |= mask2;
}

+ if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+ REG_WRITE(ah, AR_ISR, isr);
+ REG_READ(ah, AR_ISR);
+ }
+
if (AR_SREV_9100(ah))
return true;

@@ -164,11 +169,6 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
}
}

- if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
- REG_WRITE(ah, AR_ISR, isr);
- REG_READ(ah, AR_ISR);
- }
-
if (sync_cause) {
ath9k_debug_sync_cause(common, sync_cause);
fatal_int =



2013-12-15 20:13:39

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH] ath9k: Fix interrupt handling for the AR9002 family

On 2013-12-14 15:11, Sujith Manoharan wrote:
> From: Sujith Manoharan <[email protected]>
>
> This patch adds a driver workaround for a HW issue.
>
> A race condition in the HW results in missing interrupts,
> which can be avoided by a read/write with the ISR register.
> All chips in the AR9002 series are affected by this bug - AR9003
> and above do not have this problem.
>
> Cc: [email protected]
> Signed-off-by: Sujith Manoharan <[email protected]>
Please don't apply this patch just yet, it seems to be causing interrupt
storms. I'm currently looking into it.

- Felix

2013-12-16 00:16:45

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [PATCH] ath9k: Fix interrupt handling for the AR9002 family

Felix Fietkau wrote:
> This change on top of it should fix the interrupt storms (which were
> observed on AR913x):
> ---
> --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
> +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
> @@ -133,6 +133,11 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
> *masked |= mask2;
> }
>
> + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
> + REG_WRITE(ah, AR_ISR, isr);
> + REG_READ(ah, AR_ISR);
> + }
> +
> if (AR_SREV_9100(ah))
> return true;

Thanks, I'll send a revised version.

Sujith