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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -55,8 +55,8 @@ struct cpu_operations {
#endif
};

extern const struct cpu_operations *cpu_ops[NR_CPUS];
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)
{
+6 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ extern const struct cpu_operations acpi_parking_protocol_ops;
#endif
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 = {
	&smp_spin_table_ops,
@@ -111,3 +111,8 @@ int __init init_cpu_ops(int cpu)

	return 0;
}

const struct cpu_operations *get_cpu_ops(int cpu)
{
	return cpu_ops[cpu];
}
+5 −4
Original line number Diff line number Diff line
@@ -18,11 +18,11 @@

int arm_cpuidle_init(unsigned int cpu)
{
	const struct cpu_operations *ops = get_cpu_ops(cpu);
	int ret = -EOPNOTSUPP;

	if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_suspend &&
			cpu_ops[cpu]->cpu_init_idle)
		ret = cpu_ops[cpu]->cpu_init_idle(cpu);
	if (ops && ops->cpu_suspend && ops->cpu_init_idle)
		ret = ops->cpu_init_idle(cpu);

	return ret;
}
@@ -37,8 +37,9 @@ int arm_cpuidle_init(unsigned int cpu)
int arm_cpuidle_suspend(int index)
{
	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
+4 −2
Original line number Diff line number Diff line
@@ -371,8 +371,10 @@ void __init setup_arch(char **cmdline_p)
static inline bool cpu_can_disable(unsigned int cpu)
{
#ifdef CONFIG_HOTPLUG_CPU
	if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_can_disable)
		return cpu_ops[cpu]->cpu_can_disable(cpu);
	const struct cpu_operations *ops = get_cpu_ops(cpu);

	if (ops && ops->cpu_can_disable)
		return ops->cpu_can_disable(cpu);
#endif
	return false;
}
+46 −24
Original line number Diff line number Diff line
@@ -93,8 +93,10 @@ static inline int op_cpu_kill(unsigned int cpu)
 */
static int boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	if (cpu_ops[cpu]->cpu_boot)
		return cpu_ops[cpu]->cpu_boot(cpu);
	const struct cpu_operations *ops = get_cpu_ops(cpu);

	if (ops->cpu_boot)
		return ops->cpu_boot(cpu);

	return -EOPNOTSUPP;
}
@@ -196,6 +198,7 @@ asmlinkage notrace void secondary_start_kernel(void)
{
	u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
	struct mm_struct *mm = &init_mm;
	const struct cpu_operations *ops;
	unsigned int cpu;

	cpu = task_cpu(current);
@@ -227,8 +230,9 @@ asmlinkage notrace void secondary_start_kernel(void)
	 */
	check_local_cpu_capabilities();

	if (cpu_ops[cpu]->cpu_postboot)
		cpu_ops[cpu]->cpu_postboot();
	ops = get_cpu_ops(cpu);
	if (ops->cpu_postboot)
		ops->cpu_postboot();

	/*
	 * 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
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
	 * 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;

	/*
	 * 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);
	if (ops->cpu_disable)
		return ops->cpu_disable(cpu);

	return 0;
}
@@ -314,15 +320,17 @@ int __cpu_disable(void)

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
	 * 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.
	 */
	if (!cpu_ops[cpu]->cpu_kill)
	if (!ops->cpu_kill)
		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)
{
	unsigned int cpu = smp_processor_id();
	const struct cpu_operations *ops = get_cpu_ops(cpu);

	idle_task_exit();

@@ -370,12 +379,22 @@ void cpu_die(void)
	 * 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);
	ops->cpu_die(cpu);

	BUG();
}
#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
 * online.
@@ -389,12 +408,11 @@ void cpu_die_early(void)
	/* Mark this CPU absent */
	set_cpu_present(cpu, 0);

#ifdef CONFIG_HOTPLUG_CPU
	if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
		update_cpu_boot_status(CPU_KILL_ME);
	/* Check if we can park ourselves */
	if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_die)
		cpu_ops[cpu]->cpu_die(cpu);
#endif
		__cpu_try_die(cpu);
	}

	update_cpu_boot_status(CPU_STUCK_IN_KERNEL);

	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)
{
	const struct cpu_operations *ops;

	if (init_cpu_ops(cpu))
		return -ENODEV;

	if (cpu_ops[cpu]->cpu_init(cpu))
	ops = get_cpu_ops(cpu);
	if (ops->cpu_init(cpu))
		return -ENODEV;

	set_cpu_possible(cpu, true);
@@ -714,6 +735,7 @@ void __init smp_init_cpus(void)

void __init smp_prepare_cpus(unsigned int max_cpus)
{
	const struct cpu_operations *ops;
	int err;
	unsigned int cpu;
	unsigned int this_cpu;
@@ -744,10 +766,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
		if (cpu == smp_processor_id())
			continue;

		if (!cpu_ops[cpu])
		ops = get_cpu_ops(cpu);
		if (!ops)
			continue;

		err = cpu_ops[cpu]->cpu_prepare(cpu);
		err = ops->cpu_prepare(cpu);
		if (err)
			continue;

@@ -863,10 +886,8 @@ static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
	local_irq_disable();
	sdei_mask_local_cpu();

#ifdef CONFIG_HOTPLUG_CPU
	if (cpu_ops[cpu]->cpu_die)
		cpu_ops[cpu]->cpu_die(cpu);
#endif
	if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
		__cpu_try_die(cpu);

	/* just in case */
	cpu_park_loop();
@@ -1044,8 +1065,9 @@ static bool have_cpu_die(void)
{
#ifdef CONFIG_HOTPLUG_CPU
	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;
#endif
	return false;