aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2013-05-03 07:30:59 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-05-05 19:25:37 -0400
commite61133dda480062d221f09e4fc18f66763f8ecd0 (patch)
treea18b4faf3b0126277173165565f3fa1be34f67bc /arch/powerpc/platforms
parentc2fd22df89365df9451d5b91da3b7bfd48122ecd (diff)
powerpc/pseries: Force 32 bit MSIs for devices that require it
The following patch implements a new PAPR change which allows the OS to force the use of 32 bit MSIs, regardless of what the PCI capabilities indicate. This is required for some devices that advertise support for 64 bit MSIs but don't actually support them. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/pseries/msi.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index e5b084723131..420524e6f8c9 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -24,6 +24,7 @@ static int query_token, change_token;
24#define RTAS_RESET_FN 2 24#define RTAS_RESET_FN 2
25#define RTAS_CHANGE_MSI_FN 3 25#define RTAS_CHANGE_MSI_FN 3
26#define RTAS_CHANGE_MSIX_FN 4 26#define RTAS_CHANGE_MSIX_FN 4
27#define RTAS_CHANGE_32MSI_FN 5
27 28
28static struct pci_dn *get_pdn(struct pci_dev *pdev) 29static struct pci_dn *get_pdn(struct pci_dev *pdev)
29{ 30{
@@ -58,7 +59,8 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
58 59
59 seq_num = 1; 60 seq_num = 1;
60 do { 61 do {
61 if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN) 62 if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN ||
63 func == RTAS_CHANGE_32MSI_FN)
62 rc = rtas_call(change_token, 6, 4, rtas_ret, addr, 64 rc = rtas_call(change_token, 6, 4, rtas_ret, addr,
63 BUID_HI(buid), BUID_LO(buid), 65 BUID_HI(buid), BUID_LO(buid),
64 func, num_irqs, seq_num); 66 func, num_irqs, seq_num);
@@ -426,9 +428,12 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
426 */ 428 */
427again: 429again:
428 if (type == PCI_CAP_ID_MSI) { 430 if (type == PCI_CAP_ID_MSI) {
429 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); 431 if (pdn->force_32bit_msi)
432 rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
433 else
434 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
430 435
431 if (rc < 0) { 436 if (rc < 0 && !pdn->force_32bit_msi) {
432 pr_debug("rtas_msi: trying the old firmware call.\n"); 437 pr_debug("rtas_msi: trying the old firmware call.\n");
433 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); 438 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
434 } 439 }
@@ -512,3 +517,13 @@ static int rtas_msi_init(void)
512 return 0; 517 return 0;
513} 518}
514arch_initcall(rtas_msi_init); 519arch_initcall(rtas_msi_init);
520
521static void quirk_radeon(struct pci_dev *dev)
522{
523 struct pci_dn *pdn = get_pdn(dev);
524
525 if (pdn)
526 pdn->force_32bit_msi = 1;
527}
528DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon);
529DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon);