summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
authorMahesh Sivasubramanian <msivasub@codeaurora.org>2014-09-18 20:33:55 -0600
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:16:19 -0700
commitd0aebd3840defccb664c1628970be6c00957166a (patch)
tree31cf7f6a854432d9c9b935ac3ada44b51193cbbb /arch/arm64/kernel
parentee5580ee55c8e787a227076c8c6bbc77f63aa8cf (diff)
ARM64: smp: Prevent cluster LPM modes when pending IPIs on cluster CPUs
LPM modes can fail if there is a pending IPI interrupt at GIC CPU interface. On some usecases frequent failure of LPM modes can cause power and performance degradation. Hence, prevent cluster low power modes when there is a pending IPI on cluster CPUs. Change-Id: Id8a0ac24e4867ef824e0a6f11d989f1e1a2b0e93 Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org> Signed-off-by: Murali Nalajala <mnalajal@codeaurora.org> [satyap: trivial merge conflict resolution] Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/smp.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 6afe10641a93..08e78e47be95 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -484,6 +484,16 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
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
* cpu logical map array containing MPIDR values related to logical
@@ -683,17 +693,17 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
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);
+ smp_cross_call_common(cpumask_of(cpu), 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);
}
#ifdef CONFIG_IRQ_WORK
@@ -759,7 +769,7 @@ static void smp_send_all_cpu_backtrace(void)
pr_info("\nsending IPI to all other CPUs:\n");
if (!cpumask_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++) {
@@ -867,13 +877,13 @@ void handle_IPI(int ipinr, struct pt_regs *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
@@ -887,7 +897,7 @@ void smp_send_stop(void)
cpumask_copy(&mask, cpu_online_mask);
cpumask_clear_cpu(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 */