diff options
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_pcie.c | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index c8d9c4ab142b..61a0046efb76 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c | |||
@@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt, | |||
197 | struct qib_msix_entry *qib_msix_entry) | 197 | struct qib_msix_entry *qib_msix_entry) |
198 | { | 198 | { |
199 | int ret; | 199 | int ret; |
200 | u32 tabsize = 0; | 200 | int nvec = *msixcnt; |
201 | u16 msix_flags; | ||
202 | struct msix_entry *msix_entry; | 201 | struct msix_entry *msix_entry; |
203 | int i; | 202 | int i; |
204 | 203 | ||
204 | ret = pci_msix_vec_count(dd->pcidev); | ||
205 | if (ret < 0) | ||
206 | goto do_intx; | ||
207 | |||
208 | nvec = min(nvec, ret); | ||
209 | |||
205 | /* We can't pass qib_msix_entry array to qib_msix_setup | 210 | /* We can't pass qib_msix_entry array to qib_msix_setup |
206 | * so use a dummy msix_entry array and copy the allocated | 211 | * so use a dummy msix_entry array and copy the allocated |
207 | * irq back to the qib_msix_entry array. */ | 212 | * irq back to the qib_msix_entry array. */ |
208 | msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL); | 213 | msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL); |
209 | if (!msix_entry) { | 214 | if (!msix_entry) |
210 | ret = -ENOMEM; | ||
211 | goto do_intx; | 215 | goto do_intx; |
212 | } | 216 | |
213 | for (i = 0; i < *msixcnt; i++) | 217 | for (i = 0; i < nvec; i++) |
214 | msix_entry[i] = qib_msix_entry[i].msix; | 218 | msix_entry[i] = qib_msix_entry[i].msix; |
215 | 219 | ||
216 | pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags); | 220 | ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); |
217 | tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE); | 221 | if (ret < 0) |
218 | if (tabsize > *msixcnt) | 222 | goto free_msix_entry; |
219 | tabsize = *msixcnt; | 223 | else |
220 | ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); | 224 | nvec = ret; |
221 | if (ret > 0) { | 225 | |
222 | tabsize = ret; | 226 | for (i = 0; i < nvec; i++) |
223 | ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); | ||
224 | } | ||
225 | do_intx: | ||
226 | if (ret) { | ||
227 | qib_dev_err(dd, | ||
228 | "pci_enable_msix %d vectors failed: %d, falling back to INTx\n", | ||
229 | tabsize, ret); | ||
230 | tabsize = 0; | ||
231 | } | ||
232 | for (i = 0; i < tabsize; i++) | ||
233 | qib_msix_entry[i].msix = msix_entry[i]; | 227 | qib_msix_entry[i].msix = msix_entry[i]; |
228 | |||
234 | kfree(msix_entry); | 229 | kfree(msix_entry); |
235 | *msixcnt = tabsize; | 230 | *msixcnt = nvec; |
231 | return; | ||
236 | 232 | ||
237 | if (ret) | 233 | free_msix_entry: |
238 | qib_enable_intx(dd->pcidev); | 234 | kfree(msix_entry); |
239 | 235 | ||
236 | do_intx: | ||
237 | qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, " | ||
238 | "falling back to INTx\n", nvec, ret); | ||
239 | *msixcnt = 0; | ||
240 | qib_enable_intx(dd->pcidev); | ||
240 | } | 241 | } |
241 | 242 | ||
242 | /** | 243 | /** |