public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ath9k: Fix interrupt handling for the AR9002 family
@ 2013-12-14 14:11 Sujith Manoharan
  2013-12-15 20:13 ` Felix Fietkau
  0 siblings, 1 reply; 4+ messages in thread
From: Sujith Manoharan @ 2013-12-14 14:11 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, stable

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

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: stable@vger.kernel.org
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] ath9k: Fix interrupt handling for the AR9002 family
  2013-12-14 14:11 [PATCH] ath9k: Fix interrupt handling for the AR9002 family Sujith Manoharan
@ 2013-12-15 20:13 ` Felix Fietkau
  2013-12-15 20:19   ` Felix Fietkau
  0 siblings, 1 reply; 4+ messages in thread
From: Felix Fietkau @ 2013-12-15 20:13 UTC (permalink / raw)
  To: Sujith Manoharan, John Linville; +Cc: linux-wireless

On 2013-12-14 15:11, Sujith Manoharan wrote:
> From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
> 
> 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: stable@vger.kernel.org
> Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Please don't apply this patch just yet, it seems to be causing interrupt
storms. I'm currently looking into it.

- Felix

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ath9k: Fix interrupt handling for the AR9002 family
  2013-12-15 20:13 ` Felix Fietkau
@ 2013-12-15 20:19   ` Felix Fietkau
  2013-12-16  0:11     ` Sujith Manoharan
  0 siblings, 1 reply; 4+ messages in thread
From: Felix Fietkau @ 2013-12-15 20:19 UTC (permalink / raw)
  To: Sujith Manoharan, John Linville; +Cc: linux-wireless

On 2013-12-15 21:13, Felix Fietkau wrote:
> On 2013-12-14 15:11, Sujith Manoharan wrote:
>> From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
>> 
>> 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: stable@vger.kernel.org
>> Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
> 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 =



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ath9k: Fix interrupt handling for the AR9002 family
  2013-12-15 20:19   ` Felix Fietkau
@ 2013-12-16  0:11     ` Sujith Manoharan
  0 siblings, 0 replies; 4+ messages in thread
From: Sujith Manoharan @ 2013-12-16  0:11 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: John Linville, linux-wireless

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-12-16  0:16 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-14 14:11 [PATCH] ath9k: Fix interrupt handling for the AR9002 family Sujith Manoharan
2013-12-15 20:13 ` Felix Fietkau
2013-12-15 20:19   ` Felix Fietkau
2013-12-16  0:11     ` Sujith Manoharan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox