[PATCH][2.6] Nested Interrupt support

Jake Moilanen moilanen at austin.ibm.com
Fri Jan 23 01:28:10 EST 2004


> 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.
>

Here's the patch using per cpu data for the irq stack.

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.1393  -> 1.1394
#	arch/ppc64/kernel/irq.c	1.54    -> 1.55
#	arch/ppc64/kernel/xics.c	1.38    -> 1.39
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/01/22	moilanen at threadlp13.austin.ibm.com	1.1394
# Nested interrupt support.
# --------------------------------------------
#
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	Thu Jan 22 08:20:25 2004
+++ b/arch/ppc64/kernel/irq.c	Thu Jan 22 08:20:25 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	Thu Jan 22 08:20:25 2004
+++ b/arch/ppc64/kernel/xics.c	Thu Jan 22 08:20:25 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];
+};
+
+DEFINE_PER_CPU(struct cpu_irq_stack, _irq_stack);
+
+#define irq_stack __get_cpu_var(_irq_stack)
+#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++) {
+		per_cpu(_irq_stack, i).depth = 0;
+		for (j = 0; j < IRQ_DEPTH; j++) {
+			per_cpu(_irq_stack, i).priority[j] = 0xff;
+			per_cpu(_irq_stack, i).irq[j] = -1;
+		}
+	}

 	ops->cppr_info(boot_cpuid, 0xff);
 	iosync();


More information about the Linuxppc64-dev mailing list