diff options
| author | H. Peter Anvin <hpa@zytor.com> | 2008-08-25 20:07:14 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2008-08-25 20:45:48 -0400 |
| commit | f73be6dedf4fa058ce80846dae604b08fa805ca1 (patch) | |
| tree | eb38c111bedf6b356db3af20ab124dff846643cb /kernel | |
| parent | 2a61812af2e564cba2c8170cf96e1c823210f619 (diff) | |
smp: have smp_call_function_single() detect invalid CPUs
Have smp_call_function_single() return invalid CPU indicies and return
-ENXIO. This function is already executed inside a
get_cpu()..put_cpu() which locks out CPU removal, so rather than
having the higher layers doing another layer of locking to guard
against unplugged CPUs do the test here.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
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 | ||
