Commit 4644d22e authored by Thomas Gleixner's avatar Thomas Gleixner

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: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Link: https://lore.kernel.org/r/20221111122015.691357406@linutronix.de
parent 99f3d279
...@@ -725,13 +725,17 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, ...@@ -725,13 +725,17 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
return ret; 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; int i, j;
if (!entries) if (!entries)
return true; return true;
nogap = pci_msi_domain_supports(dev, MSI_FLAG_MSIX_CONTIGUOUS, DENY_LEGACY);
for (i = 0; i < nvec; i++) { for (i = 0; i < nvec; i++) {
/* Entry within hardware limit? */ /* Entry within hardware limit? */
if (entries[i].entry >= hwsize) if (entries[i].entry >= hwsize)
...@@ -742,6 +746,9 @@ static bool pci_msix_validate_entries(struct msix_entry *entries, int nvec, int ...@@ -742,6 +746,9 @@ static bool pci_msix_validate_entries(struct msix_entry *entries, int nvec, int
if (entries[i].entry == entries[j].entry) if (entries[i].entry == entries[j].entry)
return false; return false;
} }
/* Check for unsupported gaps */
if (nogap && entries[i].entry != i)
return false;
} }
return true; return true;
} }
...@@ -773,7 +780,7 @@ int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int ...@@ -773,7 +780,7 @@ int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int
if (hwsize < 0) if (hwsize < 0)
return hwsize; return hwsize;
if (!pci_msix_validate_entries(entries, nvec, hwsize)) if (!pci_msix_validate_entries(dev, entries, nvec, hwsize))
return -EINVAL; return -EINVAL;
/* PCI_IRQ_VIRTUAL is a horrible hack! */ /* PCI_IRQ_VIRTUAL is a horrible hack! */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment