diff options
| author | Mahesh Sivasubramanian <msivasub@codeaurora.org> | 2014-09-18 20:33:55 -0600 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:07:25 -0700 |
| commit | 76fb22e96d7f50b6d29851a81214e7d66043167a (patch) | |
| tree | c7cdd4f147d16255ab0da9397fa772094eb0464c /arch/arm64/kernel | |
| parent | 75765be3fe4ba52391f0c4f685b12573328487a6 (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.c | 11 |
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); } |
