diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-28 15:30:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-28 15:30:59 -0400 |
commit | e52c8857e0ca3214aa7e2a746000ac0f3016b345 (patch) | |
tree | 9fdc6bbe990a8d8dd5fc74c2145e990ae8f2f916 /kernel | |
parent | 9c2bdac40eba639c438690b1245a020e7c2530df (diff) | |
parent | c1b362e3b4d331a63915b268a33207311a439d60 (diff) |
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: update defconfigs
x86: msr: fix bogus return values from rdmsr_safe/wrmsr_safe
x86: cpuid: correct return value on partial operations
x86: msr: correct return value on partial operations
x86: cpuid: propagate error from smp_call_function_single()
x86: msr: propagate errors from smp_call_function_single()
smp: have smp_call_function_single() detect invalid CPUs
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/smp.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/kernel/smp.c b/kernel/smp.c index 782e2b93e465..f362a8553777 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
@@ -210,8 +210,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
210 | { | 210 | { |
211 | struct call_single_data d; | 211 | struct call_single_data d; |
212 | unsigned long flags; | 212 | unsigned long flags; |
213 | /* prevent preemption and reschedule on another processor */ | 213 | /* prevent preemption and reschedule on another processor, |
214 | as well as CPU removal */ | ||
214 | int me = get_cpu(); | 215 | int me = get_cpu(); |
216 | int err = 0; | ||
215 | 217 | ||
216 | /* Can deadlock when called with interrupts disabled */ | 218 | /* Can deadlock when called with interrupts disabled */ |
217 | WARN_ON(irqs_disabled()); | 219 | WARN_ON(irqs_disabled()); |
@@ -220,7 +222,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
220 | local_irq_save(flags); | 222 | local_irq_save(flags); |
221 | func(info); | 223 | func(info); |
222 | local_irq_restore(flags); | 224 | local_irq_restore(flags); |
223 | } else { | 225 | } else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) { |
224 | struct call_single_data *data = NULL; | 226 | struct call_single_data *data = NULL; |
225 | 227 | ||
226 | if (!wait) { | 228 | if (!wait) { |
@@ -236,10 +238,12 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
236 | data->func = func; | 238 | data->func = func; |
237 | data->info = info; | 239 | data->info = info; |
238 | generic_exec_single(cpu, data); | 240 | generic_exec_single(cpu, data); |
241 | } else { | ||
242 | err = -ENXIO; /* CPU not online */ | ||
239 | } | 243 | } |
240 | 244 | ||
241 | put_cpu(); | 245 | put_cpu(); |
242 | return 0; | 246 | return err; |
243 | } | 247 | } |
244 | EXPORT_SYMBOL(smp_call_function_single); | 248 | EXPORT_SYMBOL(smp_call_function_single); |
245 | 249 | ||