Commit de58ed5e authored by Gavin Shan's avatar Gavin Shan Committed by Catalin Marinas

arm64: Introduce get_cpu_ops() helper function

This introduces get_cpu_ops() to return the CPU operations according to
the given CPU index. For now, it simply returns the @cpu_ops[cpu] as
before. Also, helper function __cpu_try_die() is introduced to be shared
by cpu_die() and ipi_cpu_crash_stop(). So it shouldn't introduce any
functional changes.
Signed-off-by: default avatarGavin Shan <gshan@redhat.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
parent 6885fb12
...@@ -55,8 +55,8 @@ struct cpu_operations { ...@@ -55,8 +55,8 @@ struct cpu_operations {
#endif #endif
}; };
extern const struct cpu_operations *cpu_ops[NR_CPUS];
int __init init_cpu_ops(int cpu); int __init init_cpu_ops(int cpu);
extern const struct cpu_operations *get_cpu_ops(int cpu);
static inline void __init init_bootcpu_ops(void) static inline void __init init_bootcpu_ops(void)
{ {
......
...@@ -20,7 +20,7 @@ extern const struct cpu_operations acpi_parking_protocol_ops; ...@@ -20,7 +20,7 @@ extern const struct cpu_operations acpi_parking_protocol_ops;
#endif #endif
extern const struct cpu_operations cpu_psci_ops; extern const struct cpu_operations cpu_psci_ops;
const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init; static const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
static const struct cpu_operations *const dt_supported_cpu_ops[] __initconst = { static const struct cpu_operations *const dt_supported_cpu_ops[] __initconst = {
&smp_spin_table_ops, &smp_spin_table_ops,
...@@ -111,3 +111,8 @@ int __init init_cpu_ops(int cpu) ...@@ -111,3 +111,8 @@ int __init init_cpu_ops(int cpu)
return 0; return 0;
} }
const struct cpu_operations *get_cpu_ops(int cpu)
{
return cpu_ops[cpu];
}
...@@ -18,11 +18,11 @@ ...@@ -18,11 +18,11 @@
int arm_cpuidle_init(unsigned int cpu) int arm_cpuidle_init(unsigned int cpu)
{ {
const struct cpu_operations *ops = get_cpu_ops(cpu);
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_suspend && if (ops && ops->cpu_suspend && ops->cpu_init_idle)
cpu_ops[cpu]->cpu_init_idle) ret = ops->cpu_init_idle(cpu);
ret = cpu_ops[cpu]->cpu_init_idle(cpu);
return ret; return ret;
} }
...@@ -37,8 +37,9 @@ int arm_cpuidle_init(unsigned int cpu) ...@@ -37,8 +37,9 @@ int arm_cpuidle_init(unsigned int cpu)
int arm_cpuidle_suspend(int index) int arm_cpuidle_suspend(int index)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
const struct cpu_operations *ops = get_cpu_ops(cpu);
return cpu_ops[cpu]->cpu_suspend(index); return ops->cpu_suspend(index);
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -371,8 +371,10 @@ void __init setup_arch(char **cmdline_p) ...@@ -371,8 +371,10 @@ void __init setup_arch(char **cmdline_p)
static inline bool cpu_can_disable(unsigned int cpu) static inline bool cpu_can_disable(unsigned int cpu)
{ {
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_can_disable) const struct cpu_operations *ops = get_cpu_ops(cpu);
return cpu_ops[cpu]->cpu_can_disable(cpu);
if (ops && ops->cpu_can_disable)
return ops->cpu_can_disable(cpu);
#endif #endif
return false; return false;
} }
......
...@@ -93,8 +93,10 @@ static inline int op_cpu_kill(unsigned int cpu) ...@@ -93,8 +93,10 @@ static inline int op_cpu_kill(unsigned int cpu)
*/ */
static int boot_secondary(unsigned int cpu, struct task_struct *idle) static int boot_secondary(unsigned int cpu, struct task_struct *idle)
{ {
if (cpu_ops[cpu]->cpu_boot) const struct cpu_operations *ops = get_cpu_ops(cpu);
return cpu_ops[cpu]->cpu_boot(cpu);
if (ops->cpu_boot)
return ops->cpu_boot(cpu);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -196,6 +198,7 @@ asmlinkage notrace void secondary_start_kernel(void) ...@@ -196,6 +198,7 @@ asmlinkage notrace void secondary_start_kernel(void)
{ {
u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
struct mm_struct *mm = &init_mm; struct mm_struct *mm = &init_mm;
const struct cpu_operations *ops;
unsigned int cpu; unsigned int cpu;
cpu = task_cpu(current); cpu = task_cpu(current);
...@@ -227,8 +230,9 @@ asmlinkage notrace void secondary_start_kernel(void) ...@@ -227,8 +230,9 @@ asmlinkage notrace void secondary_start_kernel(void)
*/ */
check_local_cpu_capabilities(); check_local_cpu_capabilities();
if (cpu_ops[cpu]->cpu_postboot) ops = get_cpu_ops(cpu);
cpu_ops[cpu]->cpu_postboot(); if (ops->cpu_postboot)
ops->cpu_postboot();
/* /*
* Log the CPU info before it is marked online and might get read. * Log the CPU info before it is marked online and might get read.
...@@ -266,19 +270,21 @@ asmlinkage notrace void secondary_start_kernel(void) ...@@ -266,19 +270,21 @@ asmlinkage notrace void secondary_start_kernel(void)
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
static int op_cpu_disable(unsigned int cpu) static int op_cpu_disable(unsigned int cpu)
{ {
const struct cpu_operations *ops = get_cpu_ops(cpu);
/* /*
* If we don't have a cpu_die method, abort before we reach the point * 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. * of no return. CPU0 may not have an cpu_ops, so test for it.
*/ */
if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_die) if (!ops || !ops->cpu_die)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* /*
* We may need to abort a hot unplug for some other mechanism-specific * We may need to abort a hot unplug for some other mechanism-specific
* reason. * reason.
*/ */
if (cpu_ops[cpu]->cpu_disable) if (ops->cpu_disable)
return cpu_ops[cpu]->cpu_disable(cpu); return ops->cpu_disable(cpu);
return 0; return 0;
} }
...@@ -314,15 +320,17 @@ int __cpu_disable(void) ...@@ -314,15 +320,17 @@ int __cpu_disable(void)
static int op_cpu_kill(unsigned int cpu) static int op_cpu_kill(unsigned int cpu)
{ {
const struct cpu_operations *ops = get_cpu_ops(cpu);
/* /*
* If we have no means of synchronising with the dying CPU, then assume * If we have no means of synchronising with the dying CPU, then assume
* that it is really dead. We can only wait for an arbitrary length of * that it is really dead. We can only wait for an arbitrary length of
* time and hope that it's dead, so let's skip the wait and just hope. * time and hope that it's dead, so let's skip the wait and just hope.
*/ */
if (!cpu_ops[cpu]->cpu_kill) if (!ops->cpu_kill)
return 0; return 0;
return cpu_ops[cpu]->cpu_kill(cpu); return ops->cpu_kill(cpu);
} }
/* /*
...@@ -357,6 +365,7 @@ void __cpu_die(unsigned int cpu) ...@@ -357,6 +365,7 @@ void __cpu_die(unsigned int cpu)
void cpu_die(void) void cpu_die(void)
{ {
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
const struct cpu_operations *ops = get_cpu_ops(cpu);
idle_task_exit(); idle_task_exit();
...@@ -370,12 +379,22 @@ void cpu_die(void) ...@@ -370,12 +379,22 @@ void cpu_die(void)
* mechanism must perform all required cache maintenance to ensure that * mechanism must perform all required cache maintenance to ensure that
* no dirty lines are lost in the process of shutting down the CPU. * no dirty lines are lost in the process of shutting down the CPU.
*/ */
cpu_ops[cpu]->cpu_die(cpu); ops->cpu_die(cpu);
BUG(); BUG();
} }
#endif #endif
static void __cpu_try_die(int cpu)
{
#ifdef CONFIG_HOTPLUG_CPU
const struct cpu_operations *ops = get_cpu_ops(cpu);
if (ops && ops->cpu_die)
ops->cpu_die(cpu);
#endif
}
/* /*
* Kill the calling secondary CPU, early in bringup before it is turned * Kill the calling secondary CPU, early in bringup before it is turned
* online. * online.
...@@ -389,12 +408,11 @@ void cpu_die_early(void) ...@@ -389,12 +408,11 @@ void cpu_die_early(void)
/* Mark this CPU absent */ /* Mark this CPU absent */
set_cpu_present(cpu, 0); set_cpu_present(cpu, 0);
#ifdef CONFIG_HOTPLUG_CPU if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
update_cpu_boot_status(CPU_KILL_ME); update_cpu_boot_status(CPU_KILL_ME);
/* Check if we can park ourselves */ __cpu_try_die(cpu);
if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_die) }
cpu_ops[cpu]->cpu_die(cpu);
#endif
update_cpu_boot_status(CPU_STUCK_IN_KERNEL); update_cpu_boot_status(CPU_STUCK_IN_KERNEL);
cpu_park_loop(); cpu_park_loop();
...@@ -488,10 +506,13 @@ static bool __init is_mpidr_duplicate(unsigned int cpu, u64 hwid) ...@@ -488,10 +506,13 @@ static bool __init is_mpidr_duplicate(unsigned int cpu, u64 hwid)
*/ */
static int __init smp_cpu_setup(int cpu) static int __init smp_cpu_setup(int cpu)
{ {
const struct cpu_operations *ops;
if (init_cpu_ops(cpu)) if (init_cpu_ops(cpu))
return -ENODEV; return -ENODEV;
if (cpu_ops[cpu]->cpu_init(cpu)) ops = get_cpu_ops(cpu);
if (ops->cpu_init(cpu))
return -ENODEV; return -ENODEV;
set_cpu_possible(cpu, true); set_cpu_possible(cpu, true);
...@@ -714,6 +735,7 @@ void __init smp_init_cpus(void) ...@@ -714,6 +735,7 @@ void __init smp_init_cpus(void)
void __init smp_prepare_cpus(unsigned int max_cpus) void __init smp_prepare_cpus(unsigned int max_cpus)
{ {
const struct cpu_operations *ops;
int err; int err;
unsigned int cpu; unsigned int cpu;
unsigned int this_cpu; unsigned int this_cpu;
...@@ -744,10 +766,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -744,10 +766,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (cpu == smp_processor_id()) if (cpu == smp_processor_id())
continue; continue;
if (!cpu_ops[cpu]) ops = get_cpu_ops(cpu);
if (!ops)
continue; continue;
err = cpu_ops[cpu]->cpu_prepare(cpu); err = ops->cpu_prepare(cpu);
if (err) if (err)
continue; continue;
...@@ -863,10 +886,8 @@ static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) ...@@ -863,10 +886,8 @@ static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
local_irq_disable(); local_irq_disable();
sdei_mask_local_cpu(); sdei_mask_local_cpu();
#ifdef CONFIG_HOTPLUG_CPU if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
if (cpu_ops[cpu]->cpu_die) __cpu_try_die(cpu);
cpu_ops[cpu]->cpu_die(cpu);
#endif
/* just in case */ /* just in case */
cpu_park_loop(); cpu_park_loop();
...@@ -1044,8 +1065,9 @@ static bool have_cpu_die(void) ...@@ -1044,8 +1065,9 @@ static bool have_cpu_die(void)
{ {
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
int any_cpu = raw_smp_processor_id(); int any_cpu = raw_smp_processor_id();
const struct cpu_operations *ops = get_cpu_ops(any_cpu);
if (cpu_ops[any_cpu] && cpu_ops[any_cpu]->cpu_die) if (ops && ops->cpu_die)
return true; return true;
#endif #endif
return false; return false;
......
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