diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/pseries/msi.c | 40 |
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 | ||
377 | static 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 | |||
377 | static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) | 394 | static 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 | */ |
409 | again: | 427 | again: |
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 | ||