[GIT pull] irq/urgent for v6.15-rc1

From: Thomas Gleixner
Date: Wed Mar 26 2025 - 15:08:29 EST


Linus,

please pull the latest irq/urgent branch from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-urgent-2025-03-26

up to: 3ece3e8e5976: PCI/MSI: Handle the NOMASK flag correctly for all PCI/MSI backends

A urgent fix for the XEN related PCI/MSI changes:

XEN used a global variable to disable the masking of MSI interrupts as
XEN handles that on the hypervisor side. This turned out to be a problem
with VMD as the PCI devices behind a VMD bridge are not always handled
by the hypervisor and then require masking by guest.

To solve this the global variable was replaced by a interrupt domain
specific flag, which is set by the generic XEN PCI/MSI domain, but not by
VMD or any other domain in the system.

So far, so good. But the implementation (and the reviewer) missed the
fact, that accessing the domain flag cannot be done directly because
there are at least two situations, where this fails. Legacy architectures
are not providing interrupt domains at all. The new MSI parent domains do
not require to have a domain info pointer. Both cases result in a
unconditional NULL pointer derefence.

The PCI/MSI code already has a function to query the MSI domain specific
flag in a safe way, which handles all possible cases of PCI/MSI backends.

So the fix it simply to replace the open coded checks by invoking the
safe helper to query the flag.

Note: This is hot of the press, but has been tested and validated. As it
affects a lot of people, I fast tracked it.

Thanks,

tglx

------------------>
Thomas Gleixner (1):
PCI/MSI: Handle the NOMASK flag correctly for all PCI/MSI backends


drivers/pci/msi/msi.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
index d74162880d83..7058d59e7c5f 100644
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -285,8 +285,6 @@ static void pci_msi_set_enable(struct pci_dev *dev, int enable)
static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
struct irq_affinity_desc *masks)
{
- const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
- const struct msi_domain_info *info = d->host_data;
struct msi_desc desc;
u16 control;

@@ -297,7 +295,7 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
/* Lies, damned lies, and MSIs */
if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
control |= PCI_MSI_FLAGS_MASKBIT;
- if (info->flags & MSI_FLAG_NO_MASK)
+ if (pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY))
control &= ~PCI_MSI_FLAGS_MASKBIT;

desc.nvec_used = nvec;
@@ -604,20 +602,18 @@ static void __iomem *msix_map_region(struct pci_dev *dev,
*/
void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc)
{
- const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
- const struct msi_domain_info *info = d->host_data;
-
desc->nvec_used = 1;
desc->pci.msi_attrib.is_msix = 1;
desc->pci.msi_attrib.is_64 = 1;
desc->pci.msi_attrib.default_irq = dev->irq;
desc->pci.mask_base = dev->msix_base;
- desc->pci.msi_attrib.can_mask = !(info->flags & MSI_FLAG_NO_MASK) &&
- !desc->pci.msi_attrib.is_virtual;

- if (desc->pci.msi_attrib.can_mask) {
+
+ if (!pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY) &&
+ !desc->pci.msi_attrib.is_virtual) {
void __iomem *addr = pci_msix_desc_addr(desc);

+ desc->pci.msi_attrib.can_mask = 1;
desc->pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
}
}
@@ -715,8 +711,6 @@ static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries
static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
int nvec, struct irq_affinity *affd)
{
- const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
- const struct msi_domain_info *info = d->host_data;
int ret, tsize;
u16 control;

@@ -747,7 +741,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
/* Disable INTX */
pci_intx_for_msi(dev, 0);

- if (!(info->flags & MSI_FLAG_NO_MASK)) {
+ if (!pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY)) {
/*
* Ensure that all table entries are masked to prevent
* stale entries from firing in a crash kernel.