Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2878

kernel-2.6.18-194.11.1.el5.src.rpm

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)