drivers/pci/msi/msi.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index 1f716624ca56..d151bde8b8e0 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -750,32 +750,33 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, return ret; } -static bool pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *entries, - int nvec, int hwsize) +static int pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *entries, + int nvec, int hwsize) { bool nogap; - int i, j; + int maxvec; if (!entries) - return true; + return nvec; nogap = pci_msi_domain_supports(dev, MSI_FLAG_MSIX_CONTIGUOUS, DENY_LEGACY); - for (i = 0; i < nvec; i++) { + maxvec = -EINVAL; + for (int i = 0; i < nvec; i++) { /* Entry within hardware limit? */ - if (entries[i].entry >= hwsize) - return false; + if (entries[i].entry < hwsize) + maxvec = i+1; /* Check for duplicate entries */ - for (j = i + 1; j < nvec; j++) { + for (int j = i + 1; j < nvec; j++) { if (entries[i].entry == entries[j].entry) - return false; + return -EINVAL; } /* Check for unsupported gaps */ if (nogap && entries[i].entry != i) - return false; + return -EINVAL; } - return true; + return maxvec; } int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, @@ -805,8 +806,11 @@ int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int if (hwsize < 0) return hwsize; - if (!pci_msix_validate_entries(dev, entries, nvec, hwsize)) - return -EINVAL; + nvec = pci_msix_validate_entries(dev, entries, nvec, hwsize); + if (nvec < 0) + return nvec; + if (nvec < minvec) + return -ENOSPC; if (hwsize < nvec) { /* Keep the IRQ virtual hackery working */