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: Gavin Shan <gshan@redhat.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Mark Rutland <mark.rutland@arm.com>
This commit is contained in:
parent
6885fb129b
commit
de58ed5e16
@ -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;
|
|||||||
#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)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct cpu_operations *get_cpu_ops(int cpu)
|
||||||
|
{
|
||||||
|
return cpu_ops[cpu];
|
||||||
|
}
|
||||||
|
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
#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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
/* 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
#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;
|
||||||
|
Loading…
Reference in New Issue
Block a user