]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: qtnfmac: topaz: defer IRQ enabling until IPC init
authorRunyu Xiao <runyu.xiao@seu.edu.cn>
Sun, 31 May 2026 14:54:35 +0000 (22:54 +0800)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 3 Jun 2026 12:11:56 +0000 (14:11 +0200)
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, if the hardware misbehaves.

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.

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.

Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Link: https://patch.msgid.link/20260531145435.701703-1-runyu.xiao@seu.edu.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c

index ef5c069542d4bc76c441ba9604b11cd8d60bd2dc..a3a285f17dca72d89762893f818685dfc42daeb6 100644 (file)
@@ -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");