cpufreq: update timer notifiers
PATCH 1/1 cpufreq: update timer notifiers
- The global loops_per_jiffy can only be safely adjusted on UP.
- x86 per-CPU loops_per_jiffy is not dependend of TSC, so move it to non-TSC code.
- Save reference values so that rounding errors do not accumulate
arch/i386/kernel/cpu/common.c +47 -0
@@ -1,5 +1,7 @@#include <linux/init.h> #include <linux/string.h> +#include <linux/cpufreq.h> +#include <linux/notifier.h> #include <linux/delay.h> #include <linux/smp.h> #include <asm/semaphore.h>
@@ -45,6 +47,41 @@ }__setup ("cachesize=" , cachesize_setup); +#ifdef CONFIG_CPU_FREQ +static unsigned long loops_per_jiffy_ref =0 ; +static unsigned int ref_freq =0 ; + +static int +loops_per_jiffy_cpufreq_notifier (struct notifier_block *nb,unsigned long val, +void *data) +{ +struct cpufreq_freqs *freq = data; + +if (!loops_per_jiffy_ref) { + loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; + ref_freq = freq->old; + } + +switch (val) { +case CPUFREQ_PRECHANGE : +if (freq->old < freq->new) + cpu_data[freq->cpu].loops_per_jiffy =cpufreq_scale (loops_per_jiffy_ref, ref_freq, freq->new); +break ; +case CPUFREQ_POSTCHANGE : +if (freq->new < freq->old) + cpu_data[freq->cpu].loops_per_jiffy =cpufreq_scale (loops_per_jiffy_ref, ref_freq, freq->new); +break ; + } + +return 0 ; +} + +static struct notifier_block loops_per_jiffy_cpufreq_notifier_block = { + .notifier_call = loops_per_jiffy_cpufreq_notifier +}; +#endif + +int __init get_model_name (struct cpuinfo_x86 *c) {unsigned int *v;
@@ -354,6 +391,16 @@ boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } +/* +* Update the per-CPU loops_per_jiffy count on CPU frequency +* transitions +*/ +#ifdef CONFIG_CPU_FREQ +if (c == &boot_cpu_data) { +cpufreq_register_notifier (&loops_per_jiffy_cpufreq_notifier_block,CPUFREQ_TRANSITION_NOTIFIER ); + } +#endif +/* Init Machine Check Exception if available. */ #ifdef CONFIG_X86_MCE mcheck_init (c);
arch/i386/kernel/timers/timer_tsc.c +23 -23
78 lines not on this page · raw message
kernel/cpufreq.c +15 -5
@@ -927,17 +927,27 @@* adjust_jiffies - adjust the system "loops_per_jiffy" * * This function alters the system "loops_per_jiffy" for the clock -* speed change. Note that loops_per_jiffy is only updated if all -* CPUs are affected - else there is a need for per-CPU loops_per_jiffy -* values which are provided by various architectures. +* speed change. Note that loops_per_jiffy cannot be updated on SMP +* systems as each CPU might be scaled differently. So, use the arch +* per-CPU loops_per_jiffy value wherever possible. */ +#ifndef CONFIG_SMP +static unsigned long l_p_j_ref =0 ; +static unsigned int l_p_j_ref_freq =0 ; +static inline void adjust_jiffies (unsigned long val,struct cpufreq_freqs *ci) { +if (!l_p_j_ref_freq) { + l_p_j_ref = loops_per_jiffy; + l_p_j_ref_freq = ci->old; + }if ((val ==CPUFREQ_PRECHANGE && ci->old < ci->new) || (val ==CPUFREQ_POSTCHANGE && ci->old > ci->new)) -if (ci->cpu ==CPUFREQ_ALL_CPUS ) - loops_per_jiffy =cpufreq_scale (loops_per_jiffy, ci->old, ci->new); + loops_per_jiffy =cpufreq_scale (l_p_j_ref, l_p_j_ref_freq, ci->new); } +#else +#define adjust_jiffies (...) +#endif /**