Commit e69aab13 authored by Thomas Gleixner's avatar Thomas Gleixner

cpu/hotplug: Make wait for dead cpu completion based

Kill the busy spinning on the control side and just wait for the hotplugged
cpu to tell that it reached the dead state.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Rik van Riel <riel@redhat.com>
Cc: Rafael Wysocki <rafael.j.wysocki@intel.com>
Cc: "Srivatsa S. Bhat" <srivatsa@mit.edu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul Turner <pjt@google.com>
Link: http://lkml.kernel.org/r/20160226182341.776157858@linutronix.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 8df3e07e
...@@ -276,14 +276,15 @@ void arch_cpu_idle_enter(void); ...@@ -276,14 +276,15 @@ void arch_cpu_idle_enter(void);
void arch_cpu_idle_exit(void); void arch_cpu_idle_exit(void);
void arch_cpu_idle_dead(void); void arch_cpu_idle_dead(void);
DECLARE_PER_CPU(bool, cpu_dead_idle);
int cpu_report_state(int cpu); int cpu_report_state(int cpu);
int cpu_check_up_prepare(int cpu); int cpu_check_up_prepare(int cpu);
void cpu_set_state_online(int cpu); void cpu_set_state_online(int cpu);
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
bool cpu_wait_death(unsigned int cpu, int seconds); bool cpu_wait_death(unsigned int cpu, int seconds);
bool cpu_report_death(void); bool cpu_report_death(void);
void cpuhp_report_idle_dead(void);
#else
static inline void cpuhp_report_idle_dead(void) { }
#endif /* #ifdef CONFIG_HOTPLUG_CPU */ #endif /* #ifdef CONFIG_HOTPLUG_CPU */
#endif /* _LINUX_CPU_H_ */ #endif /* _LINUX_CPU_H_ */
...@@ -6,6 +6,7 @@ enum cpuhp_state { ...@@ -6,6 +6,7 @@ enum cpuhp_state {
CPUHP_CREATE_THREADS, CPUHP_CREATE_THREADS,
CPUHP_NOTIFY_PREPARE, CPUHP_NOTIFY_PREPARE,
CPUHP_BRINGUP_CPU, CPUHP_BRINGUP_CPU,
CPUHP_AP_IDLE_DEAD,
CPUHP_AP_OFFLINE, CPUHP_AP_OFFLINE,
CPUHP_AP_NOTIFY_STARTING, CPUHP_AP_NOTIFY_STARTING,
CPUHP_AP_ONLINE, CPUHP_AP_ONLINE,
......
...@@ -688,6 +688,7 @@ static int take_cpu_down(void *_param) ...@@ -688,6 +688,7 @@ static int take_cpu_down(void *_param)
static int takedown_cpu(unsigned int cpu) static int takedown_cpu(unsigned int cpu)
{ {
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
int err; int err;
/* /*
...@@ -733,10 +734,8 @@ static int takedown_cpu(unsigned int cpu) ...@@ -733,10 +734,8 @@ static int takedown_cpu(unsigned int cpu)
* *
* Wait for the stop thread to go away. * Wait for the stop thread to go away.
*/ */
while (!per_cpu(cpu_dead_idle, cpu)) wait_for_completion(&st->done);
cpu_relax(); BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
per_cpu(cpu_dead_idle, cpu) = false;
/* Interrupts are moved away from the dying cpu, reenable alloc/free */ /* Interrupts are moved away from the dying cpu, reenable alloc/free */
irq_unlock_sparse(); irq_unlock_sparse();
...@@ -756,6 +755,15 @@ static int notify_dead(unsigned int cpu) ...@@ -756,6 +755,15 @@ static int notify_dead(unsigned int cpu)
return 0; return 0;
} }
void cpuhp_report_idle_dead(void)
{
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
BUG_ON(st->state != CPUHP_AP_OFFLINE);
st->state = CPUHP_AP_IDLE_DEAD;
complete(&st->done);
}
#else #else
#define notify_down_prepare NULL #define notify_down_prepare NULL
#define takedown_cpu NULL #define takedown_cpu NULL
......
...@@ -194,8 +194,6 @@ static void cpuidle_idle_call(void) ...@@ -194,8 +194,6 @@ static void cpuidle_idle_call(void)
rcu_idle_exit(); rcu_idle_exit();
} }
DEFINE_PER_CPU(bool, cpu_dead_idle);
/* /*
* Generic idle loop implementation * Generic idle loop implementation
* *
...@@ -224,8 +222,7 @@ static void cpu_idle_loop(void) ...@@ -224,8 +222,7 @@ static void cpu_idle_loop(void)
if (cpu_is_offline(smp_processor_id())) { if (cpu_is_offline(smp_processor_id())) {
rcu_cpu_notify(NULL, CPU_DYING_IDLE, rcu_cpu_notify(NULL, CPU_DYING_IDLE,
(void *)(long)smp_processor_id()); (void *)(long)smp_processor_id());
smp_mb(); /* all activity before dead. */ cpuhp_report_idle_dead();
this_cpu_write(cpu_dead_idle, true);
arch_cpu_idle_dead(); arch_cpu_idle_dead();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment