aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/smp.c
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-02-25 19:07:43 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-03-04 23:55:04 -0500
commit1b67bee129a36c22c17186cc2a9981678e9323ee (patch)
treeaf3787d56f78a8f4624aabb7771589deb1428192 /arch/powerpc/kernel/smp.c
parent402d9a1e02f7215628f13b7c80ff3e98c3a0cadc (diff)
powerpc: Implement tick broadcast IPI as a fixed IPI message
For scalability and performance reasons, we want the tick broadcast IPIs to be handled as efficiently as possible. Fixed IPI messages are one of the most efficient mechanisms available - they are faster than the smp_call_function mechanism because the IPI handlers are fixed and hence they don't involve costly operations such as adding IPI handlers to the target CPU's function queue, acquiring locks for synchronization etc. Luckily we have an unused IPI message slot, so use that to implement tick broadcast IPIs efficiently. Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> [Functions renamed to tick_broadcast* and Changelog modified by Preeti U. Murthy<preeti@linux.vnet.ibm.com>] Signed-off-by: Preeti U. Murthy <preeti@linux.vnet.ibm.com> Acked-by: Geoff Levand <geoff@infradead.org> [For the PS3 part] Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r--arch/powerpc/kernel/smp.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ee7d76bfcb4c..e2a4232c5871 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -35,6 +35,7 @@
35#include <asm/ptrace.h> 35#include <asm/ptrace.h>
36#include <linux/atomic.h> 36#include <linux/atomic.h>
37#include <asm/irq.h> 37#include <asm/irq.h>
38#include <asm/hw_irq.h>
38#include <asm/page.h> 39#include <asm/page.h>
39#include <asm/pgtable.h> 40#include <asm/pgtable.h>
40#include <asm/prom.h> 41#include <asm/prom.h>
@@ -145,9 +146,9 @@ static irqreturn_t reschedule_action(int irq, void *data)
145 return IRQ_HANDLED; 146 return IRQ_HANDLED;
146} 147}
147 148
148static irqreturn_t unused_action(int irq, void *data) 149static irqreturn_t tick_broadcast_ipi_action(int irq, void *data)
149{ 150{
150 /* This slot is unused and hence available for use, if needed */ 151 tick_broadcast_ipi_handler();
151 return IRQ_HANDLED; 152 return IRQ_HANDLED;
152} 153}
153 154
@@ -168,14 +169,14 @@ static irqreturn_t debug_ipi_action(int irq, void *data)
168static irq_handler_t smp_ipi_action[] = { 169static irq_handler_t smp_ipi_action[] = {
169 [PPC_MSG_CALL_FUNCTION] = call_function_action, 170 [PPC_MSG_CALL_FUNCTION] = call_function_action,
170 [PPC_MSG_RESCHEDULE] = reschedule_action, 171 [PPC_MSG_RESCHEDULE] = reschedule_action,
171 [PPC_MSG_UNUSED] = unused_action, 172 [PPC_MSG_TICK_BROADCAST] = tick_broadcast_ipi_action,
172 [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action, 173 [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
173}; 174};
174 175
175const char *smp_ipi_name[] = { 176const char *smp_ipi_name[] = {
176 [PPC_MSG_CALL_FUNCTION] = "ipi call function", 177 [PPC_MSG_CALL_FUNCTION] = "ipi call function",
177 [PPC_MSG_RESCHEDULE] = "ipi reschedule", 178 [PPC_MSG_RESCHEDULE] = "ipi reschedule",
178 [PPC_MSG_UNUSED] = "ipi unused", 179 [PPC_MSG_TICK_BROADCAST] = "ipi tick-broadcast",
179 [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger", 180 [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
180}; 181};
181 182
@@ -251,6 +252,8 @@ irqreturn_t smp_ipi_demux(void)
251 generic_smp_call_function_interrupt(); 252 generic_smp_call_function_interrupt();
252 if (all & IPI_MESSAGE(PPC_MSG_RESCHEDULE)) 253 if (all & IPI_MESSAGE(PPC_MSG_RESCHEDULE))
253 scheduler_ipi(); 254 scheduler_ipi();
255 if (all & IPI_MESSAGE(PPC_MSG_TICK_BROADCAST))
256 tick_broadcast_ipi_handler();
254 if (all & IPI_MESSAGE(PPC_MSG_DEBUGGER_BREAK)) 257 if (all & IPI_MESSAGE(PPC_MSG_DEBUGGER_BREAK))
255 debug_ipi_action(0, NULL); 258 debug_ipi_action(0, NULL);
256 } while (info->messages); 259 } while (info->messages);
@@ -289,6 +292,16 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
289 do_message_pass(cpu, PPC_MSG_CALL_FUNCTION); 292 do_message_pass(cpu, PPC_MSG_CALL_FUNCTION);
290} 293}
291 294
295#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
296void tick_broadcast(const struct cpumask *mask)
297{
298 unsigned int cpu;
299
300 for_each_cpu(cpu, mask)
301 do_message_pass(cpu, PPC_MSG_TICK_BROADCAST);
302}
303#endif
304
292#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) 305#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
293void smp_send_debugger_break(void) 306void smp_send_debugger_break(void)
294{ 307{