Patchwork [14/16,v2] powerpc: expand vs demux ipi actions per message

login
register
mail settings
Submitter Milton Miller
Date Oct. 21, 2008, 1:37 a.m.
Message ID <patch-ipi-2-v2@bga.com>
Download mbox | patch
Permalink /patch/5174/
State Awaiting Upstream
Delegated to: Paul Mackerras
Headers show

Comments

Milton Miller - Oct. 21, 2008, 1:37 a.m.
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.
Paul Mackerras - Nov. 6, 2008, 4:42 a.m.
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.
Milton Miller - Nov. 11, 2008, 4:12 p.m.
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

Patch

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