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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
@@ -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 @@
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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)
|
|||||||
{
|
{
|
||||||
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 {
|
||||||
|
Reference in New Issue
Block a user