diff options
| -rw-r--r-- | arch/mips/kernel/smp.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 04bbbd8d91ab..73b0dab02668 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
| @@ -194,6 +194,61 @@ void smp_call_function_interrupt(void) | |||
| 194 | } | 194 | } |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | ||
| 198 | int retry, int wait) | ||
| 199 | { | ||
| 200 | struct call_data_struct data; | ||
| 201 | int me; | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Can die spectacularly if this CPU isn't yet marked online | ||
| 205 | */ | ||
| 206 | if (!cpu_online(cpu)) | ||
| 207 | return 0; | ||
| 208 | |||
| 209 | me = get_cpu(); | ||
| 210 | BUG_ON(!cpu_online(me)); | ||
| 211 | |||
| 212 | if (cpu == me) { | ||
| 213 | local_irq_disable(); | ||
| 214 | func(info); | ||
| 215 | local_irq_enable(); | ||
| 216 | put_cpu(); | ||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | /* Can deadlock when called with interrupts disabled */ | ||
| 221 | WARN_ON(irqs_disabled()); | ||
| 222 | |||
| 223 | data.func = func; | ||
| 224 | data.info = info; | ||
| 225 | atomic_set(&data.started, 0); | ||
| 226 | data.wait = wait; | ||
| 227 | if (wait) | ||
| 228 | atomic_set(&data.finished, 0); | ||
| 229 | |||
| 230 | spin_lock(&smp_call_lock); | ||
| 231 | call_data = &data; | ||
| 232 | smp_mb(); | ||
| 233 | |||
| 234 | /* Send a message to the other CPU */ | ||
| 235 | core_send_ipi(cpu, SMP_CALL_FUNCTION); | ||
| 236 | |||
| 237 | /* Wait for response */ | ||
| 238 | /* FIXME: lock-up detection, backtrace on lock-up */ | ||
| 239 | while (atomic_read(&data.started) != 1) | ||
| 240 | barrier(); | ||
| 241 | |||
| 242 | if (wait) | ||
| 243 | while (atomic_read(&data.finished) != 1) | ||
| 244 | barrier(); | ||
| 245 | call_data = NULL; | ||
| 246 | spin_unlock(&smp_call_lock); | ||
| 247 | |||
| 248 | put_cpu(); | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 197 | static void stop_this_cpu(void *dummy) | 252 | static void stop_this_cpu(void *dummy) |
| 198 | { | 253 | { |
| 199 | /* | 254 | /* |
