diff options
author | Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> | 2014-02-25 19:07:43 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-03-04 23:55:04 -0500 |
commit | 1b67bee129a36c22c17186cc2a9981678e9323ee (patch) | |
tree | af3787d56f78a8f4624aabb7771589deb1428192 /arch/powerpc/kernel/smp.c | |
parent | 402d9a1e02f7215628f13b7c80ff3e98c3a0cadc (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.c | 21 |
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 | ||
148 | static irqreturn_t unused_action(int irq, void *data) | 149 | static 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) | |||
168 | static irq_handler_t smp_ipi_action[] = { | 169 | static 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 | ||
175 | const char *smp_ipi_name[] = { | 176 | const 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 | ||
296 | void 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) |
293 | void smp_send_debugger_break(void) | 306 | void smp_send_debugger_break(void) |
294 | { | 307 | { |