Skip to content

Commit bab65e4

Browse files
committed
PCI/MSI: Sanitize MSI-X checks
There is no point in doing the same sanity checks over and over in a loop during MSI-X enablement. Put them in front of the loop and return early when they fail. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Acked-by: Bjorn Helgaas <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 12910ff commit bab65e4

File tree

1 file changed

+33
-32
lines changed

1 file changed

+33
-32
lines changed

drivers/pci/msi/msi.c

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -721,47 +721,31 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
721721
return ret;
722722
}
723723

724-
static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
725-
int nvec, struct irq_affinity *affd, int flags)
724+
static bool pci_msix_validate_entries(struct msix_entry *entries, int nvec, int hwsize)
726725
{
727-
int nr_entries;
728726
int i, j;
729727

730-
if (!pci_msi_supported(dev, nvec) || dev->current_state != PCI_D0)
731-
return -EINVAL;
728+
if (!entries)
729+
return true;
732730

733-
nr_entries = pci_msix_vec_count(dev);
734-
if (nr_entries < 0)
735-
return nr_entries;
736-
if (nvec > nr_entries && !(flags & PCI_IRQ_VIRTUAL))
737-
return nr_entries;
731+
for (i = 0; i < nvec; i++) {
732+
/* Entry within hardware limit? */
733+
if (entries[i].entry >= hwsize)
734+
return false;
738735

739-
if (entries) {
740-
/* Check for any invalid entries */
741-
for (i = 0; i < nvec; i++) {
742-
if (entries[i].entry >= nr_entries)
743-
return -EINVAL; /* invalid entry */
744-
for (j = i + 1; j < nvec; j++) {
745-
if (entries[i].entry == entries[j].entry)
746-
return -EINVAL; /* duplicate entry */
747-
}
736+
/* Check for duplicate entries */
737+
for (j = i + 1; j < nvec; j++) {
738+
if (entries[i].entry == entries[j].entry)
739+
return false;
748740
}
749741
}
750-
751-
/* Check whether driver already requested for MSI IRQ */
752-
if (dev->msi_enabled) {
753-
pci_info(dev, "can't enable MSI-X (MSI IRQ already assigned)\n");
754-
return -EINVAL;
755-
}
756-
return msix_capability_init(dev, entries, nvec, affd);
742+
return true;
757743
}
758744

759-
int __pci_enable_msix_range(struct pci_dev *dev,
760-
struct msix_entry *entries, int minvec,
761-
int maxvec, struct irq_affinity *affd,
762-
int flags)
745+
int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec,
746+
int maxvec, struct irq_affinity *affd, int flags)
763747
{
764-
int rc, nvec = maxvec;
748+
int hwsize, rc, nvec = maxvec;
765749

766750
if (maxvec < minvec)
767751
return -ERANGE;
@@ -774,6 +758,23 @@ int __pci_enable_msix_range(struct pci_dev *dev,
774758
if (WARN_ON_ONCE(dev->msix_enabled))
775759
return -EINVAL;
776760

761+
if (!pci_msi_supported(dev, nvec) || dev->current_state != PCI_D0)
762+
return -EINVAL;
763+
764+
hwsize = pci_msix_vec_count(dev);
765+
if (hwsize < 0)
766+
return hwsize;
767+
768+
if (!pci_msix_validate_entries(entries, nvec, hwsize))
769+
return -EINVAL;
770+
771+
/* PCI_IRQ_VIRTUAL is a horrible hack! */
772+
if (nvec > hwsize && !(flags & PCI_IRQ_VIRTUAL))
773+
nvec = hwsize;
774+
775+
if (nvec < minvec)
776+
return -ENOSPC;
777+
777778
rc = pci_setup_msi_context(dev);
778779
if (rc)
779780
return rc;
@@ -785,7 +786,7 @@ int __pci_enable_msix_range(struct pci_dev *dev,
785786
return -ENOSPC;
786787
}
787788

788-
rc = __pci_enable_msix(dev, entries, nvec, affd, flags);
789+
rc = msix_capability_init(dev, entries, nvec, affd);
789790
if (rc == 0)
790791
return nvec;
791792

0 commit comments

Comments
 (0)