diff options
| -rw-r--r-- | arch/x86/include/asm/cpu.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/smp.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 39 | ||||
| -rw-r--r-- | arch/x86/xen/smp.c | 46 |
4 files changed, 44 insertions, 45 deletions
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index d2b12988d2ed..bf2caa1dedc5 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h | |||
| @@ -34,8 +34,6 @@ extern int _debug_hotplug_cpu(int cpu, int action); | |||
| 34 | #endif | 34 | #endif |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | DECLARE_PER_CPU(int, cpu_state); | ||
| 38 | |||
| 39 | int mwait_usable(const struct cpuinfo_x86 *); | 37 | int mwait_usable(const struct cpuinfo_x86 *); |
| 40 | 38 | ||
| 41 | #endif /* _ASM_X86_CPU_H */ | 39 | #endif /* _ASM_X86_CPU_H */ |
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 8cd1cc3bc835..a5cb4f6e9492 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h | |||
| @@ -150,12 +150,12 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) | |||
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void cpu_disable_common(void); | 152 | void cpu_disable_common(void); |
| 153 | void cpu_die_common(unsigned int cpu); | ||
| 154 | void native_smp_prepare_boot_cpu(void); | 153 | void native_smp_prepare_boot_cpu(void); |
| 155 | void native_smp_prepare_cpus(unsigned int max_cpus); | 154 | void native_smp_prepare_cpus(unsigned int max_cpus); |
| 156 | void native_smp_cpus_done(unsigned int max_cpus); | 155 | void native_smp_cpus_done(unsigned int max_cpus); |
| 157 | int native_cpu_up(unsigned int cpunum, struct task_struct *tidle); | 156 | int native_cpu_up(unsigned int cpunum, struct task_struct *tidle); |
| 158 | int native_cpu_disable(void); | 157 | int native_cpu_disable(void); |
| 158 | int common_cpu_die(unsigned int cpu); | ||
| 159 | void native_cpu_die(unsigned int cpu); | 159 | void native_cpu_die(unsigned int cpu); |
| 160 | void native_play_dead(void); | 160 | void native_play_dead(void); |
| 161 | void play_dead_common(void); | 161 | void play_dead_common(void); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index febc6aabc72e..c8fa34963ead 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -77,9 +77,6 @@ | |||
| 77 | #include <asm/realmode.h> | 77 | #include <asm/realmode.h> |
| 78 | #include <asm/misc.h> | 78 | #include <asm/misc.h> |
| 79 | 79 | ||
| 80 | /* State of each CPU */ | ||
| 81 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; | ||
| 82 | |||
| 83 | /* Number of siblings per CPU package */ | 80 | /* Number of siblings per CPU package */ |
| 84 | int smp_num_siblings = 1; | 81 | int smp_num_siblings = 1; |
| 85 | EXPORT_SYMBOL(smp_num_siblings); | 82 | EXPORT_SYMBOL(smp_num_siblings); |
| @@ -257,7 +254,7 @@ static void notrace start_secondary(void *unused) | |||
| 257 | lock_vector_lock(); | 254 | lock_vector_lock(); |
| 258 | set_cpu_online(smp_processor_id(), true); | 255 | set_cpu_online(smp_processor_id(), true); |
| 259 | unlock_vector_lock(); | 256 | unlock_vector_lock(); |
| 260 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; | 257 | cpu_set_state_online(smp_processor_id()); |
| 261 | x86_platform.nmi_init(); | 258 | x86_platform.nmi_init(); |
| 262 | 259 | ||
| 263 | /* enable local interrupts */ | 260 | /* enable local interrupts */ |
| @@ -948,7 +945,10 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle) | |||
| 948 | */ | 945 | */ |
| 949 | mtrr_save_state(); | 946 | mtrr_save_state(); |
| 950 | 947 | ||
| 951 | per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; | 948 | /* x86 CPUs take themselves offline, so delayed offline is OK. */ |
| 949 | err = cpu_check_up_prepare(cpu); | ||
| 950 | if (err && err != -EBUSY) | ||
| 951 | return err; | ||
| 952 | 952 | ||
| 953 | /* the FPU context is blank, nobody can own it */ | 953 | /* the FPU context is blank, nobody can own it */ |
| 954 | __cpu_disable_lazy_restore(cpu); | 954 | __cpu_disable_lazy_restore(cpu); |
| @@ -1191,7 +1191,7 @@ void __init native_smp_prepare_boot_cpu(void) | |||
| 1191 | switch_to_new_gdt(me); | 1191 | switch_to_new_gdt(me); |
| 1192 | /* already set me in cpu_online_mask in boot_cpu_init() */ | 1192 | /* already set me in cpu_online_mask in boot_cpu_init() */ |
| 1193 | cpumask_set_cpu(me, cpu_callout_mask); | 1193 | cpumask_set_cpu(me, cpu_callout_mask); |
| 1194 | per_cpu(cpu_state, me) = CPU_ONLINE; | 1194 | cpu_set_state_online(me); |
| 1195 | } | 1195 | } |
| 1196 | 1196 | ||
| 1197 | void __init native_smp_cpus_done(unsigned int max_cpus) | 1197 | void __init native_smp_cpus_done(unsigned int max_cpus) |
| @@ -1318,14 +1318,10 @@ static void __ref remove_cpu_from_maps(int cpu) | |||
| 1318 | numa_remove_cpu(cpu); | 1318 | numa_remove_cpu(cpu); |
| 1319 | } | 1319 | } |
| 1320 | 1320 | ||
| 1321 | static DEFINE_PER_CPU(struct completion, die_complete); | ||
| 1322 | |||
| 1323 | void cpu_disable_common(void) | 1321 | void cpu_disable_common(void) |
| 1324 | { | 1322 | { |
| 1325 | int cpu = smp_processor_id(); | 1323 | int cpu = smp_processor_id(); |
| 1326 | 1324 | ||
| 1327 | init_completion(&per_cpu(die_complete, smp_processor_id())); | ||
| 1328 | |||
| 1329 | remove_siblinginfo(cpu); | 1325 | remove_siblinginfo(cpu); |
| 1330 | 1326 | ||
| 1331 | /* It's now safe to remove this processor from the online map */ | 1327 | /* It's now safe to remove this processor from the online map */ |
| @@ -1349,24 +1345,27 @@ int native_cpu_disable(void) | |||
| 1349 | return 0; | 1345 | return 0; |
| 1350 | } | 1346 | } |
| 1351 | 1347 | ||
| 1352 | void cpu_die_common(unsigned int cpu) | 1348 | int common_cpu_die(unsigned int cpu) |
| 1353 | { | 1349 | { |
| 1354 | wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ); | 1350 | int ret = 0; |
| 1355 | } | ||
| 1356 | 1351 | ||
| 1357 | void native_cpu_die(unsigned int cpu) | ||
| 1358 | { | ||
| 1359 | /* We don't do anything here: idle task is faking death itself. */ | 1352 | /* We don't do anything here: idle task is faking death itself. */ |
| 1360 | 1353 | ||
| 1361 | cpu_die_common(cpu); | ||
| 1362 | |||
| 1363 | /* They ack this in play_dead() by setting CPU_DEAD */ | 1354 | /* They ack this in play_dead() by setting CPU_DEAD */ |
| 1364 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { | 1355 | if (cpu_wait_death(cpu, 5)) { |
| 1365 | if (system_state == SYSTEM_RUNNING) | 1356 | if (system_state == SYSTEM_RUNNING) |
| 1366 | pr_info("CPU %u is now offline\n", cpu); | 1357 | pr_info("CPU %u is now offline\n", cpu); |
| 1367 | } else { | 1358 | } else { |
| 1368 | pr_err("CPU %u didn't die...\n", cpu); | 1359 | pr_err("CPU %u didn't die...\n", cpu); |
| 1360 | ret = -1; | ||
| 1369 | } | 1361 | } |
| 1362 | |||
| 1363 | return ret; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | void native_cpu_die(unsigned int cpu) | ||
| 1367 | { | ||
| 1368 | common_cpu_die(cpu); | ||
| 1370 | } | 1369 | } |
| 1371 | 1370 | ||
| 1372 | void play_dead_common(void) | 1371 | void play_dead_common(void) |
| @@ -1375,10 +1374,8 @@ void play_dead_common(void) | |||
| 1375 | reset_lazy_tlbstate(); | 1374 | reset_lazy_tlbstate(); |
| 1376 | amd_e400_remove_cpu(raw_smp_processor_id()); | 1375 | amd_e400_remove_cpu(raw_smp_processor_id()); |
| 1377 | 1376 | ||
| 1378 | mb(); | ||
| 1379 | /* Ack it */ | 1377 | /* Ack it */ |
| 1380 | __this_cpu_write(cpu_state, CPU_DEAD); | 1378 | (void)cpu_report_death(); |
| 1381 | complete(&per_cpu(die_complete, smp_processor_id())); | ||
| 1382 | 1379 | ||
| 1383 | /* | 1380 | /* |
| 1384 | * With physical CPU hotplug, we should halt the cpu | 1381 | * With physical CPU hotplug, we should halt the cpu |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 08e8489c47f1..1c5e760f34ca 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
| @@ -90,14 +90,10 @@ static void cpu_bringup(void) | |||
| 90 | 90 | ||
| 91 | set_cpu_online(cpu, true); | 91 | set_cpu_online(cpu, true); |
| 92 | 92 | ||
| 93 | this_cpu_write(cpu_state, CPU_ONLINE); | 93 | cpu_set_state_online(cpu); /* Implies full memory barrier. */ |
| 94 | |||
| 95 | wmb(); | ||
| 96 | 94 | ||
| 97 | /* We can take interrupts now: we're officially "up". */ | 95 | /* We can take interrupts now: we're officially "up". */ |
| 98 | local_irq_enable(); | 96 | local_irq_enable(); |
| 99 | |||
| 100 | wmb(); /* make sure everything is out */ | ||
| 101 | } | 97 | } |
| 102 | 98 | ||
| 103 | /* | 99 | /* |
| @@ -459,7 +455,13 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle) | |||
| 459 | xen_setup_timer(cpu); | 455 | xen_setup_timer(cpu); |
| 460 | xen_init_lock_cpu(cpu); | 456 | xen_init_lock_cpu(cpu); |
| 461 | 457 | ||
| 462 | per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; | 458 | /* |
| 459 | * PV VCPUs are always successfully taken down (see 'while' loop | ||
| 460 | * in xen_cpu_die()), so -EBUSY is an error. | ||
| 461 | */ | ||
| 462 | rc = cpu_check_up_prepare(cpu); | ||
| 463 | if (rc) | ||
| 464 | return rc; | ||
| 463 | 465 | ||
| 464 | /* make sure interrupts start blocked */ | ||
