[PATCH wireless] wifi: qtnfmac: topaz: defer IRQ enabling until IPC init

From: Runyu Xiao

Date: Sun May 31 2026 - 11:11:02 EST


qtnf_pcie_topaz_probe() currently calls devm_request_irq() and only then
disable_irq(). request_irq() installs the action in the irq core
immediately, so qtnf_pcie_topaz_interrupt() can run before the Topaz
private IRQ consumers are initialized.

This window is reachable on a running system as soon as probe has
successfully registered pdev->irq but before qtnf_pcie_init_shm_ipc()
sets shm_ipc_ep_in/out.irq_handler. If an interrupt is delivered in
this interval, qtnf_pcie_topaz_interrupt() calls
qtnf_shm_ipc_irq_handler() for shm_ipc_ep_in/out while their irq_handler
callbacks are still unset, so the driver can observe an early IRQ
before its IPC consumer state is ready.

The issue was found on Linux v6.18.21 by our static analysis tool while
scanning request_irq()/disable_irq() registration-order bugs in
wireless PCIe drivers, and then manually reviewed. It was validated
with a QEMU no-device harness using
IRQ_SIM and a directed generic_handle_irq_safe() injection between
request_irq() and qtnf_pcie_init_shm_ipc(). The harness reported:

has_action=1 shm_in=0000000000000000 shm_out=0000000000000000
reached handler before shm_ipc init
irq_count=1

This is family-level runtime evidence for the same early-IRQ window. No
Topaz hardware was available to exercise the real device path end-to-end.

Request the IRQ with IRQF_NO_AUTOEN instead and keep the existing
enable_irq() in qtnf_post_init_ep() as the point where interrupts
become visible. This closes the early-IRQ window while preserving the
intended bring-up order.

Build-tested by compiling topaz_pcie.o on x86_64.

Fixes: e401fa25cfa2 ("qtnfmac: add support for Topaz chipsets")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
---
drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
index ef5c069542d4..a3a285f17dca 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -1132,9 +1132,9 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,

/* assign host msi irq before card init */
if (ts->base.msi_enabled)
- irqflags = IRQF_NOBALANCING;
+ irqflags = IRQF_NOBALANCING | IRQF_NO_AUTOEN;
else
- irqflags = IRQF_NOBALANCING | IRQF_SHARED;
+ irqflags = IRQF_NOBALANCING | IRQF_SHARED | IRQF_NO_AUTOEN;

ret = devm_request_irq(&pdev->dev, pdev->irq,
&qtnf_pcie_topaz_interrupt,
@@ -1144,8 +1144,6 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,
return ret;
}

- disable_irq(pdev->irq);
-
ret = qtnf_pre_init_ep(bus);
if (ret) {
pr_err("failed to init card\n");
--
2.34.1