Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a1d0037 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM64: smp: Prevent cluster LPM modes when pending IPIs on cluster CPUs"

parents ed0032ba 50711f8b
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -434,6 +434,18 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}

static void (*smp_cross_call)(const struct cpumask *, unsigned int);
DEFINE_PER_CPU(bool, pending_ipi);

static void smp_cross_call_common(const struct cpumask *cpumask,
						unsigned int func)
{
	unsigned int cpu;

	for_each_cpu(cpu, cpumask)
		per_cpu(pending_ipi, cpu) = true;

	smp_cross_call(cpumask, func);
}

void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
{
@@ -443,17 +455,17 @@ void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))

void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_CALL_FUNC);
	smp_cross_call_common(mask, IPI_CALL_FUNC);
}

void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_WAKEUP);
	smp_cross_call_common(mask, IPI_WAKEUP);
}

void arch_send_call_function_single_ipi(int cpu)
{
	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
	smp_cross_call_common(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
}

static const char *ipi_types[NR_IPI] = {
@@ -501,7 +513,7 @@ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
void tick_broadcast(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_TIMER);
	smp_cross_call_common(mask, IPI_TIMER);
}
#endif

@@ -620,7 +632,7 @@ void smp_send_all_cpu_backtrace(void)

	pr_info("\nsending IPI to all other CPUs:\n");
	if (!cpus_empty(backtrace_mask))
		smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE);
		smp_cross_call_common(&backtrace_mask, IPI_CPU_BACKTRACE);

	/* Wait for up to 10 seconds for all other CPUs to do the backtrace */
	for (i = 0; i < 10 * 1000; i++) {
@@ -706,13 +718,15 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
		       cpu, ipinr);
		break;
	}
	per_cpu(pending_ipi, cpu) = false;

	set_irq_regs(old_regs);
}

void smp_send_reschedule(int cpu)
{
	BUG_ON(cpu_is_offline(cpu));
	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
	smp_cross_call_common(cpumask_of(cpu), IPI_RESCHEDULE);
}

void smp_send_stop(void)
@@ -723,7 +737,7 @@ void smp_send_stop(void)
	cpumask_copy(&mask, cpu_online_mask);
	cpumask_clear_cpu(smp_processor_id(), &mask);
	if (!cpumask_empty(&mask))
		smp_cross_call(&mask, IPI_CPU_STOP);
		smp_cross_call_common(&mask, IPI_CPU_STOP);

	/* Wait up to one second for other CPUs to stop */
	timeout = USEC_PER_SEC;
+20 −7
Original line number Diff line number Diff line
@@ -321,6 +321,18 @@ void __init smp_prepare_boot_cpu(void)
}

static void (*smp_cross_call)(const struct cpumask *, unsigned int);
DEFINE_PER_CPU(bool, pending_ipi);

void smp_cross_call_common(const struct cpumask *cpumask, unsigned int func)
{
	unsigned int cpu;

	for_each_cpu(cpu, cpumask)
		per_cpu(pending_ipi, cpu) = true;

	smp_cross_call(cpumask, func);
}


/*
 * Enumerate the possible CPU set from the device tree and build the
@@ -483,17 +495,17 @@ void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))

void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_CALL_FUNC);
	smp_cross_call_common(mask, IPI_CALL_FUNC);
}

void arch_send_call_function_single_ipi(int cpu)
{
	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
	smp_cross_call_common(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
}

void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_WAKEUP);
	smp_cross_call_common(mask, IPI_WAKEUP);
}

#ifdef CONFIG_IRQ_WORK
@@ -596,7 +608,7 @@ static void smp_send_all_cpu_backtrace(void)

	pr_info("\nsending IPI to all other CPUs:\n");
	if (!cpus_empty(backtrace_mask))
		smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE);
		smp_cross_call_common(&backtrace_mask, IPI_CPU_BACKTRACE);

	/* Wait for up to 10 seconds for all other CPUs to do the backtrace */
	for (i = 0; i < 10 * 1000; i++) {
@@ -696,19 +708,20 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
		pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
		break;
	}
	per_cpu(pending_ipi, cpu) = false;
	set_irq_regs(old_regs);
}

void smp_send_reschedule(int cpu)
{
	BUG_ON(cpu_is_offline(cpu));
	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
	smp_cross_call_common(cpumask_of(cpu), IPI_RESCHEDULE);
}

#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
void tick_broadcast(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_TIMER);
	smp_cross_call_common(mask, IPI_TIMER);
}
#endif

@@ -722,7 +735,7 @@ void smp_send_stop(void)
		cpumask_copy(&mask, cpu_online_mask);
		cpu_clear(smp_processor_id(), mask);

		smp_cross_call(&mask, IPI_CPU_STOP);
		smp_cross_call_common(&mask, IPI_CPU_STOP);
	}

	/* Wait up to one second for other CPUs to stop */
+2 −2
Original line number Diff line number Diff line
@@ -447,8 +447,8 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx,

	spin_lock(&cluster->sync_lock);

	if (!cpumask_equal(&cluster->num_childs_in_sync,
					&cluster->child_cpus)) {
	if (!cpumask_equal(&cluster->num_childs_in_sync, &cluster->child_cpus)
			|| is_IPI_pending(&cluster->num_childs_in_sync)) {
		spin_unlock(&cluster->sync_lock);
		return -EPERM;
	}
+19 −0
Original line number Diff line number Diff line
@@ -103,3 +103,22 @@ bool lpm_cluster_mode_allow(struct lpm_cluster *cluster,
		unsigned int mode, bool from_idle);

extern struct lpm_cluster *lpm_root_node;

#ifdef CONFIG_SMP
extern DEFINE_PER_CPU(bool, pending_ipi);
static inline bool is_IPI_pending(const struct cpumask *mask)
{
	unsigned int cpu;

	for_each_cpu(cpu, mask) {
		if per_cpu(pending_ipi, cpu)
			return true;
	}
	return false;
}
#else
static inline bool is_IPI_pending(const struct cpumask *mask)
{
	return false;
}
#endif