[PATCH] PowerMac use of SA_CASCADEIRQ

From: Benjamin Herrenschmidt
Date: Thu May 11 2006 - 01:41:22 EST


On Thu, 2006-05-11 at 15:26 +1000, Benjamin Herrenschmidt wrote:

> This patch is an implementation that was quickly tested on G5 (a second
> patch to use that for the G5 follows) and seems to work fine.

Here is the patch implementing that for the cascaced MPIC. Seems to work
fine here. (This is not useful on Quad G5s btw, only older ones really
use a cascade). This is more a test patch, not intended for merging.
I'll do a proper one if the support for SA_CASCADEIRQ goes in. There are
other issues with the way the PowerMac codes uses static irqaction
structures & directly calls setup_irq() in order to be able to install
irq actions before kmalloc is available. I want to make request_irq()
useable earlier instead, by having fallback on bootmem alloc, it make a
lot of sense for low level architecture interrupts that will never be
freed. I also noticed that the irq proc stuff has an issue with irqs
created before /proc is initialized, it will create the /proc/irq/* but
nothing below for existing actions. I'll look into fixing that as well.

Index: linux-work/arch/powerpc/platforms/powermac/pic.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pic.c 2006-01-14 14:43:22.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/pic.c 2006-05-11 15:27:58.000000000 +1000
@@ -199,7 +199,7 @@ struct hw_interrupt_type gatwick_pic = {

static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
{
- int irq, bits;
+ unsigned int irq, bits;

for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
int i = irq >> 5;
@@ -210,8 +210,7 @@ static irqreturn_t gatwick_action(int cp
if (bits == 0)
continue;
irq += __ilog2(bits);
- __do_IRQ(irq, regs);
- return IRQ_HANDLED;
+ return irq;
}
printk("gatwick irq not from gatwick pic\n");
return IRQ_NONE;
@@ -382,7 +381,7 @@ static struct irqaction xmon_action = {

static struct irqaction gatwick_cascade_action = {
.handler = gatwick_action,
- .flags = SA_INTERRUPT,
+ .flags = SA_CASCADEIRQ | SA_INTERRUPT,
.mask = CPU_MASK_NONE,
.name = "cascade",
};
@@ -503,11 +502,6 @@ static void __init pmac_pic_probe_oldsty
}
#endif /* CONFIG_PPC32 */

-static int pmac_u3_cascade(struct pt_regs *regs, void *data)
-{
- return mpic_get_one_irq((struct mpic *)data, regs);
-}
-
static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
{
#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
@@ -562,12 +556,28 @@ static struct mpic * __init pmac_setup_o
mpic_init(mpic);

return mpic;
- }
+}
+
+static irqreturn_t mpic_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int ret = mpic_get_one_irq(dev_id, regs);
+ if (unlikely(ret < 0))
+ return IRQ_NONE;
+ return ret;
+}
+
+static struct irqaction mpic_cascade_action = {
+ .handler = mpic_cascade,
+ .flags = SA_INTERRUPT | SA_CASCADEIRQ,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};

static int __init pmac_pic_probe_mpic(void)
{
struct mpic *mpic1, *mpic2;
struct device_node *np, *master = NULL, *slave = NULL;
+ int rc;

/* We can have up to 2 MPICs cascaded */
for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
@@ -613,7 +623,14 @@ static int __init pmac_pic_probe_mpic(vo
of_node_put(slave);
return 0;
}
- mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2);
+
+ printk(KERN_DEBUG "Setting up MPIC 2 cascade on irq %d\n",
+ slave->intrs[0].line);
+ mpic_cascade_action.dev_id = mpic2;
+ rc = setup_irq(slave->intrs[0].line, &mpic_cascade_action);
+ if (rc)
+ printk(KERN_DEBUG "Failed setting up MPIC 2 cascade on irq %d"
+ " error %d\n", slave->intrs[0].line, rc);

of_node_put(slave);
return 0;
Index: linux-work/kernel/irq/proc.c
===================================================================
--- linux-work.orig/kernel/irq/proc.c 2006-01-14 14:43:37.000000000 +1100
+++ linux-work/kernel/irq/proc.c 2006-05-11 14:55:39.000000000 +1000
@@ -166,6 +166,8 @@ void init_irq_proc(void)

/*
* Create entries for all existing IRQs.
+ *
+ * FIXME: Call register_handler_proc() for existing actions
*/
for (i = 0; i < NR_IRQS; i++)
register_irq_proc(i);




-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/