diff options
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r-- | kernel/cpu.c | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 41a6cb85c0af..15a413639abc 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -228,6 +228,43 @@ static int cpu_notify(unsigned long val, unsigned int cpu) | |||
228 | return __cpu_notify(val, cpu, -1, NULL); | 228 | return __cpu_notify(val, cpu, -1, NULL); |
229 | } | 229 | } |
230 | 230 | ||
231 | /* Notifier wrappers for transitioning to state machine */ | ||
232 | static int notify_prepare(unsigned int cpu) | ||
233 | { | ||
234 | int nr_calls = 0; | ||
235 | int ret; | ||
236 | |||
237 | ret = __cpu_notify(CPU_UP_PREPARE, cpu, -1, &nr_calls); | ||
238 | if (ret) { | ||
239 | nr_calls--; | ||
240 | printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n", | ||
241 | __func__, cpu); | ||
242 | __cpu_notify(CPU_UP_CANCELED, cpu, nr_calls, NULL); | ||
243 | } | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static int notify_online(unsigned int cpu) | ||
248 | { | ||
249 | cpu_notify(CPU_ONLINE, cpu); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int bringup_cpu(unsigned int cpu) | ||
254 | { | ||
255 | struct task_struct *idle = idle_thread_get(cpu); | ||
256 | int ret; | ||
257 | |||
258 | /* Arch-specific enabling code. */ | ||
259 | ret = __cpu_up(cpu, idle); | ||
260 | if (ret) { | ||
261 | cpu_notify(CPU_UP_CANCELED, cpu); | ||
262 | return ret; | ||
263 | } | ||
264 | BUG_ON(!cpu_online(cpu)); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
231 | #ifdef CONFIG_HOTPLUG_CPU | 268 | #ifdef CONFIG_HOTPLUG_CPU |
232 | 269 | ||
233 | static void cpu_notify_nofail(unsigned long val, unsigned int cpu) | 270 | static void cpu_notify_nofail(unsigned long val, unsigned int cpu) |
@@ -481,7 +518,7 @@ void smpboot_thread_init(void) | |||
481 | static int _cpu_up(unsigned int cpu, int tasks_frozen) | 518 | static int _cpu_up(unsigned int cpu, int tasks_frozen) |
482 | { | 519 | { |
483 | struct task_struct *idle; | 520 | struct task_struct *idle; |
484 | int ret, nr_calls = 0; | 521 | int ret; |
485 | 522 | ||
486 | cpu_hotplug_begin(); | 523 | cpu_hotplug_begin(); |
487 | 524 | ||
@@ -496,33 +533,21 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) | |||
496 | goto out; | 533 | goto out; |
497 | } | 534 | } |
498 | 535 | ||
536 | cpuhp_tasks_frozen = tasks_frozen; | ||
537 | |||
499 | ret = smpboot_create_threads(cpu); | 538 | ret = smpboot_create_threads(cpu); |
500 | if (ret) | 539 | if (ret) |
501 | goto out; | 540 | goto out; |
502 | 541 | ||
503 | cpuhp_tasks_frozen = tasks_frozen; | 542 | ret = notify_prepare(cpu); |
504 | 543 | if (ret) | |
505 | ret = __cpu_notify(CPU_UP_PREPARE, cpu, -1, &nr_calls); | 544 | goto out; |
506 | if (ret) { | ||
507 | nr_calls--; | ||
508 | pr_warn("%s: attempt to bring up CPU %u failed\n", | ||
509 | __func__, cpu); | ||
510 | goto out_notify; | ||
511 | } | ||
512 | |||
513 | /* Arch-specific enabling code. */ | ||
514 | ret = __cpu_up(cpu, idle); | ||
515 | |||
516 | if (ret != 0) | ||
517 | goto out_notify; | ||
518 | BUG_ON(!cpu_online(cpu)); | ||
519 | 545 | ||
520 | /* Now call notifier in preparation. */ | 546 | ret = bringup_cpu(cpu); |
521 | cpu_notify(CPU_ONLINE, cpu); | 547 | if (ret) |
548 | goto out; | ||
522 | 549 | ||
523 | out_notify: | 550 | notify_online(cpu); |
524 | if (ret != 0) | ||
525 | __cpu_notify(CPU_UP_CANCELED, cpu, nr_calls, NULL); | ||
526 | out: | 551 | out: |
527 | cpu_hotplug_done(); | 552 | cpu_hotplug_done(); |
528 | 553 | ||