aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2013-05-22 07:07:46 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-05-24 04:16:54 -0400
commitf1dd153121dcb872ae6cba8d52bec97519eb7d97 (patch)
tree83b710801b175faceba94b063d686e293e880f86 /arch
parent83920c498ebb51cbd62f26f72e87c04a2a46dec9 (diff)
powerpc/pseries: Make 32-bit MSI quirk work on systems lacking firmware support
Recent commit e61133dda480062d221f09e4fc18f66763f8ecd0 added support for a new firmware feature to force an adapter to use 32 bit MSIs. However, this firmware is not available for all systems. The hack below allows devices needing 32 bit MSIs to work on these systems as well. It is careful to only enable this on Gen2 slots, which should limit this to configurations where this hack is needed and tested to work. [Small change to factor out the hack into a separate function -- BenH] Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/pseries/msi.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index d34f4ffdb796..6d2f0abce6fa 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -374,6 +374,23 @@ static int check_msix_entries(struct pci_dev *pdev)
374 return 0; 374 return 0;
375} 375}
376 376
377static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev)
378{
379 u32 addr_hi, addr_lo;
380
381 /*
382 * We should only get in here for IODA1 configs. This is based on the
383 * fact that we using RTAS for MSIs, we don't have the 32 bit MSI RTAS
384 * support, and we are in a PCIe Gen2 slot.
385 */
386 dev_info(&pdev->dev,
387 "rtas_msi: No 32 bit MSI firmware support, forcing 32 bit MSI\n");
388 pci_read_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, &addr_hi);
389 addr_lo = 0xffff0000 | ((addr_hi >> (48 - 32)) << 4);
390 pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_LO, addr_lo);
391 pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, 0);
392}
393
377static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) 394static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
378{ 395{
379 struct pci_dn *pdn; 396 struct pci_dn *pdn;
@@ -381,6 +398,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
381 struct msi_desc *entry; 398 struct msi_desc *entry;
382 struct msi_msg msg; 399 struct msi_msg msg;
383 int nvec = nvec_in; 400 int nvec = nvec_in;
401 int use_32bit_msi_hack = 0;
384 402
385 pdn = pci_get_pdn(pdev); 403 pdn = pci_get_pdn(pdev);
386 if (!pdn) 404 if (!pdn)
@@ -408,15 +426,31 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
408 */ 426 */
409again: 427again:
410 if (type == PCI_CAP_ID_MSI) { 428 if (type == PCI_CAP_ID_MSI) {
411 if (pdn->force_32bit_msi) 429 if (pdn->force_32bit_msi) {
412 rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec); 430 rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
413 else 431 if (rc < 0) {
432 /*
433 * We only want to run the 32 bit MSI hack below if
434 * the max bus speed is Gen2 speed
435 */
436 if (pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT)
437 return rc;
438
439 use_32bit_msi_hack = 1;
440 }
441 } else
442 rc = -1;
443
444 if (rc < 0)
414 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); 445 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
415 446
416 if (rc < 0 && !pdn->force_32bit_msi) { 447 if (rc < 0) {
417 pr_debug("rtas_msi: trying the old firmware call.\n"); 448 pr_debug("rtas_msi: trying the old firmware call.\n");
418 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); 449 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
419 } 450 }
451
452 if (use_32bit_msi_hack && rc > 0)
453 rtas_hack_32bit_msi_gen2(pdev);
420 } else 454 } else
421 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); 455 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
422 456