From: AMEET M. PARANJAPE <aparanja@redhat.com> Date: Tue, 31 Mar 2009 11:05:20 -0400 Subject: [ppc] msi: return the number of MSIs we could allocate Message-id: 20090331150307.14954.56493.sendpatchset@squad5-lp1.lab.bos.redhat.com O-Subject: [PATCH RHEL5.4 BZ492580 5/8] Bugzilla: 492580 RH-Acked-by: David Howells <dhowells@redhat.com> RHBZ#: ====== https://bugzilla.redhat.com/show_bug.cgi?id=492580 Description: =========== If we can't allocate the requested number of MSIs, we can still tell the generic code how many we were able to allocate. That can then be passed onto the driver, allowing it to request that many in future, and probably succeeed. Also, we don't need to teardown in the RTAS routine's error path, that is handled by msi(x)_capability_init(). RHEL Version Found: ================ RHEL 5.3 kABI Status: ============ No symbols were harmed. Brew: ===== Built on all platforms. http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1744271 Upstream Status: ================ http://git.kernel.org/?p=linux/kernel/git/benh/powerpc.git;a=commit;h=6071ed0487c6ea8dcfadd9844b9b90944cd9de1e Test Status: ============ There is a testcase provided in the Bugzilla. A 'cat /proc/interrupts' should show the device drivers has two interrupt entries for each port. Run I/O tests. Then 'lspci -vv' should display the correct pci capabilities for the installed adapter and show the adapter is using MSI-X interrupts opposed to MSO or LSI interrupts. =============================================================== Ameet Paranjape 978-392-3903 ext 23903 IBM on-site partner Proposed Patch: =============== diff --git a/arch/powerpc/kernel/msi-rtas.c b/arch/powerpc/kernel/msi-rtas.c index 3aea3e9..e5ba47e 100644 --- a/arch/powerpc/kernel/msi-rtas.c +++ b/arch/powerpc/kernel/msi-rtas.c @@ -67,8 +67,14 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) seq_num = rtas_ret[1]; } while (rtas_busy_delay(rc)); - if (rc == 0) /* Success */ + /* + * If the RTAS call succeeded, return the number of irqs allocated. + * If not, make sure we return a negative error code. + */ + if (rc == 0) rc = rtas_ret[0]; + else if (rc > 0) + rc = -rc; pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d) = (%d)\n", func, num_irqs, rc); @@ -189,7 +195,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) if (type == PCI_CAP_ID_MSI) { rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); - if (rc != nvec) { + if (rc < 0) { pr_debug("rtas_msi: trying the old firmware call.\n"); rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); } @@ -198,35 +204,28 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) if (rc != nvec) { pr_debug("rtas_msi: rtas_change_msi() failed\n"); - - /* - * In case of an error it's not clear whether the device is - * left with MSI enabled or not, so we explicitly disable. - */ - goto out_free; + return rc; } i = 0; list_for_each_entry(entry, &pdn->msi_list, list) { hwirq = rtas_query_irq_number(pdn, i++); if (hwirq < 0) { - rc = hwirq; pr_debug("rtas_msi: error (%d) getting hwirq\n", rc); - goto out_free; + return hwirq; } virq = irq_create_mapping(NULL, hwirq); if (virq == NO_IRQ) { pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq); - rc = -ENOSPC; - goto out_free; + return -ENOSPC; } dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq); set_irq_msi(virq, entry); - /* Read config space back so we can restore after reset*/ + /* Read config space back so we can restore after reset */ read_msi_msg(virq, &msg); entry->msg = msg; @@ -234,10 +233,6 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) } return 0; - - out_free: - rtas_teardown_msi_irqs(pdev); - return rc; } static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)