linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/16] xics and ipi cleanups for 2.6.28
@ 2008-10-10 11:56 Milton Miller
  2008-10-10 11:56 ` [PATCH 1/16] powerpc pseries: eoi unmapped xics irqs after disable Milton Miller
                   ` (13 more replies)
  0 siblings, 14 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

The first two patches in this series implememnt a couple of bug
fixes for the xics interrupt controller accessed as found in pseries
hardware.  The next several patches implement some code orginization
and cleanups, followed by some changes to reduce code or flag the
behavior to generic code.

The last 5 patces are independent of the xics changes, although the
first one affects xics.  They are designed to reduce interrupt
overhead for interprocessor interupts.  

While I would have liked to do more testing where I have access to
the hardware (which is only xics), I am sending them out now for
review and consdieration for the merge window.  All have been compile
tested, and I feel they are split into reviewable pieces.

milton

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/16] powerpc pseries: eoi unmapped xics irqs after disable
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 2/16] xics: update default_server during migrate_irqs_away Milton Miller
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras; +Cc: Michael Ellerman

When reciving an irq vector that does not have a linux mapping, the kernel
prints a message and calls RTAS to disable the irq source.   Previously
the kernel did not EOI the interrupt, causing the source to think it is
still being processed by software.  While this does add an additional
layer of protection against interrupt storms had RTAS failed to disable
the source, it also prevents the interrupt from working when a driver
later enables it.  (We could alternatively send an EOI on startup, but
that strategy would likely fail on an emulated xics.)

All interrupts should be disabled when the kernel starts, but this can
be observed if a driver does not shutdown an interrupt in its reboot
hook before starting a new kernel with kexec.

Michael reports this can be reproduced trivially by banging the keyboard
while kexec'ing on a P5 LPAR: even though the hvc_console driver request's
the console irq later in boot, the console is non-functional because
we're receiving no console interrupts.

Reported-By: Michael Ellerman
Signed-off-by: Milton Miller <miltonm@bga.com>

---
This version is for 2.6.28 based on benh's next branch.  For prior
kernels, s/irq_radix_revmap_lookup/irq_radix_revmap/ before applying.

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 16:34:45.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-05 01:49:59.000000000 -0500
@@ -332,32 +332,61 @@ static void xics_eoi_lpar(unsigned int v
 	lpar_xirr_info_set((0xff << 24) | irq);
 }
 
-static inline unsigned int xics_remap_irq(unsigned int vec)
+static inline unsigned int xics_xirr_vector(unsigned int xirr)
 {
-	unsigned int irq;
+	/*
+	 * The top byte is the old cppr, to be restored on EOI.
+	 * The remaining 24 bits are the vector.
+	 */
+	return xirr & 0x00ffffff;
+}
 
-	vec &= 0x00ffffff;
+static void xics_mask_unknown_vec(unsigned int vec)
+{
+	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
+	xics_mask_real_irq(vec);
+}
+
+static unsigned int xics_get_irq_direct(void)
+{
+	unsigned int xirr = direct_xirr_info_get();
+	unsigned int vec = xics_xirr_vector(xirr);
+	unsigned int irq;
 
 	if (vec == XICS_IRQ_SPURIOUS)
 		return NO_IRQ;
+
 	irq = irq_radix_revmap_lookup(xics_host, vec);
 	if (likely(irq != NO_IRQ))
 		return irq;
 
-	printk(KERN_ERR "Interrupt %u (real) is invalid,"
-	       " disabling it.\n", vec);
-	xics_mask_real_irq(vec);
-	return NO_IRQ;
-}
+	/* We don't have a linux mapping, so have rtas mask it. */
+	xics_mask_unknown_vec(vec);
 
-static unsigned int xics_get_irq_direct(void)
-{
-	return xics_remap_irq(direct_xirr_info_get());
+	/* We might learn about it later, so EOI it */
+	direct_xirr_info_set(xirr);
+	return NO_IRQ;
 }
 
 static unsigned int xics_get_irq_lpar(void)
 {
-	return xics_remap_irq(lpar_xirr_info_get());
+	unsigned int xirr = lpar_xirr_info_get();
+	unsigned int vec = xics_xirr_vector(xirr);
+	unsigned int irq;
+
+	if (vec == XICS_IRQ_SPURIOUS)
+		return NO_IRQ;
+
+	irq = irq_radix_revmap_lookup(xics_host, vec);
+	if (likely(irq != NO_IRQ))
+		return irq;
+
+	/* We don't have a linux mapping, so have RTAS mask it. */
+	xics_mask_unknown_vec(vec);
+
+	/* We might learn about it later, so EOI it */
+	lpar_xirr_info_set(xirr);
+	return NO_IRQ;
 }
 
 #ifdef CONFIG_SMP

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 2/16] xics: update default_server during migrate_irqs_away
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
  2008-10-10 11:56 ` [PATCH 1/16] powerpc pseries: eoi unmapped xics irqs after disable Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-13 20:04   ` Nathan Fontenot
  2008-10-10 11:56 ` [PATCH 3/16] xics: consolidate ipi message encode and decode Milton Miller
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

Currently, every time we determine which irq server to use, we check if
default_server, which is the id of the bootcpu, is still online.  But
default_server is a hardware cpu, not the logical cpu id needed to index
cpu_online_map.  

Since the default server can only go offline during a cpu hotplug event,
explicitly check the default server and choose the new one when we move
irqs away from the cpu being offlined.

This has the added benefit of only needing the boot_cpuid to be updated
and not relying on the cpu being marked offline during migrate_irqs_away.

Also, since xics_update_irq_servers only reads device tree information, we
can call it before xics_init_host in xics_init_IRQ and then default_server
will always be valid when we can reach get_irq_server via the host ops.

Signed-off-by: Milton Miller <miltonm@bga.com>
---
I realized the hard vs soft cpu id as I was writing the patch description.
get_irq_server is called from unmask and set affinity.  

The effects of this bug would be the increased pathlength to walk the
device tree in the unmask and set affinity methods, and possible failure
to migrate irqs during cpu hotplug removal (not likely to be seen on
until a sequence of remove and adds is performed).

This check dates to 2.6.25 via de0723dcca6e593a12a259798a54eb0e82628fb8.

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 16:36:07.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 16:36:09.000000000 -0500
@@ -208,9 +208,6 @@ static int get_irq_server(unsigned int v
 	cpumask_t cpumask = irq_desc[virq].affinity;
 	cpumask_t tmp = CPU_MASK_NONE;
 
-	if (! cpu_isset(default_server, cpu_online_map))
-		xics_update_irq_servers();
-
 	if (!distribute_irqs)
 		return default_server;
 
@@ -685,8 +682,8 @@ void __init xics_init_IRQ(void)
 	if (found == 0)
 		return;
 
-	xics_init_host();
 	xics_update_irq_servers();
+	xics_init_host();
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		ppc_md.get_irq = xics_get_irq_lpar;
@@ -779,6 +776,10 @@ void xics_migrate_irqs_away(void)
 	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
 	unsigned int irq, virq;
 
+	/* If we used to be the default server, move to the new "boot_cpuid" */
+	if (hw_cpu == default_server)
+		xics_update_irq_servers();
+
 	/* Reject any interrupt that was queued to us... */
 	xics_set_cpu_priority(0);
 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 3/16] xics: consolidate ipi message encode and decode
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
  2008-10-10 11:56 ` [PATCH 1/16] powerpc pseries: eoi unmapped xics irqs after disable Milton Miller
  2008-10-10 11:56 ` [PATCH 2/16] xics: update default_server during migrate_irqs_away Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 4/16] xics: rearrange file to group code by function Milton Miller
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

xics supports only one ipi per cpu, and expects software to use some
queue to know why the interrupt was sent.  In Linux, we use a an array
of bitmaps indexed by cpu to identify the message.  Currently the bits
are set in smp.c and decoded in xics.c, with the data structure in a
header file.   Consolidate the code in xics.c similar to mpic and other
interrupt controllers.

Also, while making the the array static, the message word doesn't need
to be volatile as set_bit and test_clear_bit take care of it for us, and
put it under ifdef smp.

Signed-off-by: Milton Miller <miltonm@bga.com>
---
iseries and powermac psurge have similar code due to only one ipi,
but they don't spread out the lines by cachelines for scalability
like pseries.  Since that is one other platform per arch head, I
left the code replicated.

I kept smp_xics_cpu_setup in smp.c as the vpa init is unrelated.

Index: next.git/arch/powerpc/platforms/pseries/smp.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/smp.c	2008-10-04 16:34:45.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/smp.c	2008-10-04 16:37:39.000000000 -0500
@@ -37,7 +37,6 @@
 #include <asm/paca.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
-#include "xics.h"
 #include <asm/cputable.h>
 #include <asm/firmware.h>
 #include <asm/system.h>
@@ -49,6 +48,7 @@
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
+#include "xics.h"
 
 
 /*
@@ -105,36 +105,6 @@ static inline int __devinit smp_startup_
 }
 
 #ifdef CONFIG_XICS
-static inline void smp_xics_do_message(int cpu, int msg)
-{
-	set_bit(msg, &xics_ipi_message[cpu].value);
-	mb();
-	xics_cause_IPI(cpu);
-}
-
-static void smp_xics_message_pass(int target, int msg)
-{
-	unsigned int i;
-
-	if (target < NR_CPUS) {
-		smp_xics_do_message(target, msg);
-	} else {
-		for_each_online_cpu(i) {
-			if (target == MSG_ALL_BUT_SELF
-			    && i == smp_processor_id())
-				continue;
-			smp_xics_do_message(i, msg);
-		}
-	}
-}
-
-static int __init smp_xics_probe(void)
-{
-	xics_request_IPIs();
-
-	return cpus_weight(cpu_possible_map);
-}
-
 static void __devinit smp_xics_setup_cpu(int cpu)
 {
 	if (cpu != boot_cpuid)
Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 16:36:09.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:09:57.000000000 -0500
@@ -71,11 +71,6 @@ static unsigned int interrupt_server_siz
 
 static struct irq_host *xics_host;
 
-/*
- * XICS only has a single IPI, so encode the messages per CPU
- */
-struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
-
 /* RTAS service tokens */
 static int ibm_get_xive;
 static int ibm_set_xive;
@@ -201,6 +196,15 @@ static void xics_update_irq_servers(void
 }
 
 #ifdef CONFIG_SMP
+/*
+ * XICS only has a single IPI, so encode the messages per CPU
+ */
+struct xics_ipi_struct {
+        unsigned long value;
+	} ____cacheline_aligned;
+
+static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+
 static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
 	int server;
@@ -387,7 +391,6 @@ static unsigned int xics_get_irq_lpar(vo
 }
 
 #ifdef CONFIG_SMP
-
 static irqreturn_t xics_ipi_dispatch(int cpu)
 {
 	WARN_ON(cpu_is_offline(cpu));
@@ -419,6 +422,33 @@ static irqreturn_t xics_ipi_dispatch(int
 	return IRQ_HANDLED;
 }
 
+static inline void smp_xics_do_message(int cpu, int msg)
+{
+	set_bit(msg, &xics_ipi_message[cpu].value);
+	mb();
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		lpar_qirr_info(cpu, IPI_PRIORITY);
+	else
+		direct_qirr_info(cpu, IPI_PRIORITY);
+}
+
+void smp_xics_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		smp_xics_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_xics_do_message(i, msg);
+		}
+	}
+}
+
+
 static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
 {
 	int cpu = smp_processor_id();
@@ -436,15 +466,6 @@ static irqreturn_t xics_ipi_action_lpar(
 
 	return xics_ipi_dispatch(cpu);
 }
-
-void xics_cause_IPI(int cpu)
-{
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_qirr_info(cpu, IPI_PRIORITY);
-	else
-		direct_qirr_info(cpu, IPI_PRIORITY);
-}
-
 #endif /* CONFIG_SMP */
 
 static void xics_set_cpu_priority(unsigned char cppr)
@@ -697,7 +718,7 @@ void __init xics_init_IRQ(void)
 
 
 #ifdef CONFIG_SMP
-void xics_request_IPIs(void)
+static void xics_request_ipi(void)
 {
 	unsigned int ipi;
 	int rc;
@@ -718,6 +739,14 @@ void xics_request_IPIs(void)
 				"IPI", NULL);
 	BUG_ON(rc);
 }
+
+int __init smp_xics_probe(void)
+{
+	xics_request_ipi();
+
+	return cpus_weight(cpu_possible_map);
+}
+
 #endif /* CONFIG_SMP */
 
 void xics_teardown_cpu(void)
Index: next.git/arch/powerpc/platforms/pseries/xics.h
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.h	2008-10-04 16:34:45.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.h	2008-10-04 16:51:10.000000000 -0500
@@ -12,20 +12,12 @@
 #ifndef _POWERPC_KERNEL_XICS_H
 #define _POWERPC_KERNEL_XICS_H
 
-#include <linux/cache.h>
-
 extern void xics_init_IRQ(void);
 extern void xics_setup_cpu(void);
 extern void xics_teardown_cpu(void);
 extern void xics_kexec_teardown_cpu(int secondary);
-extern void xics_cause_IPI(int cpu);
-extern  void xics_request_IPIs(void);
 extern void xics_migrate_irqs_away(void);
-
-struct xics_ipi_struct {
-	volatile unsigned long value;
-} ____cacheline_aligned;
-
-extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+extern int smp_xics_probe(void);
+extern void smp_xics_message_pass(int target, int msg);
 
 #endif /* _POWERPC_KERNEL_XICS_H */

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 4/16] xics: rearrange file to group code by function
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (2 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 3/16] xics: consolidate ipi message encode and decode Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 5/16] xics: change arg type to remove casts Milton Miller
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

Now that xics_update_irq_servers is called only from init and hotplug
code, it becomes possible to clean up the ordering of functions in the
file, grouping them but the interfaces they implement.

Signed-off-by: Milton Miller <miltonm@bga.com>
---
This patch is pure function reordering and comments.

This patch applies to -next.  For prior kernels, there are 6 more lines
in xics_startup() that affect patch application.

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:09:57.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:39:02.000000000 -0500
@@ -9,7 +9,6 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-
 #include <linux/types.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
@@ -35,6 +34,8 @@
 #include "xics.h"
 #include "plpar_wrappers.h"
 
+static struct irq_host *xics_host;
+
 #define XICS_IPI		2
 #define XICS_IRQ_SPURIOUS	0
 
@@ -47,6 +48,20 @@
  */
 #define IPI_PRIORITY		4
 
+static unsigned int default_server = 0xFF;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
+
+/* RTAS service tokens */
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
+
+
+/* Direct hardware low level accessors */
+
+/* The part of the interrupt presentation layer that we care about */
 struct xics_ipl {
 	union {
 		u32 word;
@@ -65,22 +80,6 @@ struct xics_ipl {
 
 static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
 
-static unsigned int default_server = 0xFF;
-static unsigned int default_distrib_server = 0;
-static unsigned int interrupt_server_size = 8;
-
-static struct irq_host *xics_host;
-
-/* RTAS service tokens */
-static int ibm_get_xive;
-static int ibm_set_xive;
-static int ibm_int_on;
-static int ibm_int_off;
-
-
-/* Direct HW low level accessors */
-
-
 static inline unsigned int direct_xirr_info_get(void)
 {
 	int cpu = smp_processor_id();
@@ -110,7 +109,6 @@ static inline void direct_qirr_info(int 
 
 /* LPAR low level accessors */
 
-
 static inline unsigned int lpar_xirr_info_get(void)
 {
 	unsigned long lpar_rc;
@@ -152,59 +150,9 @@ static inline void lpar_qirr_info(int n_
 }
 
 
-/* High level handlers and init code */
-
-static void xics_update_irq_servers(void)
-{
-	int i, j;
-	struct device_node *np;
-	u32 ilen;
-	const u32 *ireg, *isize;
-	u32 hcpuid;
-
-	/* Find the server numbers for the boot cpu. */
-	np = of_get_cpu_node(boot_cpuid, NULL);
-	BUG_ON(!np);
-
-	ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
-	if (!ireg) {
-		of_node_put(np);
-		return;
-	}
-
-	i = ilen / sizeof(int);
-	hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
-	/* Global interrupt distribution server is specified in the last
-	 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
-	 * entry fom this property for current boot cpu id and use it as
-	 * default distribution server
-	 */
-	for (j = 0; j < i; j += 2) {
-		if (ireg[j] == hcpuid) {
-			default_server = hcpuid;
-			default_distrib_server = ireg[j+1];
-
-			isize = of_get_property(np,
-					"ibm,interrupt-server#-size", NULL);
-			if (isize)
-				interrupt_server_size = *isize;
-		}
-	}
-
-	of_node_put(np);
-}
+/* Interface to generic irq subsystem */
 
 #ifdef CONFIG_SMP
-/*
- * XICS only has a single IPI, so encode the messages per CPU
- */
-struct xics_ipi_struct {
-        unsigned long value;
-	} ____cacheline_aligned;
-
-static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
-
 static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
 	int server;
@@ -239,7 +187,6 @@ static int get_irq_server(unsigned int v
 }
 #endif
 
-
 static void xics_unmask_irq(unsigned int virq)
 {
 	unsigned int irq;
@@ -273,6 +220,13 @@ static void xics_unmask_irq(unsigned int
 	}
 }
 
+static unsigned int xics_startup(unsigned int virq)
+{
+	/* unmask it */
+	xics_unmask_irq(virq);
+	return 0;
+}
+
 static void xics_mask_real_irq(unsigned int irq)
 {
 	int call_status;
@@ -309,28 +263,10 @@ static void xics_mask_irq(unsigned int v
 	xics_mask_real_irq(irq);
 }
 
-static unsigned int xics_startup(unsigned int virq)
-{
-	/* unmask it */
-	xics_unmask_irq(virq);
-	return 0;
-}
-
-static void xics_eoi_direct(unsigned int virq)
-{
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-	iosync();
-	direct_xirr_info_set((0xff << 24) | irq);
-}
-
-
-static void xics_eoi_lpar(unsigned int virq)
+static void xics_mask_unknown_vec(unsigned int vec)
 {
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-	iosync();
-	lpar_xirr_info_set((0xff << 24) | irq);
+	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
+	xics_mask_real_irq(vec);
 }
 
 static inline unsigned int xics_xirr_vector(unsigned int xirr)
@@ -342,12 +278,6 @@ static inline unsigned int xics_xirr_vec
 	return xirr & 0x00ffffff;
 }
 
-static void xics_mask_unknown_vec(unsigned int vec)
-{
-	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
-	xics_mask_real_irq(vec);
-}
-
 static unsigned int xics_get_irq_direct(void)
 {
 	unsigned int xirr = direct_xirr_info_get();
@@ -390,91 +320,20 @@ static unsigned int xics_get_irq_lpar(vo
 	return NO_IRQ;
 }
 
-#ifdef CONFIG_SMP
-static irqreturn_t xics_ipi_dispatch(int cpu)
-{
-	WARN_ON(cpu_is_offline(cpu));
-
-	while (xics_ipi_message[cpu].value) {
-		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
-				       &xics_ipi_message[cpu].value)) {
-			mb();
-			smp_message_recv(PPC_MSG_CALL_FUNCTION);
-		}
-		if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
-				       &xics_ipi_message[cpu].value)) {
-			mb();
-			smp_message_recv(PPC_MSG_RESCHEDULE);
-		}
-		if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
-				       &xics_ipi_message[cpu].value)) {
-			mb();
-			smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
-		}
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
-		if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
-				       &xics_ipi_message[cpu].value)) {
-			mb();
-			smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
-		}
-#endif
-	}
-	return IRQ_HANDLED;
-}
-
-static inline void smp_xics_do_message(int cpu, int msg)
-{
-	set_bit(msg, &xics_ipi_message[cpu].value);
-	mb();
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_qirr_info(cpu, IPI_PRIORITY);
-	else
-		direct_qirr_info(cpu, IPI_PRIORITY);
-}
-
-void smp_xics_message_pass(int target, int msg)
-{
-	unsigned int i;
-
-	if (target < NR_CPUS) {
-		smp_xics_do_message(target, msg);
-	} else {
-		for_each_online_cpu(i) {
-			if (target == MSG_ALL_BUT_SELF
-			    && i == smp_processor_id())
-				continue;
-			smp_xics_do_message(i, msg);
-		}
-	}
-}
-
-
-static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
+static void xics_eoi_direct(unsigned int virq)
 {
-	int cpu = smp_processor_id();
-
-	direct_qirr_info(cpu, 0xff);
+	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
-	return xics_ipi_dispatch(cpu);
+	iosync();
+	direct_xirr_info_set((0xff << 24) | irq);
 }
 
-static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
+static void xics_eoi_lpar(unsigned int virq)
 {
-	int cpu = smp_processor_id();
-
-	lpar_qirr_info(cpu, 0xff);
-
-	return xics_ipi_dispatch(cpu);
-}
-#endif /* CONFIG_SMP */
+	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
-static void xics_set_cpu_priority(unsigned char cppr)
-{
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_cppr_info(cppr);
-	else
-		direct_cppr_info(cppr);
 	iosync();
+	lpar_xirr_info_set((0xff << 24) | irq);
 }
 
 static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
@@ -519,22 +378,6 @@ static void xics_set_affinity(unsigned i
 	}
 }
 
-void xics_setup_cpu(void)
-{
-	xics_set_cpu_priority(0xff);
-
-	/*
-	 * Put the calling processor into the GIQ.  This is really only
-	 * necessary from a secondary thread as the OF start-cpu interface
-	 * performs this function for us on primary threads.
-	 *
-	 * XXX: undo of teardown on kexec needs this too, as may hotplug
-	 */
-	rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-		(1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
-}
-
-
 static struct irq_chip xics_pic_direct = {
 	.typename = " XICS     ",
 	.startup = xics_startup,
@@ -544,7 +387,6 @@ static struct irq_chip xics_pic_direct =
 	.set_affinity = xics_set_affinity
 };
 
-
 static struct irq_chip xics_pic_lpar = {
 	.typename = " XICS     ",
 	.startup = xics_startup,
@@ -554,6 +396,9 @@ static struct irq_chip xics_pic_lpar = {
 	.set_affinity = xics_set_affinity
 };
 
+
+/* Interface to arch irq controller subsystem layer */
+
 /* Points to the irq_chip we're actually using */
 static struct irq_chip *xics_irq_chip;
 
@@ -613,6 +458,169 @@ static void __init xics_init_host(void)
 	irq_set_default_host(xics_host);
 }
 
+
+/* Inter-processor interrupt support */
+
+#ifdef CONFIG_SMP
+/*
+ * XICS only has a single IPI, so encode the messages per CPU
+ */
+struct xics_ipi_struct {
+        unsigned long value;
+	} ____cacheline_aligned;
+
+static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+
+static inline void smp_xics_do_message(int cpu, int msg)
+{
+	set_bit(msg, &xics_ipi_message[cpu].value);
+	mb();
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		lpar_qirr_info(cpu, IPI_PRIORITY);
+	else
+		direct_qirr_info(cpu, IPI_PRIORITY);
+}
+
+void smp_xics_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		smp_xics_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_xics_do_message(i, msg);
+		}
+	}
+}
+
+static irqreturn_t xics_ipi_dispatch(int cpu)
+{
+	WARN_ON(cpu_is_offline(cpu));
+
+	while (xics_ipi_message[cpu].value) {
+		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
+				       &xics_ipi_message[cpu].value)) {
+			mb();
+			smp_message_recv(PPC_MSG_CALL_FUNCTION);
+		}
+		if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
+				       &xics_ipi_message[cpu].value)) {
+			mb();
+			smp_message_recv(PPC_MSG_RESCHEDULE);
+		}
+		if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
+				       &xics_ipi_message[cpu].value)) {
+			mb();
+			smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
+		}
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+		if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
+				       &xics_ipi_message[cpu].value)) {
+			mb();
+			smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+		}
+#endif
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
+{
+	int cpu = smp_processor_id();
+
+	direct_qirr_info(cpu, 0xff);
+
+	return xics_ipi_dispatch(cpu);
+}
+
+static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
+{
+	int cpu = smp_processor_id();
+
+	lpar_qirr_info(cpu, 0xff);
+
+	return xics_ipi_dispatch(cpu);
+}
+
+static void xics_request_ipi(void)
+{
+	unsigned int ipi;
+	int rc;
+
+	ipi = irq_create_mapping(xics_host, XICS_IPI);
+	BUG_ON(ipi == NO_IRQ);
+
+	/*
+	 * IPIs are marked IRQF_DISABLED as they must run with irqs
+	 * disabled
+	 */
+	set_irq_handler(ipi, handle_percpu_irq);
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
+				"IPI", NULL);
+	else
+		rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
+				"IPI", NULL);
+	BUG_ON(rc);
+}
+
+int __init smp_xics_probe(void)
+{
+	xics_request_ipi();
+
+	return cpus_weight(cpu_possible_map);
+}
+
+#endif /* CONFIG_SMP */
+
+
+/* Initialization */
+
+static void xics_update_irq_servers(void)
+{
+	int i, j;
+	struct device_node *np;
+	u32 ilen;
+	const u32 *ireg, *isize;
+	u32 hcpuid;
+
+	/* Find the server numbers for the boot cpu. */
+	np = of_get_cpu_node(boot_cpuid, NULL);
+	BUG_ON(!np);
+
+	ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+	if (!ireg) {
+		of_node_put(np);
+		return;
+	}
+
+	i = ilen / sizeof(int);
+	hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+	/* Global interrupt distribution server is specified in the last
+	 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+	 * entry fom this property for current boot cpu id and use it as
+	 * default distribution server
+	 */
+	for (j = 0; j < i; j += 2) {
+		if (ireg[j] == hcpuid) {
+			default_server = hcpuid;
+			default_distrib_server = ireg[j+1];
+
+			isize = of_get_property(np,
+					"ibm,interrupt-server#-size", NULL);
+			if (isize)
+				interrupt_server_size = *isize;
+		}
+	}
+
+	of_node_put(np);
+}
+
 static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
 				     unsigned long size)
 {
@@ -716,39 +724,33 @@ void __init xics_init_IRQ(void)
 	ppc64_boot_msg(0x21, "XICS Done");
 }
 
+/* Cpu startup, shutdown, and hotplug */
 
-#ifdef CONFIG_SMP
-static void xics_request_ipi(void)
+static void xics_set_cpu_priority(unsigned char cppr)
 {
-	unsigned int ipi;
-	int rc;
-
-	ipi = irq_create_mapping(xics_host, XICS_IPI);
-	BUG_ON(ipi == NO_IRQ);
-
-	/*
-	 * IPIs are marked IRQF_DISABLED as they must run with irqs
-	 * disabled
-	 */
-	set_irq_handler(ipi, handle_percpu_irq);
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
-				"IPI", NULL);
+		lpar_cppr_info(cppr);
 	else
-		rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
-				"IPI", NULL);
-	BUG_ON(rc);
+		direct_cppr_info(cppr);
+	iosync();
 }
 
-int __init smp_xics_probe(void)
+
+void xics_setup_cpu(void)
 {
-	xics_request_ipi();
+	xics_set_cpu_priority(0xff);
 
-	return cpus_weight(cpu_possible_map);
+	/*
+	 * Put the calling processor into the GIQ.  This is really only
+	 * necessary from a secondary thread as the OF start-cpu interface
+	 * performs this function for us on primary threads.
+	 *
+	 * XXX: undo of teardown on kexec needs this too, as may hotplug
+	 */
+	rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
+		(1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
 }
 
-#endif /* CONFIG_SMP */
-
 void xics_teardown_cpu(void)
 {
 	int cpu = smp_processor_id();

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 5/16] xics: change arg type to remove casts
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (3 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 4/16] xics: rearrange file to group code by function Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 6/16] xics: trim includes Milton Miller
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

The xirr is 32 bits in hardware, but the hypervisor requries the upper
bits of the register to be clear on the hcall.  By changing the type
from signed to unsigned int we can drop masking it back to 32 bits.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 06:07:00.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 06:13:40.000000000 -0500
@@ -87,7 +87,7 @@ static inline unsigned int direct_xirr_i
 	return in_be32(&xics_per_cpu[cpu]->xirr.word);
 }
 
-static inline void direct_xirr_info_set(int value)
+static inline void direct_xirr_info_set(unsigned int value)
 {
 	int cpu = smp_processor_id();
 
@@ -120,15 +120,14 @@ static inline unsigned int lpar_xirr_inf
 	return (unsigned int)return_value;
 }
 
-static inline void lpar_xirr_info_set(int value)
+static inline void lpar_xirr_info_set(unsigned int value)
 {
 	unsigned long lpar_rc;
-	unsigned long val64 = value & 0xffffffff;
 
-	lpar_rc = plpar_eoi(val64);
+	lpar_rc = plpar_eoi(value);
 	if (lpar_rc != H_SUCCESS)
-		panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
-		      val64);
+		panic("bad return code EOI - rc = %ld, value=%x\n", lpar_rc,
+		      value);
 }
 
 static inline void lpar_cppr_info(u8 value)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 6/16] xics: trim includes
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (4 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 5/16] xics: change arg type to remove casts Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 7/16] xics: initialization cleanups Milton Miller
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

Trim unneeded includes from xics.c.  We don't use signals or gfp
flags, we use only OF functions and don't need prom, and the 8259
is now handled by our caller.

Signed-off-by: Milton Miller <miltonm@bga.com>
---
asm/smp.h gives us cpu mask accessors for !CONFIG_SMP, used in the next patch

Index: work.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- work.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-08-07 03:41:08.000000000 -0500
+++ work.git/arch/powerpc/platforms/pseries/xics.c	2008-08-07 03:43:12.000000000 -0500
@@ -15,21 +15,18 @@
 #include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/signal.h>
 #include <linux/init.h>
-#include <linux/gfp.h>
 #include <linux/radix-tree.h>
 #include <linux/cpu.h>
+#include <linux/of.h>
 
 #include <asm/firmware.h>
-#include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/smp.h>
 #include <asm/rtas.h>
 #include <asm/hvcall.h>
 #include <asm/machdep.h>
-#include <asm/i8259.h>
 
 #include "xics.h"
 #include "plpar_wrappers.h"

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 7/16] xics: initialization cleanups
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (5 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 6/16] xics: trim includes Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-13  0:55   ` Benjamin Herrenschmidt
  2008-10-10 11:56 ` [PATCH 8/16] xics: factor out giq set and unset Milton Miller
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

We only need to check the ibm,interrupt-server#-size property once, not
once per global server and thread.

We can use !CONFIG_SMP cpu masks and hard_smp_processor_id() to avoid an ifdef.  
Put the node when breaking out of the loop on lpar systems.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:39:58.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:40:00.000000000 -0500
@@ -606,21 +606,20 @@ static void xics_update_irq_servers(void
 		if (ireg[j] == hcpuid) {
 			default_server = hcpuid;
 			default_distrib_server = ireg[j+1];
-
-			isize = of_get_property(np,
-					"ibm,interrupt-server#-size", NULL);
-			if (isize)
-				interrupt_server_size = *isize;
 		}
 	}
 
+	/* get the bit size of server numbers */
+	isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
+	if (isize)
+		interrupt_server_size = *isize;
+
 	of_node_put(np);
 }
 
 static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
 				     unsigned long size)
 {
-#ifdef CONFIG_SMP
 	int i;
 
 	/* This may look gross but it's good enough for now, we don't quite
@@ -634,11 +633,6 @@ static void __init xics_map_one_cpu(int 
 			return;
 		}
 	}
-#else
-	if (hw_id != 0)
-		return;
-	xics_per_cpu[0] = ioremap(addr, size);
-#endif /* CONFIG_SMP */
 }
 
 static void __init xics_init_one_node(struct device_node *np,
@@ -700,8 +694,10 @@ void __init xics_init_IRQ(void)
 
 	for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
 		found = 1;
-		if (firmware_has_feature(FW_FEATURE_LPAR))
+		if (firmware_has_feature(FW_FEATURE_LPAR)) {
+			of_node_put(np);
 			break;
+			}
 		xics_init_one_node(np, &indx);
 	}
 	if (found == 0)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 8/16] xics: factor out giq set and unset
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (6 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 7/16] xics: initialization cleanups Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 9/16] powerpc: eoi xics ipi by hand in kexec Milton Miller
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

There is a bit of math to calculate the arguments to rtas to join
or leave the global interrupt queue, and a warning on failure
afterwards.  Make a helper for the 3 callers.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:40:00.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:42:53.000000000 -0500
@@ -727,20 +727,19 @@ static void xics_set_cpu_priority(unsign
 	iosync();
 }
 
+/* Have the calling processor join or leave the specified global queue */
+static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
+{
+	int status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
+		(1UL << interrupt_server_size) - 1 - gserver, join);
+	WARN_ON(status < 0);
+}
 
 void xics_setup_cpu(void)
 {
 	xics_set_cpu_priority(0xff);
 
-	/*
-	 * Put the calling processor into the GIQ.  This is really only
-	 * necessary from a secondary thread as the OF start-cpu interface
-	 * performs this function for us on primary threads.
-	 *
-	 * XXX: undo of teardown on kexec needs this too, as may hotplug
-	 */
-	rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-		(1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
+	xics_set_cpu_giq(default_distrib_server, 1);
 }
 
 void xics_teardown_cpu(void)
@@ -749,9 +748,7 @@ void xics_teardown_cpu(void)
 
 	xics_set_cpu_priority(0);
 
-	/*
-	 * Clear IPI
-	 */
+	/* Clear any pending IPI request */
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		lpar_qirr_info(cpu, 0xff);
 	else
@@ -785,9 +782,7 @@ void xics_kexec_teardown_cpu(int seconda
 	 * so leave the master cpu in the group.
 	 */
 	if (secondary)
-		rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-				   (1UL << interrupt_server_size) - 1 -
-				   default_distrib_server, 0);
+		xics_set_cpu_giq(default_distrib_server, 0);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -795,7 +790,6 @@ void xics_kexec_teardown_cpu(int seconda
 /* Interrupts are disabled. */
 void xics_migrate_irqs_away(void)
 {
-	int status;
 	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
 	unsigned int irq, virq;
 
@@ -806,10 +800,8 @@ void xics_migrate_irqs_away(void)
 	/* Reject any interrupt that was queued to us... */
 	xics_set_cpu_priority(0);
 
-	/* remove ourselves from the global interrupt queue */
-	status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-		(1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
-	WARN_ON(status < 0);
+	/* Remove ourselves from the global interrupt queue */
+	xics_set_cpu_giq(default_distrib_server, 0);
 
 	/* Allow IPIs again... */
 	xics_set_cpu_priority(DEFAULT_PRIORITY);
@@ -817,6 +809,7 @@ void xics_migrate_irqs_away(void)
 	for_each_irq(virq) {
 		struct irq_desc *desc;
 		int xics_status[2];
+		int status;
 		unsigned long flags;
 
 		/* We cant set affinity on ISA interrupts */

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 9/16] powerpc: eoi xics ipi by hand in kexec
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (7 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 8/16] xics: factor out giq set and unset Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 11/16] powerpc: mark xics ipi percpu Milton Miller
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

EOI normally has the side effect of returning the cpu to the base
priority to recieve the next interrupt.  This is actually controlled
by the top byte of the xirr register.   When we are exiting the
kernel in kexec we must eoi the ipi for the next kernel because we
never return from the handler, but we want to leave interrupt
delivery blocked until the next kernel takes action.

Since the hardware ipi vector is fixed, its easiest to just do the
eoi explicitly.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 17:43:17.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 21:56:17.000000000 -0500
@@ -757,25 +757,21 @@ void xics_teardown_cpu(void)
 
 void xics_kexec_teardown_cpu(int secondary)
 {
-	unsigned int ipi;
-	struct irq_desc *desc;
-
 	xics_teardown_cpu();
 
 	/*
-	 * we need to EOI the IPI
+	 * we take the ipi irq but and never return so we
+	 * need to EOI the IPI, but want to leave our priority 0
 	 *
-	 * probably need to check all the other interrupts too
+	 * should we check all the other interrupts too?
 	 * should we be flagging idle loop instead?
 	 * or creating some task to be scheduled?
 	 */
 
-	ipi = irq_find_mapping(xics_host, XICS_IPI);
-	if (ipi == XICS_IRQ_SPURIOUS)
-		return;
-	desc = get_irq_desc(ipi);
-	if (desc->chip && desc->chip->eoi)
-		desc->chip->eoi(ipi);
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		lpar_xirr_info_set((0x00 << 24) | XICS_IPI);
+	else
+		direct_xirr_info_set((0x00 << 24) | XICS_IPI);
 
 	/*
 	 * Some machines need to have at least one cpu in the GIQ,

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 10/16] xics: make printk formats fit on one line
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (9 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 11/16] powerpc: mark xics ipi percpu Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 12/16] powerpc: reduce and comment xics ipi memory barrier Milton Miller
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

Several printks were broken at word boundaries for line length.   Some
even referred to old function names.   Using __func__ and changing the
text slightly for the format allows these printk formats to fit on one
line.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 21:56:17.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 21:56:30.000000000 -0500
@@ -201,17 +201,17 @@ static void xics_unmask_irq(unsigned int
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
 				DEFAULT_PRIORITY);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
-		       "returned %d\n", irq, call_status);
-		printk("set_xive %x, server %x\n", ibm_set_xive, server);
+		printk(KERN_ERR
+			"%s: ibm_set_xive irq %u server %x returned %d\n",
+			__func__, irq, server, call_status);
 		return;
 	}
 
 	/* Now unmask the interrupt (often a no-op) */
 	call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
-		       "returned %d\n", irq, call_status);
+		printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
+			__func__, irq, call_status);
 		return;
 	}
 }
@@ -232,8 +232,8 @@ static void xics_mask_real_irq(unsigned 
 
 	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
-		       "ibm_int_off returned %d\n", irq, call_status);
+		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
+			__func__, irq, call_status);
 		return;
 	}
 
@@ -241,8 +241,8 @@ static void xics_mask_real_irq(unsigned 
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
 				default_server, 0xff);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
-		       " returned %d\n", irq, call_status);
+		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
+			__func__, irq, call_status);
 		return;
 	}
 }
@@ -346,8 +346,8 @@ static void xics_set_affinity(unsigned i
 	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
 	if (status) {
-		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
-		       "returns %d\n", irq, status);
+		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+			__func__, irq, status);
 		return;
 	}
 
@@ -359,8 +359,9 @@ static void xics_set_affinity(unsigned i
 	if (irq_server == -1) {
 		char cpulist[128];
 		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
-		printk(KERN_WARNING "xics_set_affinity: No online cpus in "
-				"the mask %s for irq %d\n", cpulist, virq);
+		printk(KERN_WARNING
+			"%s: No online cpus in the mask %s for irq %d\n",
+			__func__, cpulist, virq);
 		return;
 	}
 
@@ -368,8 +369,8 @@ static void xics_set_affinity(unsigned i
 				irq, irq_server, xics_status[1]);
 
 	if (status) {
-		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
-		       "returns %d\n", irq, status);
+		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
+			__func__, irq, status);
 		return;
 	}
 }
@@ -829,9 +830,8 @@ void xics_migrate_irqs_away(void)
 
 		status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 		if (status) {
-			printk(KERN_ERR "migrate_irqs_away: irq=%u "
-					"ibm,get-xive returns %d\n",
-					virq, status);
+			printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+					__func__, irq, status);
 			goto unlock;
 		}
 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 11/16] powerpc: mark xics ipi percpu
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (8 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 9/16] powerpc: eoi xics ipi by hand in kexec Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 10/16] xics: make printk formats fit on one line Milton Miller
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

Its physically per-cpu, and we want the irq layer to treat it that way.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 23:54:18.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 23:55:43.000000000 -0500
@@ -557,11 +557,11 @@ static void xics_request_ipi(void)
 	 */
 	set_irq_handler(ipi, handle_percpu_irq);
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
-				"IPI", NULL);
+		rc = request_irq(ipi, xics_ipi_action_lpar,
+				IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
 	else
-		rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
-				"IPI", NULL);
+		rc = request_irq(ipi, xics_ipi_action_direct,
+				IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
 	BUG_ON(rc);
 }
 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 12/16] powerpc: reduce and comment xics ipi memory barrier
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (10 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 10/16] xics: make printk formats fit on one line Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56 ` [PATCH 13/16] powerpc smp: no need to set_need_resched in resched ipi Milton Miller
  2008-10-13  5:28 ` [PATCH 00/16] xics and ipi cleanups for 2.6.28 Benjamin Herrenschmidt
  13 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

A single full sync (mb()) is requrired to order the mmio to the qirr reg
with the set or clear of the message word.  However, test_and_clear_bit
has the effect of smp_mb() and we are not doing any other io from here,
so we don't need a mb per bit processed.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 23:56:15.000000000 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-05 00:01:26.000000000 -0500
@@ -498,26 +498,23 @@ static irqreturn_t xics_ipi_dispatch(int
 {
 	WARN_ON(cpu_is_offline(cpu));
 
+	mb();	/* order mmio clearing qirr */
 	while (xics_ipi_message[cpu].value) {
 		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
 				       &xics_ipi_message[cpu].value)) {
-			mb();
 			smp_message_recv(PPC_MSG_CALL_FUNCTION);
 		}
 		if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
 				       &xics_ipi_message[cpu].value)) {
-			mb();
 			smp_message_recv(PPC_MSG_RESCHEDULE);
 		}
 		if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
 				       &xics_ipi_message[cpu].value)) {
-			mb();
 			smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
 		}
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 		if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
 				       &xics_ipi_message[cpu].value)) {
-			mb();
 			smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
 		}
 #endif

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 13/16] powerpc smp: no need to set_need_resched in resched ipi
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (11 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 12/16] powerpc: reduce and comment xics ipi memory barrier Milton Miller
@ 2008-10-10 11:56 ` Milton Miller
  2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
  2008-10-13  5:28 ` [PATCH 00/16] xics and ipi cleanups for 2.6.28 Benjamin Herrenschmidt
  13 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

The code was asking "Do we have to do this?", and according to x86 and s390
the answer is no, the scheduler will do it before calling the arch hook.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/kernel/smp.c
===================================================================
--- next.git.orig/arch/powerpc/kernel/smp.c	2008-10-04 22:09:36.000000000 -0500
+++ next.git/arch/powerpc/kernel/smp.c	2008-10-04 22:12:32.000000000 -0500
@@ -101,8 +101,7 @@ void smp_message_recv(int msg)
 		generic_smp_call_function_interrupt();
 		break;
 	case PPC_MSG_RESCHEDULE:
-		/* XXX Do we have to do this? */
-		set_need_resched();
+		/* we notice need_resched on exit */
 		break;
 	case PPC_MSG_CALL_FUNC_SINGLE:
 		generic_smp_call_function_single_interrupt();

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 14/16] powerpc: expand vs demux ipi actions per message
  2008-10-10 11:56 ` [PATCH 13/16] powerpc smp: no need to set_need_resched in resched ipi Milton Miller
@ 2008-10-10 11:56   ` Milton Miller
  2008-10-10 11:56     ` [PATCH 14/16] powerpc mpic: use smp_request_message_ipi Milton Miller
                       ` (4 more replies)
  0 siblings, 5 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras; +Cc: Arnd Bergmann

With the new generic smp call function helpers, I noticed the code in
smp_message_recv was a single function call in many cases.  While
getting the message number from the ipi data is easy, we can reduce
the path length by a function call and a mult-way data dependent
switch by registering seperate ipi actions for these simple calls.

Originally I left the ipi action array exposed, but then I realized the
registration code should be common so that decisions like needing the
driver data are common, along with flagging the interrupt per-cpu.

The three users each had their own name array and contents, so I
made a fourth style for all users.  

Signed-off-by: Milton Miller <miltonm@bga.com>
---
Perhaps we should make the common code look like an ipi action handler
and remove this last call?  Currently we still have to allocate a stack
frame to load the return value.

Index: next.git/arch/powerpc/include/asm/smp.h
===================================================================
--- next.git.orig/arch/powerpc/include/asm/smp.h	2008-10-05 00:08:36.000000000 -0500
+++ next.git/arch/powerpc/include/asm/smp.h	2008-10-05 00:16:34.000000000 -0500
@@ -81,6 +81,13 @@ extern int cpu_to_core_id(int cpu);
 #define PPC_MSG_CALL_FUNC_SINGLE	2
 #define PPC_MSG_DEBUGGER_BREAK  3
 
+/*
+ * irq controllers that have dedicated ipis per message and don't
+ * need additional code in the action handler may use this
+ */
+extern int smp_request_message_ipi(int irq, int message);
+extern const char *smp_ipi_name[];
+
 void smp_init_iSeries(void);
 void smp_init_pSeries(void);
 void smp_init_cell(void);
Index: next.git/arch/powerpc/kernel/smp.c
===================================================================
--- next.git.orig/arch/powerpc/kernel/smp.c	2008-10-05 00:08:38.000000000 -0500
+++ next.git/arch/powerpc/kernel/smp.c	2008-10-05 00:19:12.000000000 -0500
@@ -123,6 +123,65 @@ void smp_message_recv(int msg)
 	}
 }
 
+static irqreturn_t call_function_action(int irq, void *data)
+{
+	generic_smp_call_function_interrupt();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t reschedule_action(int irq, void *data)
+{
+	/* we just need the return path side effect of checking need_resched */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t call_function_single_action(int irq, void *data)
+{
+	generic_smp_call_function_single_interrupt();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t debug_ipi_action(int irq, void *data)
+{
+	smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+	return IRQ_HANDLED;
+}
+
+static irq_handler_t smp_ipi_action[] = {
+	[PPC_MSG_CALL_FUNCTION] =  call_function_action,
+	[PPC_MSG_RESCHEDULE] = reschedule_action,
+	[PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action,
+	[PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
+};
+
+const char *smp_ipi_name[] = {
+	[PPC_MSG_CALL_FUNCTION] =  "ipi call function",
+	[PPC_MSG_RESCHEDULE] = "ipi reschedule",
+	[PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single",
+	[PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
+};
+
+/* optional function to request ipi, for controllers with >= 4 ipis */
+int smp_request_message_ipi(int msg, int virq)
+{
+	int err;
+
+	if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
+		return -EINVAL;
+	}
+#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
+	if (msg == PPC_MSG_DEBUGGER_BREAK) {
+		return 1;
+	}
+#endif
+	err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+			  smp_ipi_name[msg], 0);
+	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
+		virq, ipi_names[msg], err);
+
+	return err;
+}
+
 void smp_send_reschedule(int cpu)
 {
 	if (likely(smp_ops))

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 14/16] powerpc mpic: use smp_request_message_ipi
  2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
@ 2008-10-10 11:56     ` Milton Miller
  2008-10-10 11:56     ` [PATCH 15/16] powerpc cell: " Milton Miller
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerrus

mpic has 4 ipis so use the new smp_request_message_ipi to reduce
pathlength when reciving an ipi.

This has the side effect of using the common ipi names, and also
continuing to try request the remaining messages when one fails.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/sysdev/mpic.c
===================================================================
--- next.git.orig/arch/powerpc/sysdev/mpic.c	2008-10-05 00:20:41.000000000 -0500
+++ next.git/arch/powerpc/sysdev/mpic.c	2008-10-05 00:21:41.000000000 -0500
@@ -616,17 +616,6 @@ static inline void mpic_eoi(struct mpic 
 	(void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
 }
 
-#ifdef CONFIG_SMP
-static irqreturn_t mpic_ipi_action(int irq, void *data)
-{
-	long ipi = (long)data;
-
-	smp_message_recv(ipi);
-
-	return IRQ_HANDLED;
-}
-#endif /* CONFIG_SMP */
-
 /*
  * Linux descriptor level callbacks
  */
@@ -1492,13 +1481,7 @@ unsigned int mpic_get_mcirq(void)
 void mpic_request_ipis(void)
 {
 	struct mpic *mpic = mpic_primary;
-	long i, err;
-	static char *ipi_names[] = {
-		"IPI0 (call function)",
-		"IPI1 (reschedule)",
-		"IPI2 (call function single)",
-		"IPI3 (debugger break)",
-	};
+	int i;
 	BUG_ON(mpic == NULL);
 
 	printk(KERN_INFO "mpic: requesting IPIs ... \n");
@@ -1507,17 +1490,10 @@ void mpic_request_ipis(void)
 		unsigned int vipi = irq_create_mapping(mpic->irqhost,
 						       mpic->ipi_vecs[0] + i);
 		if (vipi == NO_IRQ) {
-			printk(KERN_ERR "Failed to map IPI %ld\n", i);
-			break;
-		}
-		err = request_irq(vipi, mpic_ipi_action,
-				  IRQF_DISABLED|IRQF_PERCPU,
-				  ipi_names[i], (void *)i);
-		if (err) {
-			printk(KERN_ERR "Request of irq %d for IPI %ld failed\n",
-			       vipi, i);
-			break;
+			printk(KERN_ERR "Failed to map %s\n", smp_ipi_name[i]);
+			continue;
 		}
+		smp_request_message_ipi(vipi, i);
 	}
 }
 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 15/16] powerpc cell: use smp_request_message_ipi
  2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
  2008-10-10 11:56     ` [PATCH 14/16] powerpc mpic: use smp_request_message_ipi Milton Miller
@ 2008-10-10 11:56     ` Milton Miller
  2008-10-10 11:56     ` [PATCH 16/16] powerpc ps3: " Milton Miller
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras; +Cc: Arnd Bergmann

cell native has 4 interrupts for ipis, so use the new smp_request_message_ipi
to save pathlength and the data-dependent branch.

This has the side effects of enabling the debugger ipi for kdump and
setting IRQF_PERCPU for the ipi interrupts.  It doesn't undo the virq
mapping if it turns out the ipi is not used.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/cell/interrupt.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/cell/interrupt.c	2008-10-04 23:40:24.000000000 -0500
+++ next.git/arch/powerpc/platforms/cell/interrupt.c	2008-10-04 23:44:49.000000000 -0500
@@ -190,38 +190,25 @@ struct irq_host *iic_get_irq_host(int no
 }
 EXPORT_SYMBOL_GPL(iic_get_irq_host);
 
-static irqreturn_t iic_ipi_action(int irq, void *dev_id)
-{
-	int ipi = (int)(long)dev_id;
-
-	smp_message_recv(ipi);
-
-	return IRQ_HANDLED;
-}
-static void iic_request_ipi(int ipi, const char *name)
+static void iic_request_ipi(int ipi)
 {
 	int virq;
 
 	virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi));
 	if (virq == NO_IRQ) {
 		printk(KERN_ERR
-		       "iic: failed to map IPI %s\n", name);
+		       "iic: failed to map IPI %s\n", smp_ipi_name[ipi]);
 		return;
 	}
-	if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name,
-			(void *)(long)ipi))
-		printk(KERN_ERR
-		       "iic: failed to request IPI %s\n", name);
+	smp_request_message_ipi(virq, ipi);
 }
 
 void iic_request_IPIs(void)
 {
-	iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
-	iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
-	iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single");
-#ifdef CONFIG_DEBUGGER
-	iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
-#endif /* CONFIG_DEBUGGER */
+	iic_request_ipi(PPC_MSG_CALL_FUNCTION);
+	iic_request_ipi(PPC_MSG_RESCHEDULE);
+	iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE);
+	iic_request_ipi(PPC_MSG_DEBUGGER_BREAK);
 }
 
 #endif /* CONFIG_SMP */

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 16/16] powerpc ps3: use smp_request_message_ipi
  2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
  2008-10-10 11:56     ` [PATCH 14/16] powerpc mpic: use smp_request_message_ipi Milton Miller
  2008-10-10 11:56     ` [PATCH 15/16] powerpc cell: " Milton Miller
@ 2008-10-10 11:56     ` Milton Miller
  2008-10-10 12:55     ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Geert Uytterhoeven
  2008-10-21  1:37     ` [PATCH 14/16 v2] " Milton Miller
  4 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-10-10 11:56 UTC (permalink / raw)
  To: linuxppc-dev, Ben Herrenschmidt, Paul Mackerras

ps3 has 4 ipis per cpu and can use the new smp_request_message_ipi to
reduce path length when receiving an ipi.

This has the side effect of setting IRQF_PERCPU.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/ps3/smp.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/ps3/smp.c	2008-10-05 00:20:41.000000000 -0500
+++ next.git/arch/powerpc/platforms/ps3/smp.c	2008-10-05 00:22:50.000000000 -0500
@@ -32,12 +32,6 @@
 #define DBG pr_debug
 #endif
 
-static irqreturn_t ipi_function_handler(int irq, void *msg)
-{
-	smp_message_recv((int)(long)msg);
-	return IRQ_HANDLED;
-}
-
 /**
   * ps3_ipi_virqs - a per cpu array of virqs for ipi use
   */
@@ -45,13 +39,6 @@ static irqreturn_t ipi_function_handler(
 #define MSG_COUNT 4
 static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
 
-static const char *names[MSG_COUNT] = {
-	"ipi call",
-	"ipi reschedule",
-	"ipi migrate",
-	"ipi debug brk"
-};
-
 static void do_message_pass(int target, int msg)
 {
 	int result;
@@ -119,8 +106,7 @@ static void __init ps3_smp_setup_cpu(int
 		DBG("%s:%d: (%d, %d) => virq %u\n",
 			__func__, __LINE__, cpu, i, virqs[i]);
 
-		result = request_irq(virqs[i], ipi_function_handler,
-			IRQF_DISABLED, names[i], (void*)(long)i);
+		result = smp_request_message_ipi(virqs[i], i);
 
 		if (result)
 			virqs[i] = NO_IRQ;

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/16] powerpc: expand vs demux ipi actions per message
  2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
                       ` (2 preceding siblings ...)
  2008-10-10 11:56     ` [PATCH 16/16] powerpc ps3: " Milton Miller
@ 2008-10-10 12:55     ` Geert Uytterhoeven
  2008-10-21  1:37     ` [PATCH 14/16 v2] " Milton Miller
  4 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2008-10-10 12:55 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Arnd Bergmann

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1072 bytes --]

On Fri, 10 Oct 2008, Milton Miller wrote:
> +/*
> + * irq controllers that have dedicated ipis per message and don't
> + * need additional code in the action handler may use this
> + */
> +extern int smp_request_message_ipi(int irq, int message);
                                          ^^^      ^^^^^^^
> +/* optional function to request ipi, for controllers with >= 4 ipis */
> +int smp_request_message_ipi(int msg, int virq)
                                   ^^^      ^^^^

Woops, the order (and to a lesser extend, the name) of the arguments doesn't
match?
Worse, all callers use the order of the prototype, not the one of the
implementation.

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone:    +32 (0)2 700 8453
Fax:      +32 (0)2 700 8622
E-mail:   Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 7/16] xics: initialization cleanups
  2008-10-10 11:56 ` [PATCH 7/16] xics: initialization cleanups Milton Miller
@ 2008-10-13  0:55   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 25+ messages in thread
From: Benjamin Herrenschmidt @ 2008-10-13  0:55 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras


>  static void __init xics_init_one_node(struct device_node *np,
> @@ -700,8 +694,10 @@ void __init xics_init_IRQ(void)
>  
>  	for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
>  		found = 1;
> -		if (firmware_has_feature(FW_FEATURE_LPAR))
> +		if (firmware_has_feature(FW_FEATURE_LPAR)) {
> +			of_node_put(np);
>  			break;
> +			}

Little tab damage up here... no big deal.

>  		xics_init_one_node(np, &indx);
>  	}
>  	if (found == 0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 00/16] xics and ipi cleanups for 2.6.28
  2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
                   ` (12 preceding siblings ...)
  2008-10-10 11:56 ` [PATCH 13/16] powerpc smp: no need to set_need_resched in resched ipi Milton Miller
@ 2008-10-13  5:28 ` Benjamin Herrenschmidt
  13 siblings, 0 replies; 25+ messages in thread
From: Benjamin Herrenschmidt @ 2008-10-13  5:28 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras

On Fri, 2008-10-10 at 06:56 -0500, Milton Miller wrote:
> The first two patches in this series implememnt a couple of bug
> fixes for the xics interrupt controller accessed as found in pseries
> hardware.  The next several patches implement some code orginization
> and cleanups, followed by some changes to reduce code or flag the
> behavior to generic code.
> 
> The last 5 patces are independent of the xics changes, although the
> first one affects xics.  They are designed to reduce interrupt
> overhead for interprocessor interupts.  

I've merged 1..13. The other ones, I'm less sure about, we need to
have a closer look (in addition to Geert comments) and they are
probably not .28 material anyway.

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/16] xics: update default_server during migrate_irqs_away
  2008-10-10 11:56 ` [PATCH 2/16] xics: update default_server during migrate_irqs_away Milton Miller
@ 2008-10-13 20:04   ` Nathan Fontenot
  0 siblings, 0 replies; 25+ messages in thread
From: Nathan Fontenot @ 2008-10-13 20:04 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras

Milton Miller wrote:
> Currently, every time we determine which irq server to use, we check if
> default_server, which is the id of the bootcpu, is still online.  But
> default_server is a hardware cpu, not the logical cpu id needed to index
> cpu_online_map.  
> 
> Since the default server can only go offline during a cpu hotplug event,
> explicitly check the default server and choose the new one when we move
> irqs away from the cpu being offlined.
> 
> This has the added benefit of only needing the boot_cpuid to be updated
> and not relying on the cpu being marked offline during migrate_irqs_away.
> 
> Also, since xics_update_irq_servers only reads device tree information, we
> can call it before xics_init_host in xics_init_IRQ and then default_server
> will always be valid when we can reach get_irq_server via the host ops.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>

Acked-by: Nathan Fontenot <nfont@austin.ibm.com>

> ---
> I realized the hard vs soft cpu id as I was writing the patch description.
> get_irq_server is called from unmask and set affinity.  
> 
> The effects of this bug would be the increased pathlength to walk the
> device tree in the unmask and set affinity methods, and possible failure
> to migrate irqs during cpu hotplug removal (not likely to be seen on
> until a sequence of remove and adds is performed).
> 
> This check dates to 2.6.25 via de0723dcca6e593a12a259798a54eb0e82628fb8.
> 
> Index: next.git/arch/powerpc/platforms/pseries/xics.c
> ===================================================================
> --- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2008-10-04 16:36:07.000000000 -0500
> +++ next.git/arch/powerpc/platforms/pseries/xics.c	2008-10-04 16:36:09.000000000 -0500
> @@ -208,9 +208,6 @@ static int get_irq_server(unsigned int v
>  	cpumask_t cpumask = irq_desc[virq].affinity;
>  	cpumask_t tmp = CPU_MASK_NONE;
>  
> -	if (! cpu_isset(default_server, cpu_online_map))
> -		xics_update_irq_servers();
> -
>  	if (!distribute_irqs)
>  		return default_server;
>  
> @@ -685,8 +682,8 @@ void __init xics_init_IRQ(void)
>  	if (found == 0)
>  		return;
>  
> -	xics_init_host();
>  	xics_update_irq_servers();
> +	xics_init_host();
>  
>  	if (firmware_has_feature(FW_FEATURE_LPAR))
>  		ppc_md.get_irq = xics_get_irq_lpar;
> @@ -779,6 +776,10 @@ void xics_migrate_irqs_away(void)
>  	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
>  	unsigned int irq, virq;
>  
> +	/* If we used to be the default server, move to the new "boot_cpuid" */
> +	if (hw_cpu == default_server)
> +		xics_update_irq_servers();
> +
>  	/* Reject any interrupt that was queued to us... */
>  	xics_set_cpu_priority(0);
>  

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 14/16 v2] powerpc: expand vs demux ipi actions per message
  2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
                       ` (3 preceding siblings ...)
  2008-10-10 12:55     ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Geert Uytterhoeven
@ 2008-10-21  1:37     ` Milton Miller
  2008-11-06  4:42       ` Paul Mackerras
  4 siblings, 1 reply; 25+ messages in thread
From: Milton Miller @ 2008-10-21  1:37 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Arnd Bergmann

With the new generic smp call function helpers, I noticed the code in
smp_message_recv was a single function call in many cases.  While
getting the message number from the ipi data is easy, we can reduce
the path length by a function and data dependent switch by registering
separate ipi actions for these simple calls.

Originally I left the ipi action array exposed, but then I realized the
registration code should be common too.

The three users each had their own name array, so I made a fourth
to convert all users to use a common one.

Signed-off-by: Milton Miller <miltonm@bga.com>
---
v2: fix arg reversal noted by Geert Uytterhoeven.   This order is most
similar to request_irq and message in data field, but without casting.

Perhaps we should make the common code look like an ipi action handler
and remove this last call?  Currently we still have to allocate a stack
frame to load the return value.

Index: next.git/arch/powerpc/include/asm/smp.h
===================================================================
--- next.git.orig/arch/powerpc/include/asm/smp.h	2008-10-05 00:08:36.000000000 -0500
+++ next.git/arch/powerpc/include/asm/smp.h	2008-10-05 00:16:34.000000000 -0500
@@ -81,6 +81,13 @@ extern int cpu_to_core_id(int cpu);
 #define PPC_MSG_CALL_FUNC_SINGLE	2
 #define PPC_MSG_DEBUGGER_BREAK  3
 
+/*
+ * irq controllers that have dedicated ipis per message and don't
+ * need additional code in the action handler may use this
+ */
+extern int smp_request_message_ipi(int virq, int message);
+extern const char *smp_ipi_name[];
+
 void smp_init_iSeries(void);
 void smp_init_pSeries(void);
 void smp_init_cell(void);
Index: next.git/arch/powerpc/kernel/smp.c
===================================================================
--- next.git.orig/arch/powerpc/kernel/smp.c	2008-10-05 00:08:38.000000000 -0500
+++ next.git/arch/powerpc/kernel/smp.c	2008-10-05 00:19:12.000000000 -0500
@@ -123,6 +123,65 @@ void smp_message_recv(int msg)
 	}
 }
 
+static irqreturn_t call_function_action(int irq, void *data)
+{
+	generic_smp_call_function_interrupt();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t reschedule_action(int irq, void *data)
+{
+	/* we just need the return path side effect of checking need_resched */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t call_function_single_action(int irq, void *data)
+{
+	generic_smp_call_function_single_interrupt();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t debug_ipi_action(int irq, void *data)
+{
+	smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+	return IRQ_HANDLED;
+}
+
+static irq_handler_t smp_ipi_action[] = {
+	[PPC_MSG_CALL_FUNCTION] =  call_function_action,
+	[PPC_MSG_RESCHEDULE] = reschedule_action,
+	[PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action,
+	[PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
+};
+
+const char *smp_ipi_name[] = {
+	[PPC_MSG_CALL_FUNCTION] =  "ipi call function",
+	[PPC_MSG_RESCHEDULE] = "ipi reschedule",
+	[PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single",
+	[PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
+};
+
+/* optional function to request ipi, for controllers with >= 4 ipis */
+int smp_request_message_ipi(int virq, int msg)
+{
+	int err;
+
+	if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
+		return -EINVAL;
+	}
+#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
+	if (msg == PPC_MSG_DEBUGGER_BREAK) {
+		return 1;
+	}
+#endif
+	err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+			  smp_ipi_name[msg], 0);
+	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
+		virq, ipi_names[msg], err);
+
+	return err;
+}
+
 void smp_send_reschedule(int cpu)
 {
 	if (likely(smp_ops))

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/16 v2] powerpc: expand vs demux ipi actions per message
  2008-10-21  1:37     ` [PATCH 14/16 v2] " Milton Miller
@ 2008-11-06  4:42       ` Paul Mackerras
  2008-11-11 16:12         ` Milton Miller
  0 siblings, 1 reply; 25+ messages in thread
From: Paul Mackerras @ 2008-11-06  4:42 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Arnd Bergmann

Milton Miller writes:

> With the new generic smp call function helpers, I noticed the code in
> smp_message_recv was a single function call in many cases.  While
> getting the message number from the ipi data is easy, we can reduce
> the path length by a function and data dependent switch by registering
> separate ipi actions for these simple calls.

With this I get:

  CC      arch/powerpc/kernel/smp.o
arch/powerpc/kernel/smp.c: In function 'smp_request_message_ipi':
arch/powerpc/kernel/smp.c:177: error: 'ipi_names' undeclared (first use in this function)
arch/powerpc/kernel/smp.c:177: error: (Each undeclared identifier is reported only once
arch/powerpc/kernel/smp.c:177: error: for each function it appears in.)
make[2]: *** [arch/powerpc/kernel/smp.o] Error 1

I think you need smp_ipi_name rather than ipi_names here:

> +	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
> +		virq, ipi_names[msg], err);

Paul.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/16 v2] powerpc: expand vs demux ipi actions per message
  2008-11-06  4:42       ` Paul Mackerras
@ 2008-11-11 16:12         ` Milton Miller
  0 siblings, 0 replies; 25+ messages in thread
From: Milton Miller @ 2008-11-11 16:12 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann


On Nov 5, 2008, at 10:42 PM, Paul Mackerras wrote:

> Milton Miller writes:
>
>> With the new generic smp call function helpers, I noticed the code in
>> smp_message_recv was a single function call in many cases.  While
>> getting the message number from the ipi data is easy, we can reduce
>> the path length by a function and data dependent switch by registering
>> separate ipi actions for these simple calls.
>
> With this I get:
>
>   CC      arch/powerpc/kernel/smp.o
> arch/powerpc/kernel/smp.c: In function 'smp_request_message_ipi':
> arch/powerpc/kernel/smp.c:177: error: 'ipi_names' undeclared (first 
> use in this function)
> arch/powerpc/kernel/smp.c:177: error: (Each undeclared identifier is 
> reported only once
> arch/powerpc/kernel/smp.c:177: error: for each function it appears in.)
> make[2]: *** [arch/powerpc/kernel/smp.o] Error 1
>
> I think you need smp_ipi_name rather than ipi_names here:
>
>> +	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
>> +		virq, ipi_names[msg], err);
>

You are exactly correct.  I changed my mind on the name of this 
varable, and missed this spot on the final edit.  However, my compile 
passed because it was during the time that the powerpc version of WARN 
was never evaluating its printf arguments.

I wrote and compile tested the change, but need to find or setup a 
mailer to send it.

milton

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2008-11-11 16:07 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-10 11:56 [PATCH 00/16] xics and ipi cleanups for 2.6.28 Milton Miller
2008-10-10 11:56 ` [PATCH 1/16] powerpc pseries: eoi unmapped xics irqs after disable Milton Miller
2008-10-10 11:56 ` [PATCH 2/16] xics: update default_server during migrate_irqs_away Milton Miller
2008-10-13 20:04   ` Nathan Fontenot
2008-10-10 11:56 ` [PATCH 3/16] xics: consolidate ipi message encode and decode Milton Miller
2008-10-10 11:56 ` [PATCH 4/16] xics: rearrange file to group code by function Milton Miller
2008-10-10 11:56 ` [PATCH 5/16] xics: change arg type to remove casts Milton Miller
2008-10-10 11:56 ` [PATCH 6/16] xics: trim includes Milton Miller
2008-10-10 11:56 ` [PATCH 7/16] xics: initialization cleanups Milton Miller
2008-10-13  0:55   ` Benjamin Herrenschmidt
2008-10-10 11:56 ` [PATCH 8/16] xics: factor out giq set and unset Milton Miller
2008-10-10 11:56 ` [PATCH 9/16] powerpc: eoi xics ipi by hand in kexec Milton Miller
2008-10-10 11:56 ` [PATCH 11/16] powerpc: mark xics ipi percpu Milton Miller
2008-10-10 11:56 ` [PATCH 10/16] xics: make printk formats fit on one line Milton Miller
2008-10-10 11:56 ` [PATCH 12/16] powerpc: reduce and comment xics ipi memory barrier Milton Miller
2008-10-10 11:56 ` [PATCH 13/16] powerpc smp: no need to set_need_resched in resched ipi Milton Miller
2008-10-10 11:56   ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Milton Miller
2008-10-10 11:56     ` [PATCH 14/16] powerpc mpic: use smp_request_message_ipi Milton Miller
2008-10-10 11:56     ` [PATCH 15/16] powerpc cell: " Milton Miller
2008-10-10 11:56     ` [PATCH 16/16] powerpc ps3: " Milton Miller
2008-10-10 12:55     ` [PATCH 14/16] powerpc: expand vs demux ipi actions per message Geert Uytterhoeven
2008-10-21  1:37     ` [PATCH 14/16 v2] " Milton Miller
2008-11-06  4:42       ` Paul Mackerras
2008-11-11 16:12         ` Milton Miller
2008-10-13  5:28 ` [PATCH 00/16] xics and ipi cleanups for 2.6.28 Benjamin Herrenschmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).