Currently, the DesignWare PCIe driver cannot configure interrupts on SoC that do not support MSIX. All MSI interrupts are handled by CPU0. Backport MSI affinity support for the PCI dwc driver from linux-next, so now we can adjust MSI interrupts to other CPU cores. Tested on HINLINK H28K (RK3528) and OrangePi R2S (Ky X1). Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn> Link: https://github.com/openwrt/openwrt/pull/21770 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
93 lines
3.3 KiB
Diff
93 lines
3.3 KiB
Diff
From eaf290c404f7c39f23292e9ce83b8b5b51ab598a Mon Sep 17 00:00:00 2001
|
|
From: Radu Rendec <rrendec@redhat.com>
|
|
Date: Fri, 28 Nov 2025 16:20:55 -0500
|
|
Subject: [PATCH] PCI: dwc: Enable MSI affinity support
|
|
|
|
Leverage the interrupt redirection infrastructure to enable CPU affinity
|
|
support for MSI interrupts. Since the parent interrupt affinity cannot
|
|
be changed, affinity control for the child interrupt (MSI) is achieved
|
|
by redirecting the handler to run in IRQ work context on the target CPU.
|
|
|
|
This patch was originally prepared by Thomas Gleixner (see Link tag below)
|
|
in a patch series that was never submitted as is, and only parts of that
|
|
series have made it upstream so far.
|
|
|
|
Originally-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Signed-off-by: Radu Rendec <rrendec@redhat.com>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Link: https://lore.kernel.org/linux-pci/878qpg4o4t.ffs@tglx/
|
|
Link: https://patch.msgid.link/20251128212055.1409093-4-rrendec@redhat.com
|
|
---
|
|
.../pci/controller/dwc/pcie-designware-host.c | 33 ++++++++++++++++---
|
|
1 file changed, 28 insertions(+), 5 deletions(-)
|
|
|
|
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
|
|
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
|
|
@@ -24,9 +24,27 @@
|
|
static struct pci_ops dw_pcie_ops;
|
|
static struct pci_ops dw_child_pcie_ops;
|
|
|
|
+#ifdef CONFIG_SMP
|
|
+static void dw_irq_noop(struct irq_data *d) { }
|
|
+#endif
|
|
+
|
|
+static bool dw_pcie_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
|
|
+ struct irq_domain *real_parent, struct msi_domain_info *info)
|
|
+{
|
|
+ if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
|
|
+ return false;
|
|
+
|
|
+#ifdef CONFIG_SMP
|
|
+ info->chip->irq_ack = dw_irq_noop;
|
|
+ info->chip->irq_pre_redirect = irq_chip_pre_redirect_parent;
|
|
+#else
|
|
+ info->chip->irq_ack = irq_chip_ack_parent;
|
|
+#endif
|
|
+ return true;
|
|
+}
|
|
+
|
|
#define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
|
|
MSI_FLAG_USE_DEF_CHIP_OPS | \
|
|
- MSI_FLAG_NO_AFFINITY | \
|
|
MSI_FLAG_PCI_MSI_MASK_PARENT)
|
|
#define DW_PCIE_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \
|
|
MSI_FLAG_PCI_MSIX | \
|
|
@@ -36,9 +54,8 @@ static const struct msi_parent_ops dw_pc
|
|
.required_flags = DW_PCIE_MSI_FLAGS_REQUIRED,
|
|
.supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED,
|
|
.bus_select_token = DOMAIN_BUS_PCI_MSI,
|
|
- .chip_flags = MSI_CHIP_FLAG_SET_ACK,
|
|
.prefix = "DW-",
|
|
- .init_dev_msi_info = msi_lib_init_dev_msi_info,
|
|
+ .init_dev_msi_info = dw_pcie_init_dev_msi_info,
|
|
};
|
|
|
|
/* MSI int handler */
|
|
@@ -59,7 +76,7 @@ void dw_handle_msi_irq(struct dw_pcie_rp
|
|
continue;
|
|
|
|
for_each_set_bit(pos, &status, MAX_MSI_IRQS_PER_CTRL)
|
|
- generic_handle_domain_irq(pp->irq_domain, irq_off + pos);
|
|
+ generic_handle_demux_domain_irq(pp->irq_domain, irq_off + pos);
|
|
}
|
|
}
|
|
|
|
@@ -136,10 +153,16 @@ static void dw_pci_bottom_ack(struct irq
|
|
|
|
static struct irq_chip dw_pci_msi_bottom_irq_chip = {
|
|
.name = "DWPCI-MSI",
|
|
- .irq_ack = dw_pci_bottom_ack,
|
|
.irq_compose_msi_msg = dw_pci_setup_msi_msg,
|
|
.irq_mask = dw_pci_bottom_mask,
|
|
.irq_unmask = dw_pci_bottom_unmask,
|
|
+#ifdef CONFIG_SMP
|
|
+ .irq_ack = dw_irq_noop,
|
|
+ .irq_pre_redirect = dw_pci_bottom_ack,
|
|
+ .irq_set_affinity = irq_chip_redirect_set_affinity,
|
|
+#else
|
|
+ .irq_ack = dw_pci_bottom_ack,
|
|
+#endif
|
|
};
|
|
|
|
static int dw_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|