powerpc/smp: More generic support for "soft hotplug"

This adds more generic support for doing CPU hotplug with a simple
idle loop and no actual reset of the processors. The generic
smp_generic_kick_cpu() does the hotplug bringup trick if the PACA
shows that the CPU has already been started at boot and we provide
an accessor for the CPU state.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent b8bb922c
...@@ -65,6 +65,7 @@ int generic_cpu_disable(void); ...@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
void generic_cpu_die(unsigned int cpu); void generic_cpu_die(unsigned int cpu);
void generic_mach_cpu_die(void); void generic_mach_cpu_die(void);
void generic_set_cpu_dead(unsigned int cpu); void generic_set_cpu_dead(unsigned int cpu);
int generic_check_cpu_restart(unsigned int cpu);
#endif #endif
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
......
...@@ -70,6 +70,10 @@ ...@@ -70,6 +70,10 @@
static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))
/* State of each CPU during hotplug phases */
static DEFINE_PER_CPU(int, cpu_state) = { 0 };
#else #else
static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
#define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define get_idle_for_cpu(x) (idle_thread_array[(x)])
...@@ -104,12 +108,25 @@ int __devinit smp_generic_kick_cpu(int nr) ...@@ -104,12 +108,25 @@ int __devinit smp_generic_kick_cpu(int nr)
* cpu_start field to become non-zero After we set cpu_start, * cpu_start field to become non-zero After we set cpu_start,
* the processor will continue on to secondary_start * the processor will continue on to secondary_start
*/ */
paca[nr].cpu_start = 1; if (!paca[nr].cpu_start) {
smp_mb(); paca[nr].cpu_start = 1;
smp_mb();
return 0;
}
#ifdef CONFIG_HOTPLUG_CPU
/*
* Ok it's not there, so it might be soft-unplugged, let's
* try to bring it back
*/
per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
smp_wmb();
smp_send_reschedule(nr);
#endif /* CONFIG_HOTPLUG_CPU */
return 0; return 0;
} }
#endif #endif /* CONFIG_PPC64 */
static irqreturn_t call_function_action(int irq, void *data) static irqreturn_t call_function_action(int irq, void *data)
{ {
...@@ -357,8 +374,6 @@ void __devinit smp_prepare_boot_cpu(void) ...@@ -357,8 +374,6 @@ void __devinit smp_prepare_boot_cpu(void)
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
/* State of each CPU during hotplug phases */
static DEFINE_PER_CPU(int, cpu_state) = { 0 };
int generic_cpu_disable(void) int generic_cpu_disable(void)
{ {
...@@ -406,6 +421,11 @@ void generic_set_cpu_dead(unsigned int cpu) ...@@ -406,6 +421,11 @@ void generic_set_cpu_dead(unsigned int cpu)
{ {
per_cpu(cpu_state, cpu) = CPU_DEAD; per_cpu(cpu_state, cpu) = CPU_DEAD;
} }
int generic_check_cpu_restart(unsigned int cpu)
{
return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
}
#endif #endif
struct create_idle { struct create_idle {
......
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