On 13-10-11 04:41 AM, Alexander Gordeev wrote: > On Thu, Oct 10, 2013 at 07:17:18PM -0400, Mark Lord wrote: >> Just to help us all understand "the loop" issue.. >> >> Here's an example of driver code which uses the existing MSI-X interfaces, >> for a device which can work with either 16, 8, 4, 2, or 1 MSI-X interrupt. >> This is from a new driver I'm working on right now: .. > Now, this is a loop-free alternative: > > static int xx_alloc_msix_irqs(struct xx_dev *dev, int nvec) > { > nvec = roundup_pow_of_two(nvec); /* assume 0 > nvec <= 16 */ > > xx_disable_all_irqs(dev); > > pci_lock_msi(dev->pdev); > > rc = pci_get_msix_limit(dev->pdev, nvec); > if (rc < 0) > goto err; > > nvec = min(nvec, rc); /* if limit is more than requested */ > nvec = rounddown_pow_of_two(nvec); /* (a) */ > > xx_prep_for_msix_vectors(dev, nvec); > > rc = pci_enable_msix(dev->pdev, dev->irqs, nvec); /* (b) */ > if (rc < 0) > goto err; > > pci_unlock_msi(dev->pdev); > > dev->num_vectors = nvec; /* (b) */ > return 0; > > err: > pci_unlock_msi(dev->pdev); > > kerr(dev->name, "pci_enable_msix() failed, err=%d", rc); > dev->num_vectors = 0; > return rc; > } That would still need a loop, to handle the natural race between the calls to pci_get_msix_limit() and pci_enable_msix() -- the driver and device can and should fall back to a smaller number of vectors when pci_enable_msix() fails.