smp/hotplug: Differentiate the AP completion between up and down

With lockdep-crossrelease we get deadlock reports that span cpu-up and
cpu-down chains. Such deadlocks cannot possibly happen because cpu-up
and cpu-down are globally serialized.

takedown_cpu()
irq_lock_sparse()
wait_for_completion(&st->done)

cpuhp_thread_fun
cpuhp_up_callback
cpuhp_invoke_callback
irq_affinity_online_cpu
irq_local_spare()
irq_unlock_sparse()
complete(&st->done)

Now that we have consistent AP state, we can trivially separate the
AP completion between up and down using st->bringup.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: max.byungchul.park@gmail.com
Cc: bigeasy@linutronix.de
Cc: efault@gmx.de
Cc: rostedt@goodmis.org
Link: https://lkml.kernel.org/r/20170920170546.872472799@infradead.org


authored by Peter Zijlstra and committed by Thomas Gleixner 5ebe7742 5f4b55e1

Changed files
+32 -17
kernel
+32 -17
kernel/cpu.c
··· 46 46 * @bringup: Single callback bringup or teardown selector 47 47 * @cb_state: The state for a single callback (install/uninstall) 48 48 * @result: Result of the operation 49 - * @done: Signal completion to the issuer of the task 49 + * @done_up: Signal completion to the issuer of the task for cpu-up 50 + * @done_down: Signal completion to the issuer of the task for cpu-down 50 51 */ 51 52 struct cpuhp_cpu_state { 52 53 enum cpuhp_state state; ··· 62 61 struct hlist_node *last; 63 62 enum cpuhp_state cb_state; 64 63 int result; 65 - struct completion done; 64 + struct completion done_up; 65 + struct completion done_down; 66 66 #endif 67 67 }; 68 68 ··· 130 128 * purposes as that state is handled explicitly in cpu_down. 131 129 */ 132 130 return state > CPUHP_BRINGUP_CPU && state != CPUHP_TEARDOWN_CPU; 133 - } 134 - 135 - /* 136 - * The former STARTING/DYING states, ran with IRQs disabled and must not fail. 137 - */ 138 - static bool cpuhp_is_atomic_state(enum cpuhp_state state) 139 - { 140 - return CPUHP_AP_IDLE_DEAD <= state && state < CPUHP_AP_ONLINE; 141 131 } 142 132 143 133 static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state) ··· 226 232 } 227 233 228 234 #ifdef CONFIG_SMP 235 + static inline void wait_for_ap_thread(struct cpuhp_cpu_state *st, bool bringup) 236 + { 237 + struct completion *done = bringup ? &st->done_up : &st->done_down; 238 + wait_for_completion(done); 239 + } 240 + 241 + static inline void complete_ap_thread(struct cpuhp_cpu_state *st, bool bringup) 242 + { 243 + struct completion *done = bringup ? &st->done_up : &st->done_down; 244 + complete(done); 245 + } 246 + 247 + /* 248 + * The former STARTING/DYING states, ran with IRQs disabled and must not fail. 249 + */ 250 + static bool cpuhp_is_atomic_state(enum cpuhp_state state) 251 + { 252 + return CPUHP_AP_IDLE_DEAD <= state && state < CPUHP_AP_ONLINE; 253 + } 254 + 229 255 /* Serializes the updates to cpu_online_mask, cpu_present_mask */ 230 256 static DEFINE_MUTEX(cpu_add_remove_lock); 231 257 bool cpuhp_tasks_frozen; ··· 382 368 smp_mb(); 383 369 st->should_run = true; 384 370 wake_up_process(st->thread); 385 - wait_for_completion(&st->done); 371 + wait_for_ap_thread(st, st->bringup); 386 372 } 387 373 388 374 static int cpuhp_kick_ap(struct cpuhp_cpu_state *st, enum cpuhp_state target) ··· 405 391 struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); 406 392 407 393 /* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */ 408 - wait_for_completion(&st->done); 394 + wait_for_ap_thread(st, true); 409 395 if (WARN_ON_ONCE((!cpu_online(cpu)))) 410 396 return -ECANCELED; 411 397 ··· 478 464 { 479 465 struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); 480 466 481 - init_completion(&st->done); 467 + init_completion(&st->done_up); 468 + init_completion(&st->done_down); 482 469 } 483 470 484 471 static int cpuhp_should_run(unsigned int cpu) ··· 572 557 cpuhp_lock_release(bringup); 573 558 574 559 if (!st->should_run) 575 - complete(&st->done); 560 + complete_ap_thread(st, bringup); 576 561 } 577 562 578 563 /* Invoke a single callback on a remote cpu */ ··· 768 753 * 769 754 * Wait for the stop thread to go away. 770 755 */ 771 - wait_for_completion(&st->done); 756 + wait_for_ap_thread(st, false); 772 757 BUG_ON(st->state != CPUHP_AP_IDLE_DEAD); 773 758 774 759 /* Interrupts are moved away from the dying cpu, reenable alloc/free */ ··· 787 772 { 788 773 struct cpuhp_cpu_state *st = arg; 789 774 790 - complete(&st->done); 775 + complete_ap_thread(st, false); 791 776 } 792 777 793 778 void cpuhp_report_idle_dead(void) ··· 954 939 return; 955 940 956 941 st->state = CPUHP_AP_ONLINE_IDLE; 957 - complete(&st->done); 942 + complete_ap_thread(st, true); 958 943 } 959 944 960 945 /* Requires cpu_add_remove_lock to be held */