| /* |
| * Copyright (c) 2014 Hauke Mehrtens <hauke@hauke-m.de> |
| * |
| * Backport functionality introduced in Linux 3.14. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| */ |
| #include <linux/version.h> |
| #include <linux/kernel.h> |
| #include <linux/pci.h> |
| |
| #ifdef CONFIG_PCI_MSI |
| /** |
| * pci_enable_msi_range - configure device's MSI capability structure |
| * @dev: device to configure |
| * @minvec: minimal number of interrupts to configure |
| * @maxvec: maximum number of interrupts to configure |
| * |
| * This function tries to allocate a maximum possible number of interrupts in a |
| * range between @minvec and @maxvec. It returns a negative errno if an error |
| * occurs. If it succeeds, it returns the actual number of interrupts allocated |
| * and updates the @dev's irq member to the lowest new interrupt number; |
| * the other interrupt numbers allocated to this device are consecutive. |
| **/ |
| int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) |
| { |
| int nvec = maxvec; |
| int rc; |
| |
| if (maxvec < minvec) |
| return -ERANGE; |
| |
| do { |
| rc = pci_enable_msi_block(dev, nvec); |
| if (rc < 0) { |
| return rc; |
| } else if (rc > 0) { |
| if (rc < minvec) |
| return -ENOSPC; |
| nvec = rc; |
| } |
| } while (rc); |
| |
| return nvec; |
| } |
| EXPORT_SYMBOL(pci_enable_msi_range); |
| #endif |
| |
| #ifdef CONFIG_PCI_MSI |
| /** |
| * pci_enable_msix_range - configure device's MSI-X capability structure |
| * @dev: pointer to the pci_dev data structure of MSI-X device function |
| * @entries: pointer to an array of MSI-X entries |
| * @minvec: minimum number of MSI-X irqs requested |
| * @maxvec: maximum number of MSI-X irqs requested |
| * |
| * Setup the MSI-X capability structure of device function with a maximum |
| * possible number of interrupts in the range between @minvec and @maxvec |
| * upon its software driver call to request for MSI-X mode enabled on its |
| * hardware device function. It returns a negative errno if an error occurs. |
| * If it succeeds, it returns the actual number of interrupts allocated and |
| * indicates the successful configuration of MSI-X capability structure |
| * with new allocated MSI-X interrupts. |
| **/ |
| int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, |
| int minvec, int maxvec) |
| { |
| int nvec = maxvec; |
| int rc; |
| |
| if (maxvec < minvec) |
| return -ERANGE; |
| |
| do { |
| rc = pci_enable_msix(dev, entries, nvec); |
| if (rc < 0) { |
| return rc; |
| } else if (rc > 0) { |
| if (rc < minvec) |
| return -ENOSPC; |
| nvec = rc; |
| } |
| } while (rc); |
| |
| return nvec; |
| } |
| EXPORT_SYMBOL(pci_enable_msix_range); |
| #endif |