cpufreq: x86 per-CPU loops_per_jiffy notifier
PATCH 1/1 cpufreq: x86 per-CPU loops_per_jiffy notifier
The per-CPU loops_per_jiffy value should be adjusted on frequency transitions. To get rid of accumulating rounding errors, some reference values are stored.
Dominik
arch/i386/kernel/cpu/common.c +40 -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>
@@ -61,6 +63,41 @@#endif __setup ("notsc" , tsc_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;
@@ -350,6 +387,9 @@for ( i =0 ; i <NCAPINTS ; i++ ) boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } +if (c == &boot_cpu_data) { +cpufreq_register_notifier (&loops_per_jiffy_cpufreq_notifier_block,CPUFREQ_TRANSITION_NOTIFIER ); + } printk(KERN_DEBUG "CPU: Common caps: %08lx %08lx %08lx %08lx\n", boot_cpu_data.x86_capability[0],