diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-08-01 06:23:57 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-08-01 06:23:57 -0400 |
commit | 440fdb53b4ae58602711b5b8c3a139ace2404dbb (patch) | |
tree | c6fb88d6ad537ec53aeecadc75a61ab6147d4c9c /arch/mips/kernel/smp.c | |
parent | 8b2b403ce0f1a816b7a6a4f47c8798003b26c07a (diff) | |
parent | 8d4fbcfbe0a4bfc73e7f0297c59ae514e1f1436f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/mips/kernel/smp.c')
-rw-r--r-- | arch/mips/kernel/smp.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index be7362bc2c9a..73b0dab02668 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/cpumask.h> | 31 | #include <linux/cpumask.h> |
32 | #include <linux/cpu.h> | 32 | #include <linux/cpu.h> |
33 | #include <linux/err.h> | ||
33 | 34 | ||
34 | #include <asm/atomic.h> | 35 | #include <asm/atomic.h> |
35 | #include <asm/cpu.h> | 36 | #include <asm/cpu.h> |
@@ -193,6 +194,61 @@ void smp_call_function_interrupt(void) | |||
193 | } | 194 | } |
194 | } | 195 | } |
195 | 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 | |||
196 | static void stop_this_cpu(void *dummy) | 252 | static void stop_this_cpu(void *dummy) |
197 | { | 253 | { |
198 | /* | 254 | /* |