aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r--arch/powerpc/kernel/smp.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index d76f7d7929be..a8909aa50642 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -180,7 +180,7 @@ int smp_request_message_ipi(int virq, int msg)
180 180
181#ifdef CONFIG_PPC_SMP_MUXED_IPI 181#ifdef CONFIG_PPC_SMP_MUXED_IPI
182struct cpu_messages { 182struct cpu_messages {
183 unsigned long messages; /* current messages bits */ 183 int messages; /* current messages */
184 unsigned long data; /* data for cause ipi */ 184 unsigned long data; /* data for cause ipi */
185}; 185};
186static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_messages, ipi_message); 186static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_messages, ipi_message);
@@ -195,9 +195,9 @@ void smp_muxed_ipi_set_data(int cpu, unsigned long data)
195void smp_muxed_ipi_message_pass(int cpu, int msg) 195void smp_muxed_ipi_message_pass(int cpu, int msg)
196{ 196{
197 struct cpu_messages *info = &per_cpu(ipi_message, cpu); 197 struct cpu_messages *info = &per_cpu(ipi_message, cpu);
198 unsigned long *tgt = &info->messages; 198 char *message = (char *)&info->messages;
199 199
200 set_bit(msg, tgt); 200 message[msg] = 1;
201 mb(); 201 mb();
202 smp_ops->cause_ipi(cpu, info->data); 202 smp_ops->cause_ipi(cpu, info->data);
203} 203}
@@ -205,30 +205,35 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
205void smp_muxed_ipi_resend(void) 205void smp_muxed_ipi_resend(void)
206{ 206{
207 struct cpu_messages *info = &__get_cpu_var(ipi_message); 207 struct cpu_messages *info = &__get_cpu_var(ipi_message);
208 unsigned long *tgt = &info->messages;
209 208
210 if (*tgt) 209 if (info->messages)
211 smp_ops->cause_ipi(smp_processor_id(), info->data); 210 smp_ops->cause_ipi(smp_processor_id(), info->data);
212} 211}
213 212
214irqreturn_t smp_ipi_demux(void) 213irqreturn_t smp_ipi_demux(void)
215{ 214{
216 struct cpu_messages *info = &__get_cpu_var(ipi_message); 215 struct cpu_messages *info = &__get_cpu_var(ipi_message);
217 unsigned long *tgt = &info->messages; 216 unsigned int all;
218 217
219 mb(); /* order any irq clear */ 218 mb(); /* order any irq clear */
220 while (*tgt) { 219
221 if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) 220 do {
221 all = xchg_local(&info->messages, 0);
222
223#ifdef __BIG_ENDIAN
224 if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION)))
222 generic_smp_call_function_interrupt(); 225 generic_smp_call_function_interrupt();
223 if (test_and_clear_bit(PPC_MSG_RESCHEDULE, tgt)) 226 if (all & (1 << (24 - 8 * PPC_MSG_RESCHEDULE)))
224 reschedule_action(0, NULL); /* upcoming sched hook */ 227 reschedule_action(0, NULL); /* upcoming sched hook */
225 if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, tgt)) 228 if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNC_SINGLE)))
226 generic_smp_call_function_single_interrupt(); 229 generic_smp_call_function_single_interrupt();
227#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) 230 if (all & (1 << (24 - 8 * PPC_MSG_DEBUGGER_BREAK)))
228 if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, tgt))
229 debug_ipi_action(0, NULL); 231 debug_ipi_action(0, NULL);
232#else
233#error Unsupported ENDIAN
230#endif 234#endif
231 } 235 } while (info->messages);
236
232 return IRQ_HANDLED; 237 return IRQ_HANDLED;
233} 238}
234#endif /* CONFIG_PPC_SMP_MUXED_IPI */ 239#endif /* CONFIG_PPC_SMP_MUXED_IPI */