[PATCH][2.6] Nested Interrupt support

Jake Moilanen moilanen at austin.ibm.com
Tue Jan 20 08:22:49 EST 2004


On Sun, 2004-01-18 at 22:20, Anton Blanchard wrote:

> Looks good. Could we use per cpu data here (do we init per cpu data
> before the xics setup)? Also Im wondering if we should have a quick
> check for overflow of the buffer.

I do have a debug patch that did more validation of the stacks if you
want more.  I attached a patch w/ updates.

> > One concern I have is at the end of ppc_irq_dispatch_handler(), there is
> > a check to see if the desc->handler went away due to an interrupt being
> > disabled.  If the handler does go away, desc->handler->end will not be
> > called and the irq_stack will get out of sync.  I could not find
> > anywhere were this handler would actually be removed (eg function
> > pointer set to zero).  Why is this code still here?
>
> Im not sure, how does it match up with what x86 does these days?

It looks like x86 just does desc->handler->end(irq) w/o checking that
desc->handler is valid or not.   I'll make the change to just do the
end() call.

Thanks,
Jake
-------------- next part --------------
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1389  -> 1.1390 
#	arch/ppc64/kernel/irq.c	1.53    -> 1.54   
#	arch/ppc64/kernel/xics.c	1.37    -> 1.38   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/01/19	moilanen at threadlp13.austin.ibm.com	1.1390
# XICs nested interrupt support.
# --------------------------------------------
#
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	Mon Jan 19 15:16:10 2004
+++ b/arch/ppc64/kernel/irq.c	Mon Jan 19 15:16:10 2004
@@ -822,16 +822,9 @@
 	}
 out:
 	desc->status &= ~IRQ_INPROGRESS;
-	/*
-	 * The ->end() handler has to deal with interrupts which got
-	 * disabled while the handler was running.
-	 */
-	if (desc->handler) {
-		if (desc->handler->end)
-			desc->handler->end(irq);
-		else if (desc->handler->enable)
-			desc->handler->enable(irq);
-	}
+
+	desc->handler->end(irq);
+
 	spin_unlock(&desc->lock);
 }
 
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	Mon Jan 19 15:16:10 2004
+++ b/arch/ppc64/kernel/xics.c	Mon Jan 19 15:16:10 2004
@@ -92,6 +92,21 @@
 static unsigned int default_server = 0xFF;
 static unsigned int default_distrib_server = 0;
 
+/* Number of nested IRQs we can store */
+#define IRQ_DEPTH 2
+
+struct cpu_irq_stack
+{
+	int depth;
+	int priority[IRQ_DEPTH];
+	int irq[IRQ_DEPTH];
+};
+
+struct cpu_irq_stack _irq_stack[NR_CPUS];
+
+#define irq_stack _irq_stack[smp_processor_id()]
+#define irq_stack_depth (irq_stack).depth
+
 /*
  * XICS only has a single IPI, so encode the messages per CPU
  */
@@ -302,20 +317,36 @@
 void xics_end_irq(unsigned int irq)
 {
 	int cpu = smp_processor_id();
+	unsigned int priority;
+
+	if (irq >= 0 && irq != irq_offset_up(xics_irq_8259_cascade)) {
+		irq_stack_depth--;
+		priority = irq_stack.priority[irq_stack_depth];
+	} else {
+		priority = 0xff;
+	}
 
 	iosync();
-	ops->xirr_info_set(cpu, ((0xff<<24) | (irq_offset_down(irq))));
+	ops->xirr_info_set(cpu, (priority<<24) | (irq_offset_down(irq)));
 
 }
 
 void xics_mask_and_ack_irq(u_int irq)
 {
 	int cpu = smp_processor_id();
+	unsigned int priority;
 
 	if (irq < irq_offset_value()) {
+		if (irq >= 0) {
+			irq_stack_depth--;
+			priority = irq_stack.priority[irq_stack_depth];
+		} else {
+			priority = 0xff;
+		}
+
 		i8259_pic.ack(irq);
 		iosync();
-		ops->xirr_info_set(cpu, ((0xff<<24) |
+		ops->xirr_info_set(cpu, ((priority<<24) |
 					 xics_irq_8259_cascade_real));
 		iosync();
 	}
@@ -325,10 +356,12 @@
 {
 	u_int cpu = smp_processor_id();
 	u_int vec;
+	u_int priority;
 	int irq;
 
 	vec = ops->xirr_info_get(cpu);
-	/*  (vec >> 24) == old priority */
+
+	priority = vec >> 24;
 	vec &= 0x00ffffff;
 
 	/* for sanity, this had better be < NR_IRQS - 16 */
@@ -345,6 +378,16 @@
 	} else {
 		irq = irq_offset_up(vec);
 	}
+
+	if (irq >= 0) {
+		if (irq_stack_depth >= IRQ_DEPTH) 
+			panic("Illegal irq stack depth");
+
+		irq_stack.priority[irq_stack_depth] = priority;
+		irq_stack.irq[irq_stack_depth] = irq;
+		irq_stack_depth++;
+	}
+
 	return irq;
 }
 
@@ -413,7 +456,7 @@
 
 void xics_init_IRQ(void)
 {
-	int i;
+	int i, j;
 	unsigned long intr_size = 0;
 	struct device_node *np;
 	uint *ireg, ilen, indx = 0;
@@ -531,6 +574,14 @@
 	xics_8259_pic.disable = i8259_pic.disable;
 	for (i = 0; i < 16; ++i)
 		get_real_irq_desc(i)->handler = &xics_8259_pic;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		_irq_stack[i].depth = 0;
+		for (j = 0; j < IRQ_DEPTH; j++) {
+			_irq_stack[i].priority[j] = 0xff;
+			_irq_stack[i].irq[j] = -1;
+		}
+	}
 
 	ops->cppr_info(boot_cpuid, 0xff);
 	iosync();


More information about the Linuxppc64-dev mailing list