summaryrefslogtreecommitdiff
path: root/drivers/pci/msi
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2022-11-11 14:55:12 +0100
committerThomas Gleixner <tglx@linutronix.de>2022-11-17 15:15:22 +0100
commit4644d22eb673f173252610a93aaaba4c2bff7b41 (patch)
tree3f28c4ebe72b6baec02f4104f0d20fd78404fe55 /drivers/pci/msi
parent99f3d279765725920aa5924fa445537a20129a6f (diff)
PCI/MSI: Validate MSI-X contiguous restriction early
With interrupt domains the sanity check for MSI-X vector validation can be done _before_ any allocation happens. The sanity check only applies to the allocation functions which have an 'entries' array argument. The entries array is filled by the caller with the requested MSI-X indices. Some drivers have gaps in the index space which is not supported on all architectures. The PCI/MSI irq domain has a 'feature' bit to enforce this validation late during the allocation phase. Just do it right away before doing any other work along with the other sanity checks on that array. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://lore.kernel.org/r/20221111122015.691357406@linutronix.de
Diffstat (limited to 'drivers/pci/msi')
-rw-r--r--drivers/pci/msi/msi.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
index 0740acd10bde..b94f6da3f32f 100644
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -725,13 +725,17 @@ out_disable:
return ret;
}
-static bool pci_msix_validate_entries(struct msix_entry *entries, int nvec, int hwsize)
+static bool pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *entries,
+ int nvec, int hwsize)
{
+ bool nogap;
int i, j;
if (!entries)
return true;
+ nogap = pci_msi_domain_supports(dev, MSI_FLAG_MSIX_CONTIGUOUS, DENY_LEGACY);
+
for (i = 0; i < nvec; i++) {
/* Entry within hardware limit? */
if (entries[i].entry >= hwsize)
@@ -742,6 +746,9 @@ static bool pci_msix_validate_entries(struct msix_entry *entries, int nvec, int
if (entries[i].entry == entries[j].entry)
return false;
}
+ /* Check for unsupported gaps */
+ if (nogap && entries[i].entry != i)
+ return false;
}
return true;
}
@@ -773,7 +780,7 @@ int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int
if (hwsize < 0)
return hwsize;
- if (!pci_msix_validate_entries(entries, nvec, hwsize))
+ if (!pci_msix_validate_entries(dev, entries, nvec, hwsize))
return -EINVAL;
/* PCI_IRQ_VIRTUAL is a horrible hack! */