[PATCH ath-next] wifi: ath12k: fix IRQ disable imbalance in AHB ext interrupt handler
Karthikeyan Periyasamy
karthikeyan.periyasamy at oss.qualcomm.com
Tue Oct 20 22:07:26 PDT 2026
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>
--
Karthikeyan Periyasamy
--
கார்த்திகேயன் பெரியசாமி
More information about the ath12k
mailing list