]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NTB: epf: Avoid calling pci_irq_vector() from hardirq context
authorKoichiro Den <den@valinux.co.jp>
Wed, 4 Mar 2026 08:30:28 +0000 (17:30 +0900)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 22 Jun 2026 20:23:40 +0000 (15:23 -0500)
ntb_epf_vec_isr() calls pci_irq_vector() in hardirq context to derive
the vector number. pci_irq_vector() calls msi_get_virq() that takes a
mutex and can therefore trigger "scheduling while atomic" splats:

  BUG: scheduling while atomic: kworker/u33:0/55/0x00010001
  ...
  Call trace:
   ...
   schedule+0x38/0x110
   schedule_preempt_disabled+0x28/0x50
   __mutex_lock.constprop.0+0x848/0x908
   __mutex_lock_slowpath+0x18/0x30
   mutex_lock+0x4c/0x60
   msi_domain_get_virq+0xe8/0x138
   pci_irq_vector+0x2c/0x60
   ntb_epf_vec_isr+0x28/0x120 [ntb_hw_epf]
   __handle_irq_event_percpu+0x70/0x3a8
   handle_irq_event+0x48/0x100
   handle_edge_irq+0x100/0x1c8
   ...

Cache the Linux IRQ number for vector 0 when vectors are allocated and
use it as a base in the ISR. Running the ISR in a threaded IRQ handler
would also avoid the problem, but that would be unnecessary here.

Fixes: 812ce2f8d14e ("NTB: Add support for EPF PCI Non-Transparent Bridge")
Signed-off-by: Koichiro Den <den@valinux.co.jp>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Cc: stable@vger.kernel.org # v5.12+
Link: https://patch.msgid.link/20260304083028.1391068-3-den@valinux.co.jp
drivers/ntb/hw/epf/ntb_hw_epf.c

index 5a35f341f82137ab944306ed6b39b1a05488d0a6..8925c688930cfedf929a81738a9766e0351938d7 100644 (file)
@@ -92,6 +92,7 @@ struct ntb_epf_dev {
 
        int db_val;
        u64 db_valid_mask;
+       int irq_base;
 };
 
 #define ntb_ndev(__ntb) container_of(__ntb, struct ntb_epf_dev, ntb)
@@ -318,7 +319,7 @@ static irqreturn_t ntb_epf_vec_isr(int irq, void *dev)
        struct ntb_epf_dev *ndev = dev;
        int irq_no;
 
-       irq_no = irq - pci_irq_vector(ndev->ntb.pdev, 0);
+       irq_no = irq - ndev->irq_base;
        ndev->db_val = irq_no + 1;
 
        if (irq_no == 0)
@@ -350,6 +351,7 @@ static int ntb_epf_init_isr(struct ntb_epf_dev *ndev, int msi_min, int msi_max)
                argument &= ~MSIX_ENABLE;
        }
 
+       ndev->irq_base = pci_irq_vector(pdev, 0);
        for (i = 0; i < irq; i++) {
                ret = request_irq(pci_irq_vector(pdev, i), ntb_epf_vec_isr,
                                  0, "ntb_epf", ndev);