Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler
@ 2026-10-15  8:44 P Praneesh
  2026-10-21  5:07 ` Karthikeyan Periyasamy
  2026-10-27  8:43 ` Baochen Qiang
  0 siblings, 2 replies; 4+ messages in thread
From: P Praneesh @ 2026-10-15  8:44 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, praneesh.p

On AHB platforms such as IPQ5332, IRQ group 3 maps multiple hardware
rings to a single NAPI instance. Each ring is assigned its own IRQ
line, but all IRQs in the group share one napi struct and one poll
function.

When two IRQs from the same group fire simultaneously on different
CPUs, both handlers call ath12k_ahb_ext_grp_disable(), which invokes
disable_irq_nosync() for every IRQ in the group. This increments the
interrupt controller's disable reference count for each IRQ twice. The
single NAPI poll that runs calls ath12k_ahb_ext_grp_enable() once,
decrementing each count from 2 to 1. Because the count never reaches 0,
all IRQs in the group remain permanently masked by the interrupt
controller.

With no further interrupts, TX completions stop being reaped from the
WBM release ring. The pending TX descriptor count grows until the WBM
idle link descriptor pool is exhausted. Once full, TX ring allocation
fails and no new packets including management frames can be enqueued.
This causes stations to disassociate with reason 34 (DISASSOC_LOW_ACK)
and ath12k_mac_flush() to time out:
"failed to flush transmit queue, data pkts req N pending N"
where N equals ATH12K_NUM_POOL_TX_DESC(ab).

Fix this by using napi_schedule_prep() to atomically test-and-set
NAPI_STATE_SCHED before disabling IRQs. Only the first CPU to win the
atomic operation disables the group and calls __napi_schedule(). Any
concurrent handler that loses the race skips the disable entirely,
keeping the reference count balanced. Guard the enable_irq() call in
the poll routine with the return value of napi_complete_done() to
prevent an unbalanced enable if the NAPI instance was re-scheduled
before the poll completed.

Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.7-00587-QCAHKSWPL_SILICONZ-1

Fixes: 6cee30f0da75 ("wifi: ath12k: add AHB driver support for IPQ5332")
Signed-off-by: P Praneesh <praneesh.p@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/ahb.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
index 2c55aae06dd0..e5bbfca2b2ac 100644
--- a/drivers/net/wireless/ath/ath12k/ahb.c
+++ b/drivers/net/wireless/ath/ath12k/ahb.c
@@ -602,8 +602,8 @@ static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
 
 	work_done = ath12k_dp_service_srng(dp, irq_grp, budget);
 	if (work_done < budget) {
-		napi_complete_done(napi, work_done);
-		ath12k_ahb_ext_grp_enable(irq_grp);
+		if (likely(napi_complete_done(napi, work_done)))
+			ath12k_ahb_ext_grp_enable(irq_grp);
 	}
 
 	if (work_done > budget)
@@ -619,9 +619,10 @@ static irqreturn_t ath12k_ahb_ext_interrupt_handler(int irq, void *arg)
 	/* last interrupt received for this group */
 	irq_grp->timestamp = jiffies;
 
-	ath12k_ahb_ext_grp_disable(irq_grp);
-
-	napi_schedule(&irq_grp->napi);
+	if (napi_schedule_prep(&irq_grp->napi)) {
+		ath12k_ahb_ext_grp_disable(irq_grp);
+		__napi_schedule(&irq_grp->napi);
+	}
 
 	return IRQ_HANDLED;
 }

base-commit: cd026e68fdbf88b9cc522b76c7a9d92c9a41f709
-- 
2.43.0


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

* Re: [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler
  2026-10-15  8:44 [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler P Praneesh
@ 2026-10-21  5:07 ` Karthikeyan Periyasamy
  2026-10-27 18:29   ` Jeff Johnson
  2026-10-27  8:43 ` Baochen Qiang
  1 sibling, 1 reply; 4+ messages in thread
From: Karthikeyan Periyasamy @ 2026-10-21  5:07 UTC (permalink / raw)
  To: P Praneesh, ath12k; +Cc: karthikeyan.periyasamy, linux-wireless



On 10/15/2026 2:14 PM, P Praneesh wrote:
> On AHB platforms such as IPQ5332, IRQ group 3 maps multiple hardware
> rings to a single NAPI instance. Each ring is assigned its own IRQ
> line, but all IRQs in the group share one napi struct and one poll
> function.
> 
> When two IRQs from the same group fire simultaneously on different
> CPUs, both handlers call ath12k_ahb_ext_grp_disable(), which invokes
> disable_irq_nosync() for every IRQ in the group. This increments the
> interrupt controller's disable reference count for each IRQ twice. The
> single NAPI poll that runs calls ath12k_ahb_ext_grp_enable() once,
> decrementing each count from 2 to 1. Because the count never reaches 0,
> all IRQs in the group remain permanently masked by the interrupt
> controller.
> 
> With no further interrupts, TX completions stop being reaped from the
> WBM release ring. The pending TX descriptor count grows until the WBM
> idle link descriptor pool is exhausted. Once full, TX ring allocation
> fails and no new packets including management frames can be enqueued.
> This causes stations to disassociate with reason 34 (DISASSOC_LOW_ACK)
> and ath12k_mac_flush() to time out:
> "failed to flush transmit queue, data pkts req N pending N"
> where N equals ATH12K_NUM_POOL_TX_DESC(ab).
> 
> Fix this by using napi_schedule_prep() to atomically test-and-set
> NAPI_STATE_SCHED before disabling IRQs. Only the first CPU to win the
> atomic operation disables the group and calls __napi_schedule(). Any
> concurrent handler that loses the race skips the disable entirely,
> keeping the reference count balanced. Guard the enable_irq() call in
> the poll routine with the return value of napi_complete_done() to
> prevent an unbalanced enable if the NAPI instance was re-scheduled
> before the poll completed.
> 
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.7-00587-QCAHKSWPL_SILICONZ-1
> 
> Fixes: 6cee30f0da75 ("wifi: ath12k: add AHB driver support for IPQ5332")
> Signed-off-by: P Praneesh <praneesh.p@oss.qualcomm.com>
> ---
>   drivers/net/wireless/ath/ath12k/ahb.c | 11 ++++++-----
>   1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
> index 2c55aae06dd0..e5bbfca2b2ac 100644
> --- a/drivers/net/wireless/ath/ath12k/ahb.c
> +++ b/drivers/net/wireless/ath/ath12k/ahb.c
> @@ -602,8 +602,8 @@ static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
>   
>   	work_done = ath12k_dp_service_srng(dp, irq_grp, budget);
>   	if (work_done < budget) {
> -		napi_complete_done(napi, work_done);
> -		ath12k_ahb_ext_grp_enable(irq_grp);
> +		if (likely(napi_complete_done(napi, work_done)))
> +			ath12k_ahb_ext_grp_enable(irq_grp);
>   	}
>   
>   	if (work_done > budget)
> @@ -619,9 +619,10 @@ static irqreturn_t ath12k_ahb_ext_interrupt_handler(int irq, void *arg)
>   	/* last interrupt received for this group */
>   	irq_grp->timestamp = jiffies;
>   
> -	ath12k_ahb_ext_grp_disable(irq_grp);
> -
> -	napi_schedule(&irq_grp->napi);
> +	if (napi_schedule_prep(&irq_grp->napi)) {
> +		ath12k_ahb_ext_grp_disable(irq_grp);
> +		__napi_schedule(&irq_grp->napi);
> +	}
>   
>   	return IRQ_HANDLED;
>   }
> 
> base-commit: cd026e68fdbf88b9cc522b76c7a9d92c9a41f709

Reviewed-by: Karthikeyan Periyasamy 
<karthikeyan.periyasamy@oss.qualcomm.com>

-- 
Karthikeyan Periyasamy
--
கார்த்திகேயன் பெரியசாமி


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

* Re: [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler
  2026-10-15  8:44 [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler P Praneesh
  2026-10-21  5:07 ` Karthikeyan Periyasamy
@ 2026-10-27  8:43 ` Baochen Qiang
  1 sibling, 0 replies; 4+ messages in thread
From: Baochen Qiang @ 2026-10-27  8:43 UTC (permalink / raw)
  To: P Praneesh, ath12k; +Cc: linux-wireless



On 10/15/2026 4:44 PM, P Praneesh wrote:
> On AHB platforms such as IPQ5332, IRQ group 3 maps multiple hardware
> rings to a single NAPI instance. Each ring is assigned its own IRQ
> line, but all IRQs in the group share one napi struct and one poll
> function.
> 
> When two IRQs from the same group fire simultaneously on different
> CPUs, both handlers call ath12k_ahb_ext_grp_disable(), which invokes
> disable_irq_nosync() for every IRQ in the group. This increments the
> interrupt controller's disable reference count for each IRQ twice. The
> single NAPI poll that runs calls ath12k_ahb_ext_grp_enable() once,
> decrementing each count from 2 to 1. Because the count never reaches 0,
> all IRQs in the group remain permanently masked by the interrupt
> controller.
> 
> With no further interrupts, TX completions stop being reaped from the
> WBM release ring. The pending TX descriptor count grows until the WBM
> idle link descriptor pool is exhausted. Once full, TX ring allocation
> fails and no new packets including management frames can be enqueued.
> This causes stations to disassociate with reason 34 (DISASSOC_LOW_ACK)
> and ath12k_mac_flush() to time out:
> "failed to flush transmit queue, data pkts req N pending N"
> where N equals ATH12K_NUM_POOL_TX_DESC(ab).
> 
> Fix this by using napi_schedule_prep() to atomically test-and-set
> NAPI_STATE_SCHED before disabling IRQs. Only the first CPU to win the
> atomic operation disables the group and calls __napi_schedule(). Any
> concurrent handler that loses the race skips the disable entirely,
> keeping the reference count balanced. Guard the enable_irq() call in
> the poll routine with the return value of napi_complete_done() to
> prevent an unbalanced enable if the NAPI instance was re-scheduled
> before the poll completed.
> 
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.7-00587-QCAHKSWPL_SILICONZ-1
> 
> Fixes: 6cee30f0da75 ("wifi: ath12k: add AHB driver support for IPQ5332")
> Signed-off-by: P Praneesh <praneesh.p@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>

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

* Re: [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler
  2026-10-21  5:07 ` Karthikeyan Periyasamy
@ 2026-10-27 18:29   ` Jeff Johnson
  0 siblings, 0 replies; 4+ messages in thread
From: Jeff Johnson @ 2026-10-27 18:29 UTC (permalink / raw)
  To: Karthikeyan Periyasamy, P Praneesh, ath12k; +Cc: linux-wireless

On 10/20/2026 10:07 PM, Karthikeyan Periyasamy wrote:
> 
> 
> On 10/15/2026 2:14 PM, P Praneesh wrote:
>> On AHB platforms such as IPQ5332, IRQ group 3 maps multiple hardware
>> rings to a single NAPI instance. Each ring is assigned its own IRQ
>> line, but all IRQs in the group share one napi struct and one poll
>> function.
>>
>> When two IRQs from the same group fire simultaneously on different
>> CPUs, both handlers call ath12k_ahb_ext_grp_disable(), which invokes
>> disable_irq_nosync() for every IRQ in the group. This increments the
>> interrupt controller's disable reference count for each IRQ twice. The
>> single NAPI poll that runs calls ath12k_ahb_ext_grp_enable() once,
>> decrementing each count from 2 to 1. Because the count never reaches 0,
>> all IRQs in the group remain permanently masked by the interrupt
>> controller.
>>
>> With no further interrupts, TX completions stop being reaped from the
>> WBM release ring. The pending TX descriptor count grows until the WBM
>> idle link descriptor pool is exhausted. Once full, TX ring allocation
>> fails and no new packets including management frames can be enqueued.
>> This causes stations to disassociate with reason 34 (DISASSOC_LOW_ACK)
>> and ath12k_mac_flush() to time out:
>> "failed to flush transmit queue, data pkts req N pending N"
>> where N equals ATH12K_NUM_POOL_TX_DESC(ab).
>>
>> Fix this by using napi_schedule_prep() to atomically test-and-set
>> NAPI_STATE_SCHED before disabling IRQs. Only the first CPU to win the
>> atomic operation disables the group and calls __napi_schedule(). Any
>> concurrent handler that loses the race skips the disable entirely,
>> keeping the reference count balanced. Guard the enable_irq() call in
>> the poll routine with the return value of napi_complete_done() to
>> prevent an unbalanced enable if the NAPI instance was re-scheduled
>> before the poll completed.
>>
>> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.7-00587-QCAHKSWPL_SILICONZ-1
>>
>> Fixes: 6cee30f0da75 ("wifi: ath12k: add AHB driver support for IPQ5332")
>> Signed-off-by: P Praneesh <praneesh.p@oss.qualcomm.com>
>> ---
>>   drivers/net/wireless/ath/ath12k/ahb.c | 11 ++++++-----
>>   1 file changed, 6 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
>> index 2c55aae06dd0..e5bbfca2b2ac 100644
>> --- a/drivers/net/wireless/ath/ath12k/ahb.c
>> +++ b/drivers/net/wireless/ath/ath12k/ahb.c
>> @@ -602,8 +602,8 @@ static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
>>   
>>   	work_done = ath12k_dp_service_srng(dp, irq_grp, budget);
>>   	if (work_done < budget) {
>> -		napi_complete_done(napi, work_done);
>> -		ath12k_ahb_ext_grp_enable(irq_grp);
>> +		if (likely(napi_complete_done(napi, work_done)))
>> +			ath12k_ahb_ext_grp_enable(irq_grp);
>>   	}
>>   
>>   	if (work_done > budget)
>> @@ -619,9 +619,10 @@ static irqreturn_t ath12k_ahb_ext_interrupt_handler(int irq, void *arg)
>>   	/* last interrupt received for this group */
>>   	irq_grp->timestamp = jiffies;
>>   
>> -	ath12k_ahb_ext_grp_disable(irq_grp);
>> -
>> -	napi_schedule(&irq_grp->napi);
>> +	if (napi_schedule_prep(&irq_grp->napi)) {
>> +		ath12k_ahb_ext_grp_disable(irq_grp);
>> +		__napi_schedule(&irq_grp->napi);
>> +	}
>>   
>>   	return IRQ_HANDLED;
>>   }
>>
>> base-commit: cd026e68fdbf88b9cc522b76c7a9d92c9a41f709
> 
> Reviewed-by: Karthikeyan Periyasamy 
> <karthikeyan.periyasamy@oss.qualcomm.com>
> 
I think you meant...
Reviewed-by: Karthikeyan Periyasamy <karthikeyan.periyasamy@oss.qualcomm.com>

by posting that my tooling will now pick it up.

/jeff



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

end of thread, other threads:[~2026-10-27 18:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15  8:44 [PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler P Praneesh
2026-10-21  5:07 ` Karthikeyan Periyasamy
2026-10-27 18:29   ` Jeff Johnson
2026-10-27  8:43 ` Baochen Qiang

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