PCI/MSI: Provide MSI_FLAG_MSIX_CONTIGUOUS
authorThomas Gleixner <tglx@linutronix.de>
Fri, 10 Dec 2021 22:19:20 +0000 (23:19 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 16 Dec 2021 21:16:40 +0000 (22:16 +0100)
Provide a domain info flag which makes the core code check for a contiguous
MSI-X index on allocation. That's simpler than checking it at some other
domain callback in architecture code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://lore.kernel.org/r/20211210221814.662401116@linutronix.de
drivers/pci/msi/irqdomain.c
include/linux/msi.h

index 4224202..180b2a1 100644 (file)
@@ -89,9 +89,21 @@ static int pci_msi_domain_check_cap(struct irq_domain *domain,
        if (pci_msi_desc_is_multi_msi(desc) &&
            !(info->flags & MSI_FLAG_MULTI_PCI_MSI))
                return 1;
-       else if (desc->pci.msi_attrib.is_msix && !(info->flags & MSI_FLAG_PCI_MSIX))
-               return -ENOTSUPP;
 
+       if (desc->pci.msi_attrib.is_msix) {
+               if (!(info->flags & MSI_FLAG_PCI_MSIX))
+                       return -ENOTSUPP;
+
+               if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) {
+                       unsigned int idx = 0;
+
+                       /* Check for gaps in the entry indices */
+                       for_each_msi_entry(desc, dev) {
+                               if (desc->msi_index != idx++)
+                                       return -ENOTSUPP;
+                       }
+               }
+       }
        return 0;
 }
 
index b3d3b0b..d206239 100644 (file)
@@ -362,6 +362,8 @@ enum {
        MSI_FLAG_LEVEL_CAPABLE          = (1 << 6),
        /* Populate sysfs on alloc() and destroy it on free() */
        MSI_FLAG_DEV_SYSFS              = (1 << 7),
+       /* MSI-X entries must be contiguous */
+       MSI_FLAG_MSIX_CONTIGUOUS        = (1 << 8),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,