diff options
Diffstat (limited to 'kernel/cpu.c')
| -rw-r--r-- | kernel/cpu.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 1972b161c61e..94bbe4695232 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/gfp.h> | 20 | #include <linux/gfp.h> |
| 21 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
| 22 | #include <linux/lockdep.h> | 22 | #include <linux/lockdep.h> |
| 23 | #include <linux/tick.h> | ||
| 23 | #include <trace/events/power.h> | 24 | #include <trace/events/power.h> |
| 24 | 25 | ||
| 25 | #include "smpboot.h" | 26 | #include "smpboot.h" |
| @@ -338,6 +339,8 @@ static int __ref take_cpu_down(void *_param) | |||
| 338 | return err; | 339 | return err; |
| 339 | 340 | ||
| 340 | cpu_notify(CPU_DYING | param->mod, param->hcpu); | 341 | cpu_notify(CPU_DYING | param->mod, param->hcpu); |
| 342 | /* Give up timekeeping duties */ | ||
| 343 | tick_handover_do_timer(); | ||
| 341 | /* Park the stopper thread */ | 344 | /* Park the stopper thread */ |
| 342 | kthread_park(current); | 345 | kthread_park(current); |
| 343 | return 0; | 346 | return 0; |
| @@ -408,13 +411,17 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) | |||
| 408 | * | 411 | * |
| 409 | * Wait for the stop thread to go away. | 412 | * Wait for the stop thread to go away. |
| 410 | */ | 413 | */ |
| 411 | while (!idle_cpu(cpu)) | 414 | while (!per_cpu(cpu_dead_idle, cpu)) |
| 412 | cpu_relax(); | 415 | cpu_relax(); |
| 416 | smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */ | ||
| 417 | per_cpu(cpu_dead_idle, cpu) = false; | ||
| 413 | 418 | ||
| 419 | hotplug_cpu__broadcast_tick_pull(cpu); | ||
| 414 | /* This actually kills the CPU. */ | 420 | /* This actually kills the CPU. */ |
| 415 | __cpu_die(cpu); | 421 | __cpu_die(cpu); |
| 416 | 422 | ||
| 417 | /* CPU is completely dead: tell everyone. Too late to complain. */ | 423 | /* CPU is completely dead: tell everyone. Too late to complain. */ |
| 424 | tick_cleanup_dead_cpu(cpu); | ||
| 418 | cpu_notify_nofail(CPU_DEAD | mod, hcpu); | 425 | cpu_notify_nofail(CPU_DEAD | mod, hcpu); |
| 419 | 426 | ||
| 420 | check_for_tasks(cpu); | 427 | check_for_tasks(cpu); |
| @@ -446,6 +453,37 @@ out: | |||
| 446 | EXPORT_SYMBOL(cpu_down); | 453 | EXPORT_SYMBOL(cpu_down); |
| 447 | #endif /*CONFIG_HOTPLUG_CPU*/ | 454 | #endif /*CONFIG_HOTPLUG_CPU*/ |
| 448 | 455 | ||
| 456 | /* | ||
| 457 | * Unpark per-CPU smpboot kthreads at CPU-online time. | ||
| 458 | */ | ||
| 459 | static int smpboot_thread_call(struct notifier_block *nfb, | ||
| 460 | unsigned long action, void *hcpu) | ||
| 461 | { | ||
| 462 | int cpu = (long)hcpu; | ||
| 463 | |||
| 464 | switch (action & ~CPU_TASKS_FROZEN) { | ||
| 465 | |||
| 466 | case CPU_ONLINE: | ||
| 467 | smpboot_unpark_threads(cpu); | ||
| 468 | break; | ||
| 469 | |||
| 470 | default: | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | |||
| 474 | return NOTIFY_OK; | ||
| 475 | } | ||
| 476 | |||
| 477 | static struct notifier_block smpboot_thread_notifier = { | ||
| 478 | .notifier_call = smpboot_thread_call, | ||
| 479 | .priority = CPU_PRI_SMPBOOT, | ||
| 480 | }; | ||
| 481 | |||
| 482 | void __cpuinit smpboot_thread_init(void) | ||
| 483 | { | ||
| 484 | register_cpu_notifier(&smpboot_thread_notifier); | ||
| 485 | } | ||
| 486 | |||
| 449 | /* Requires cpu_add_remove_lock to be held */ | 487 | /* Requires cpu_add_remove_lock to be held */ |
| 450 | static int _cpu_up(unsigned int cpu, int tasks_frozen) | 488 | static int _cpu_up(unsigned int cpu, int tasks_frozen) |
| 451 | { | 489 | { |
| @@ -485,9 +523,6 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) | |||
| 485 | goto out_notify; | 523 | goto out_notify; |
| 486 | BUG_ON(!cpu_online(cpu)); | 524 | BUG_ON(!cpu_online(cpu)); |
| 487 | 525 | ||
| 488 | /* Wake the per cpu threads */ | ||
| 489 | smpboot_unpark_threads(cpu); | ||
| 490 | |||
| 491 | /* Now call notifier in preparation. */ | 526 | /* Now call notifier in preparation. */ |
| 492 | cpu_notify(CPU_ONLINE | mod, hcpu); | 527 | cpu_notify(CPU_ONLINE | mod, hcpu); |
| 493 | 528 | ||
