[PATCH RFC 2/2] irqchip/ls-scfg-msi: enable multi-MSI allocation

From: Alexander Wilhelm

Date: Thu Jul 16 2026 - 06:37:42 EST


Add MSI_FLAG_MULTI_PCI_MSI to the parent domain's supported flags so PCI
devices can request more than one contiguous MSI vector. The previous
refactor to bitmap_find_free_region() already handles arbitrary
power-of-two orders, so drop the WARN_ON(nr_irqs != 1) guard.

In practice, multi-MSI requires the 'no-affinity' MSIR routing, because
affinity mode only releases every (1 << ibs_shift)-th hwirq and therefore
cannot satisfy aligned power-of-two blocks larger than one bit. Statically
pin each MSIR's chained parent IRQ to its matching CPU in that mode: the
low ibs_shift bits of the hwirq then select both the MSIR and the target
CPU, giving each MSI vector a deterministic target CPU without runtime
migration.

Assisted-by: Copilot:claude-opus-4.7
Signed-off-by: Alexander Wilhelm <alexander.wilhelm@xxxxxxxxxxxx>
---
drivers/irqchip/irq-ls-scfg-msi.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index bd5833ef621a..a9660bbcdf7f 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -60,6 +60,7 @@ struct ls_scfg_msi {
#define MPIC_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
MSI_FLAG_USE_DEF_CHIP_OPS)
#define MPIC_MSI_FLAGS_SUPPORTED (MSI_FLAG_PCI_MSIX | \
+ MSI_FLAG_MULTI_PCI_MSI | \
MSI_GENERIC_FLAGS_MASK)

static const struct msi_parent_ops ls_scfg_msi_parent_ops = {
@@ -145,8 +146,6 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain,
int pos, err;
unsigned int i;

- WARN_ON(nr_irqs != 1);
-
spin_lock(&msi_data->lock);
pos = bitmap_find_free_region(msi_data->used, msi_data->irqs_num,
order);
@@ -271,8 +270,12 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
/* Associate MSIR interrupt to the cpu */
irq_set_affinity(msir->gic_irq, get_cpu_mask(index));
msir->srs = 0; /* This value is determined by the CPU */
- } else
+ } else {
msir->srs = index;
+ /* Statically pin each MSIR to its matching CPU */
+ if (index < num_possible_cpus())
+ irq_set_affinity(msir->gic_irq, get_cpu_mask(index));
+ }

/* Release the hwirqs corresponding to this MSIR */
if (!msi_affinity_flag || msir->index == 0) {

--
2.43.0