arm64: add CPU_HOTPLUG infrastructure
This patch adds the basic infrastructure necessary to support CPU_HOTPLUG on arm64, based on the arm implementation. Actual hotplug support will depend on an implementation's cpu_operations (e.g. PSCI). Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:

committed by
Catalin Marinas

parent
e8765b265a
commit
9327e2c6bb
@@ -167,6 +167,102 @@ asmlinkage void secondary_start_kernel(void)
|
||||
cpu_startup_entry(CPUHP_ONLINE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static int op_cpu_disable(unsigned int cpu)
|
||||
{
|
||||
/*
|
||||
* If we don't have a cpu_die method, abort before we reach the point
|
||||
* of no return. CPU0 may not have an cpu_ops, so test for it.
|
||||
*/
|
||||
if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_die)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* We may need to abort a hot unplug for some other mechanism-specific
|
||||
* reason.
|
||||
*/
|
||||
if (cpu_ops[cpu]->cpu_disable)
|
||||
return cpu_ops[cpu]->cpu_disable(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __cpu_disable runs on the processor to be shutdown.
|
||||
*/
|
||||
int __cpu_disable(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int ret;
|
||||
|
||||
ret = op_cpu_disable(cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Take this CPU offline. Once we clear this, we can't return,
|
||||
* and we must not schedule until we're ready to give up the cpu.
|
||||
*/
|
||||
set_cpu_online(cpu, false);
|
||||
|
||||
/*
|
||||
* OK - migrate IRQs away from this CPU
|
||||
*/
|
||||
migrate_irqs();
|
||||
|
||||
/*
|
||||
* Remove this CPU from the vm mask set of all processes.
|
||||
*/
|
||||
clear_tasks_mm_cpumask(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DECLARE_COMPLETION(cpu_died);
|
||||
|
||||
/*
|
||||
* called on the thread which is asking for a CPU to be shutdown -
|
||||
* waits until shutdown has completed, or it is timed out.
|
||||
*/
|
||||
void __cpu_die(unsigned int cpu)
|
||||
{
|
||||
if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
|
||||
pr_crit("CPU%u: cpu didn't die\n", cpu);
|
||||
return;
|
||||
}
|
||||
pr_notice("CPU%u: shutdown\n", cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from the idle thread for the CPU which has been shutdown.
|
||||
*
|
||||
* Note that we disable IRQs here, but do not re-enable them
|
||||
* before returning to the caller. This is also the behaviour
|
||||
* of the other hotplug-cpu capable cores, so presumably coming
|
||||
* out of idle fixes this.
|
||||
*/
|
||||
void cpu_die(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
idle_task_exit();
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
/* Tell __cpu_die() that this CPU is now safe to dispose of */
|
||||
complete(&cpu_died);
|
||||
|
||||
/*
|
||||
* Actually shutdown the CPU. This must never fail. The specific hotplug
|
||||
* mechanism must perform all required cache maintenance to ensure that
|
||||
* no dirty lines are lost in the process of shutting down the CPU.
|
||||
*/
|
||||
cpu_ops[cpu]->cpu_die(cpu);
|
||||
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init smp_cpus_done(unsigned int max_cpus)
|
||||
{
|
||||
pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
|
||||
|
Reference in New Issue
Block a user