X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=kernel%2Fcpu.c;fp=kernel%2Fcpu.c;h=63aa50d7ce1efa16f9c29faa97f734f8c5db5d34;hb=955b2fee301c6fc3565e0b3f071236287b06d379;hp=d7f07a2da5a6b6bcc682d39918b3bd97471d9543;hpb=ef5bfcc8f2afb0fa3ee1a38a80bf1b16a9a0d01e;p=karo-tx-linux.git diff --git a/kernel/cpu.c b/kernel/cpu.c index d7f07a2da5a6..63aa50d7ce1e 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -308,6 +308,23 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) } smpboot_park_threads(cpu); + /* + * By now we've cleared cpu_active_mask, wait for all preempt-disabled + * and RCU users of this state to go away such that all new such users + * will observe it. + * + * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might + * not imply sync_sched(), so explicitly call both. + */ +#ifdef CONFIG_PREEMPT + synchronize_sched(); +#endif + synchronize_rcu(); + + /* + * So now all preempt/rcu users must observe !cpu_active(). + */ + err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { /* CPU didn't die: tell everyone. Can't complain. */