aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRichard Zhao <richard.zhao@linaro.org>2012-09-04 19:08:59 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-09 16:06:33 -0400
commitec971ea5f2426a0bf9d5cca9a103743918c12978 (patch)
tree58594e18af78718548dea595c26e1a67d964a29e /arch
parente1f0b8e9b04a262834ed111e605e5d215685dfab (diff)
ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp
If CONFIG_SMP, cpufreq skips loops_per_jiffy update, because different arch has different per-cpu loops_per_jiffy definition. Signed-off-by: Richard Zhao <richard.zhao@linaro.org> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/smp.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ebd8ad274d7..8e03567c958 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -25,6 +25,7 @@
25#include <linux/percpu.h> 25#include <linux/percpu.h>
26#include <linux/clockchips.h> 26#include <linux/clockchips.h>
27#include <linux/completion.h> 27#include <linux/completion.h>
28#include <linux/cpufreq.h>
28 29
29#include <linux/atomic.h> 30#include <linux/atomic.h>
30#include <asm/cacheflush.h> 31#include <asm/cacheflush.h>
@@ -584,3 +585,56 @@ int setup_profiling_timer(unsigned int multiplier)
584{ 585{
585 return -EINVAL; 586 return -EINVAL;
586} 587}
588
589#ifdef CONFIG_CPU_FREQ
590
591static DEFINE_PER_CPU(unsigned long, l_p_j_ref);
592static DEFINE_PER_CPU(unsigned long, l_p_j_ref_freq);
593static unsigned long global_l_p_j_ref;
594static unsigned long global_l_p_j_ref_freq;
595
596static int cpufreq_callback(struct notifier_block *nb,
597 unsigned long val, void *data)
598{
599 struct cpufreq_freqs *freq = data;
600 int cpu = freq->cpu;
601
602 if (freq->flags & CPUFREQ_CONST_LOOPS)
603 return NOTIFY_OK;
604
605 if (!per_cpu(l_p_j_ref, cpu)) {
606 per_cpu(l_p_j_ref, cpu) =
607 per_cpu(cpu_data, cpu).loops_per_jiffy;
608 per_cpu(l_p_j_ref_freq, cpu) = freq->old;
609 if (!global_l_p_j_ref) {
610 global_l_p_j_ref = loops_per_jiffy;
611 global_l_p_j_ref_freq = freq->old;
612 }
613 }
614
615 if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
616 (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
617 (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
618 loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
619 global_l_p_j_ref_freq,
620 freq->new);
621 per_cpu(cpu_data, cpu).loops_per_jiffy =
622 cpufreq_scale(per_cpu(l_p_j_ref, cpu),
623 per_cpu(l_p_j_ref_freq, cpu),
624 freq->new);
625 }
626 return NOTIFY_OK;
627}
628
629static struct notifier_block cpufreq_notifier = {
630 .notifier_call = cpufreq_callback,
631};
632
633static int __init register_cpufreq_notifier(void)
634{
635 return cpufreq_register_notifier(&cpufreq_notifier,
636 CPUFREQ_TRANSITION_NOTIFIER);
637}
638core_initcall(register_cpufreq_notifier);
639
640#endif