aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2012-06-04 12:47:03 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-09-06 20:45:31 -0400
commit752f5216f1eaabb0cfa84eaecd0ce17d79c7d2cf (patch)
tree3c580a585976bac22f248f2f74a7c3c34b6f4536 /arch/powerpc
parentcf1a4cf8754afb248e498815c7957aeb4faca79f (diff)
powerpc/pseries: Round up MSI-X requests
The pseries firmware currently refuses any non power of two MSI-X request. Unfortunately most network drivers end up asking for that because they want a power of two for RX queues and one or two extra for everything else. This patch rounds up the firmware request to the next power of two if the quota allows it. If this fails we fall back to using the original request size. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pseries/msi.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 109fdb75578d..8bc89e4ecb50 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -387,12 +387,13 @@ static int check_msix_entries(struct pci_dev *pdev)
387 return 0; 387 return 0;
388} 388}
389 389
390static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 390static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
391{ 391{
392 struct pci_dn *pdn; 392 struct pci_dn *pdn;
393 int hwirq, virq, i, rc; 393 int hwirq, virq, i, rc;
394 struct msi_desc *entry; 394 struct msi_desc *entry;
395 struct msi_msg msg; 395 struct msi_msg msg;
396 int nvec = nvec_in;
396 397
397 pdn = get_pdn(pdev); 398 pdn = get_pdn(pdev);
398 if (!pdn) 399 if (!pdn)
@@ -402,10 +403,23 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
402 return -EINVAL; 403 return -EINVAL;
403 404
404 /* 405 /*
406 * Firmware currently refuse any non power of two allocation
407 * so we round up if the quota will allow it.
408 */
409 if (type == PCI_CAP_ID_MSIX) {
410 int m = roundup_pow_of_two(nvec);
411 int quota = msi_quota_for_device(pdev, m);
412
413 if (quota >= m)
414 nvec = m;
415 }
416
417 /*
405 * Try the new more explicit firmware interface, if that fails fall 418 * Try the new more explicit firmware interface, if that fails fall
406 * back to the old interface. The old interface is known to never 419 * back to the old interface. The old interface is known to never
407 * return MSI-Xs. 420 * return MSI-Xs.
408 */ 421 */
422again:
409 if (type == PCI_CAP_ID_MSI) { 423 if (type == PCI_CAP_ID_MSI) {
410 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); 424 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
411 425
@@ -417,6 +431,10 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
417 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); 431 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
418 432
419 if (rc != nvec) { 433 if (rc != nvec) {
434 if (nvec != nvec_in) {
435 nvec = nvec_in;
436 goto again;
437 }
420 pr_debug("rtas_msi: rtas_change_msi() failed\n"); 438 pr_debug("rtas_msi: rtas_change_msi() failed\n");
421 return rc; 439 return rc;
422 } 440 }