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:07:25 -0700
commit76fb22e96d7f50b6d29851a81214e7d66043167a (patch)
treec7cdd4f147d16255ab0da9397fa772094eb0464c /arch/arm64/kernel
parent75765be3fe4ba52391f0c4f685b12573328487a6 (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> Conflicts: arch/arm/kernel/smp.c arch/arm64/kernel/smp.c
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/smp.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 91d673a05d03..60946e1c30cf 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -469,6 +469,8 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
#else
#define acpi_table_parse_madt(...) do { } while (0)
#endif
+void (*__smp_cross_call)(const struct cpumask *, unsigned int);
+DEFINE_PER_CPU(bool, pending_ipi);
/*
* Enumerate the possible CPU set from the device tree and build the
@@ -615,8 +617,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
-void (*__smp_cross_call)(const struct cpumask *, unsigned int);
-
void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
{
__smp_cross_call = fn;
@@ -633,6 +633,11 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
{
+ unsigned int cpu;
+
+ for_each_cpu(cpu, target)
+ per_cpu(pending_ipi, cpu) = true;
+
trace_ipi_raise(target, ipi_types[ipinr]);
__smp_cross_call(target, ipinr);
}
@@ -760,6 +765,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
if ((unsigned)ipinr < NR_IPI)
trace_ipi_exit_rcuidle(ipi_types[ipinr]);
+
+ per_cpu(pending_ipi, cpu) = false;
set_irq_regs(old_regs);
}