diff options
author | Alexander Gordeev <agordeev@redhat.com> | 2013-12-30 02:28:16 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-01-03 19:17:55 -0500 |
commit | 302a2523c277bea0bbe8340312b09507905849ed (patch) | |
tree | a2d971a8aa28744c65dd454bfe4509a9be7be623 /drivers/pci/msi.c | |
parent | ff1aa430a2fa43189e89c7ddd559f0bee2298288 (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.c | 74 |
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 | **/ | ||
1118 | int 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 | } | ||
1139 | EXPORT_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 | **/ | ||
1156 | int 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 | } | ||
1178 | EXPORT_SYMBOL(pci_enable_msix_range); | ||