aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@redhat.com>2013-12-30 02:28:16 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-01-03 19:17:55 -0500
commit302a2523c277bea0bbe8340312b09507905849ed (patch)
treea2d971a8aa28744c65dd454bfe4509a9be7be623 /drivers/pci/msi.c
parentff1aa430a2fa43189e89c7ddd559f0bee2298288 (diff)
PCI/MSI: Add pci_enable_msi_range() and pci_enable_msix_range()
This adds pci_enable_msi_range(), which supersedes the pci_enable_msi() and pci_enable_msi_block() MSI interfaces. It also adds pci_enable_msix_range(), which supersedes the pci_enable_msix() MSI-X interface. The old interfaces have three categories of return values: negative: failure; caller should not retry positive: failure; value indicates number of interrupts that *could* have been allocated, and caller may retry with a smaller request zero: success; at least as many interrupts allocated as requested It is error-prone to handle these three cases correctly in drivers. The new functions return either a negative error code or a number of successfully allocated MSI/MSI-X interrupts, which is expected to lead to clearer device driver code. pci_enable_msi(), pci_enable_msi_block() and pci_enable_msix() still exist unchanged, but are deprecated and may be removed after callers are updated. [bhelgaas: tweak changelog] Suggested-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Alexander Gordeev <agordeev@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r--drivers/pci/msi.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index bd18ecf74c55..e6bd8e57d92d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1102,3 +1102,77 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
1102 if (dev->msix_cap) 1102 if (dev->msix_cap)
1103 msix_set_enable(dev, 0); 1103 msix_set_enable(dev, 0);
1104} 1104}
1105
1106/**
1107 * pci_enable_msi_range - configure device's MSI capability structure
1108 * @dev: device to configure
1109 * @minvec: minimal number of interrupts to configure
1110 * @maxvec: maximum number of interrupts to configure
1111 *
1112 * This function tries to allocate a maximum possible number of interrupts in a
1113 * range between @minvec and @maxvec. It returns a negative errno if an error
1114 * occurs. If it succeeds, it returns the actual number of interrupts allocated
1115 * and updates the @dev's irq member to the lowest new interrupt number;
1116 * the other interrupt numbers allocated to this device are consecutive.
1117 **/
1118int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
1119{
1120 int nvec = maxvec;
1121 int rc;
1122
1123 if (maxvec < minvec)
1124 return -ERANGE;
1125
1126 do {
1127 rc = pci_enable_msi_block(dev, nvec);
1128 if (rc < 0) {
1129 return rc;
1130 } else if (rc > 0) {
1131 if (rc < minvec)
1132 return -ENOSPC;
1133 nvec = rc;
1134 }
1135 } while (rc);
1136
1137 return nvec;
1138}
1139EXPORT_SYMBOL(pci_enable_msi_range);
1140
1141/**
1142 * pci_enable_msix_range - configure device's MSI-X capability structure
1143 * @dev: pointer to the pci_dev data structure of MSI-X device function
1144 * @entries: pointer to an array of MSI-X entries
1145 * @minvec: minimum number of MSI-X irqs requested
1146 * @maxvec: maximum number of MSI-X irqs requested
1147 *
1148 * Setup the MSI-X capability structure of device function with a maximum
1149 * possible number of interrupts in the range between @minvec and @maxvec
1150 * upon its software driver call to request for MSI-X mode enabled on its
1151 * hardware device function. It returns a negative errno if an error occurs.
1152 * If it succeeds, it returns the actual number of interrupts allocated and
1153 * indicates the successful configuration of MSI-X capability structure
1154 * with new allocated MSI-X interrupts.
1155 **/
1156int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
1157 int minvec, int maxvec)
1158{
1159 int nvec = maxvec;
1160 int rc;
1161
1162 if (maxvec < minvec)
1163 return -ERANGE;
1164
1165 do {
1166 rc = pci_enable_msix(dev, entries, nvec);
1167 if (rc < 0) {
1168 return rc;
1169 } else if (rc > 0) {
1170 if (rc < minvec)
1171 return -ENOSPC;
1172 nvec = rc;
1173 }
1174 } while (rc);
1175
1176 return nvec;
1177}
1178EXPORT_SYMBOL(pci_enable_msix_range);