[PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler

Jeff Johnson jeff.johnson at oss.qualcomm.com
Tue Oct 27 11:29:26 PDT 2026


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 at 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 at oss.qualcomm.com>
> 
I think you meant...
Reviewed-by: Karthikeyan Periyasamy <karthikeyan.periyasamy at oss.qualcomm.com>

by posting that my tooling will now pick it up.

/jeff





More information about the ath12k mailing list