diff mbox

[10/10] powerpc/mpic: Add in-core support for cascaded MPICs

Message ID 1322593117-29938-11-git-send-email-Kyle.D.Moffett@boeing.com (mailing list archive)
State Superseded, archived
Delegated to: Benjamin Herrenschmidt
Headers show

Commit Message

Kyle Moffett Nov. 29, 2011, 6:58 p.m. UTC
The Cell and PowerMac platforms use virtually identical cascaded-IRQ
setup code, so just merge it into the core.  Ideally this code would
trigger automatically when an MPIC device-node specifies an "interrupts"
property, perhaps even enabling MPIC_SECONDARY along the way.

Unfortunately, Benjamin Herrenschmidt has had bad experiences in the
past with the quality of Apple PowerMac device-trees, so to be safe we
will only try to parse out an IRQ if the MPIC_SECONDARY flag is set by
the caller.

Signed-off-by: Kyle Moffett <Kyle.D.Moffett@boeing.com>
---
 arch/powerpc/platforms/cell/setup.c   |   22 --------------------
 arch/powerpc/platforms/powermac/pic.c |   36 ++++----------------------------
 arch/powerpc/sysdev/mpic.c            |   30 +++++++++++++++++++++++++-
 3 files changed, 33 insertions(+), 55 deletions(-)

Comments

Michael Ellerman Dec. 1, 2011, 6:59 a.m. UTC | #1
On Tue, 2011-11-29 at 13:58 -0500, Kyle Moffett wrote:
> diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
> index cd00ca8..a0f5d28 100644
> --- a/arch/powerpc/platforms/cell/setup.c
> +++ b/arch/powerpc/platforms/cell/setup.c
> @@ -215,15 +202,6 @@ static void __init mpic_init_IRQ(void)
>  		if (mpic == NULL)
>  			continue;
>  		mpic_init(mpic);
> -
> -		virq = irq_of_parse_and_map(dn, 0);
> -		if (virq == NO_IRQ)
> -			continue;
> -
> -		printk(KERN_INFO "%s : hooking up to IRQ %d\n",
> -		       dn->full_name, virq);
> -		irq_set_handler_data(virq, mpic);
> -		irq_set_chained_handler(virq, cell_mpic_cascade);
>  	}
>  }

This leaves virq unused, which breaks the build.

cheers
Kyle Moffett Dec. 2, 2011, 1:48 a.m. UTC | #2
Ben,

I fixed the 3 issues that Paul and Michael reported and I can provide them
to you two different ways, however you would prefer.  I can also send the
patches via email if that's more convenient.

Option 1: Squashed into the the original patches for bisectability:
  git://opensource.exmeritus.com/hww-1u-1a/linux.git mpc85xx/mpic-and-stuff

Option 2: As a fixup patch on the end:
  git://opensource.exmeritus.com/hww-1u-1a/linux.git mpc85xx/mpic-and-stuff-fixup

You can also use HTTP if you would prefer:
  http://opensource.exmeritus.com/git/hww-1u-1a/linux.git

Cheers,
Kyle Moffett

--
Curious about my work on the Debian powerpcspe port?
I'm keeping a blog here: http://pureperl.blogspot.com/
Benjamin Herrenschmidt Dec. 2, 2011, 3:04 a.m. UTC | #3
On Thu, 2011-12-01 at 19:48 -0600, Moffett, Kyle D wrote:
> Ben,
> 
> I fixed the 3 issues that Paul and Michael reported and I can provide them
> to you two different ways, however you would prefer.  I can also send the
> patches via email if that's more convenient.
> 
> Option 1: Squashed into the the original patches for bisectability:
>   git://opensource.exmeritus.com/hww-1u-1a/linux.git mpc85xx/mpic-and-stuff

This option, please just re-send to the list.

Cheers,
Ben.
Kyle Moffett Dec. 2, 2011, 4:27 p.m. UTC | #4
Hello,

This is version 3 of the MPIC cleanup patches.

A few minor bugfixes have been rolled into patches 2, 7, and 10, kudos
to Paul Mackerras and Michael Ellerman for reporting them.

Additionally, the series has been rebased onto Ben's "next" branch
for easier merging:
  git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next

Unfortunately, my local board-support code conflicts with the mpc85xx
device-tree updates in that branch, so I haven't been able to do more
testing locally.  I will hopefully have that resolved soon, however.

Cheers,
Kyle Moffett
diff mbox

Patch

diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index cd00ca8..a0f5d28 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -184,19 +184,6 @@  static int __init cell_publish_devices(void)
 }
 machine_subsys_initcall(cell, cell_publish_devices);
 
-static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct mpic *mpic = irq_desc_get_handler_data(desc);
-	unsigned int virq;
-
-	virq = mpic_get_one_irq(mpic);
-	if (virq != NO_IRQ)
-		generic_handle_irq(virq);
-
-	chip->irq_eoi(&desc->irq_data);
-}
-
 static void __init mpic_init_IRQ(void)
 {
 	struct device_node *dn;
@@ -215,15 +202,6 @@  static void __init mpic_init_IRQ(void)
 		if (mpic == NULL)
 			continue;
 		mpic_init(mpic);
-
-		virq = irq_of_parse_and_map(dn, 0);
-		if (virq == NO_IRQ)
-			continue;
-
-		printk(KERN_INFO "%s : hooking up to IRQ %d\n",
-		       dn->full_name, virq);
-		irq_set_handler_data(virq, mpic);
-		irq_set_chained_handler(virq, cell_mpic_cascade);
 	}
 }
 
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index bbfcc94..5cbceb4 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -464,18 +464,6 @@  int of_irq_map_oldworld(struct device_node *device, int index,
 }
 #endif /* CONFIG_PPC32 */
 
-static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-	struct mpic *mpic = irq_desc_get_handler_data(desc);
-	unsigned int cascade_irq = mpic_get_one_irq(mpic);
-
-	if (cascade_irq != NO_IRQ)
-		generic_handle_irq(cascade_irq);
-
-	chip->irq_eoi(&desc->irq_data);
-}
-
 static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
 {
 #if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
@@ -527,7 +515,6 @@  static int __init pmac_pic_probe_mpic(void)
 {
 	struct mpic *mpic1, *mpic2;
 	struct device_node *np, *master = NULL, *slave = NULL;
-	unsigned int cascade;
 
 	/* We can have up to 2 MPICs cascaded */
 	for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
@@ -563,27 +550,14 @@  static int __init pmac_pic_probe_mpic(void)
 
 	of_node_put(master);
 
-	/* No slave, let's go out */
-	if (slave == NULL)
-		return 0;
-
-	/* Get/Map slave interrupt */
-	cascade = irq_of_parse_and_map(slave, 0);
-	if (cascade == NO_IRQ) {
-		printk(KERN_ERR "Failed to map cascade IRQ\n");
-		return 0;
-	}
-
-	mpic2 = pmac_setup_one_mpic(slave, 0);
-	if (mpic2 == NULL) {
-		printk(KERN_ERR "Failed to setup slave MPIC\n");
+	/* Set up a cascaded controller, if present */
+	if (slave) {
+		mpic2 = pmac_setup_one_mpic(slave, 0);
+		if (mpic2 == NULL)
+			printk(KERN_ERR "Failed to setup slave MPIC\n");
 		of_node_put(slave);
-		return 0;
 	}
-	irq_set_handler_data(cascade, mpic2);
-	irq_set_chained_handler(cascade, pmac_u3_cascade);
 
-	of_node_put(slave);
 	return 0;
 }
 
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 67842a5..02191bb 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1111,6 +1111,22 @@  static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
 	return 0;
 }
 
+/* IRQ handler for a secondary MPIC cascaded from another IRQ controller */
+static void mpic_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct mpic *mpic = irq_desc_get_handler_data(desc);
+	unsigned int virq;
+
+	BUG_ON(!(mpic->flags & MPIC_SECONDARY));
+
+	virq = mpic_get_one_irq(mpic);
+	if (virq != NO_IRQ)
+		generic_handle_irq(virq);
+
+	chip->irq_eoi(&desc->irq_data);
+}
+
 static struct irq_host_ops mpic_host_ops = {
 	.match = mpic_host_match,
 	.map = mpic_host_map,
@@ -1402,8 +1418,7 @@  void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
 
 void __init mpic_init(struct mpic *mpic)
 {
-	int i;
-	int cpu;
+	int i, cpu;
 
 	BUG_ON(mpic->num_sources == 0);
 
@@ -1488,6 +1503,17 @@  void __init mpic_init(struct mpic *mpic)
 				  GFP_KERNEL);
 	BUG_ON(mpic->save_data == NULL);
 #endif
+
+	/* Check if this MPIC is chained from a parent interrupt controller */
+	if (mpic->flags & MPIC_SECONDARY) {
+		int virq = irq_of_parse_and_map(mpic->node, 0);
+		if (virq != NO_IRQ) {
+			printk(KERN_INFO "%s: hooking up to IRQ %d\n",
+					mpic->node->full_name, virq);
+			irq_set_handler_data(virq, mpic);
+			irq_set_chained_handler(virq, &mpic_cascade);
+		}
+	}
 }
 
 void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)