Commit f1dd153121dcb872ae6cba8d52bec97519eb7d97

Authored by Brian King
Committed by Benjamin Herrenschmidt
1 parent 83920c498e

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>

Showing 1 changed file with 37 additions and 3 deletions Side-by-side Diff

arch/powerpc/platforms/pseries/msi.c
... ... @@ -374,6 +374,23 @@
374 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 394 static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
378 395 {
379 396 struct pci_dn *pdn;
... ... @@ -381,6 +398,7 @@
381 398 struct msi_desc *entry;
382 399 struct msi_msg msg;
383 400 int nvec = nvec_in;
  401 + int use_32bit_msi_hack = 0;
384 402  
385 403 pdn = pci_get_pdn(pdev);
386 404 if (!pdn)
387 405  
388 406  
389 407  
... ... @@ -408,15 +426,31 @@
408 426 */
409 427 again:
410 428 if (type == PCI_CAP_ID_MSI) {
411   - if (pdn->force_32bit_msi)
  429 + if (pdn->force_32bit_msi) {
412 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 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 448 pr_debug("rtas_msi: trying the old firmware call.\n");
418 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 454 } else
421 455 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
422 456