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>

+7 -3
+7 -3
kernel/smp.c
··· 210 { 211 struct call_single_data d; 212 unsigned long flags; 213 - /* prevent preemption and reschedule on another processor */ 214 int me = get_cpu(); 215 216 /* Can deadlock when called with interrupts disabled */ 217 WARN_ON(irqs_disabled()); ··· 222 local_irq_save(flags); 223 func(info); 224 local_irq_restore(flags); 225 - } else { 226 struct call_single_data *data = NULL; 227 228 if (!wait) { ··· 238 data->func = func; 239 data->info = info; 240 generic_exec_single(cpu, data); 241 } 242 243 put_cpu(); 244 - return 0; 245 } 246 EXPORT_SYMBOL(smp_call_function_single); 247
··· 210 { 211 struct call_single_data d; 212 unsigned long flags; 213 + /* prevent preemption and reschedule on another processor, 214 + as well as CPU removal */ 215 int me = get_cpu(); 216 + int err = 0; 217 218 /* Can deadlock when called with interrupts disabled */ 219 WARN_ON(irqs_disabled()); ··· 220 local_irq_save(flags); 221 func(info); 222 local_irq_restore(flags); 223 + } else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) { 224 struct call_single_data *data = NULL; 225 226 if (!wait) { ··· 236 data->func = func; 237 data->info = info; 238 generic_exec_single(cpu, data); 239 + } else { 240 + err = -ENXIO; /* CPU not online */ 241 } 242 243 put_cpu(); 244 + return err; 245 } 246 EXPORT_SYMBOL(smp_call_function_single); 247