diff options
author | Mark Langsdorf <mark.langsdorf@amd.com> | 2010-03-18 13:41:46 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-04-09 17:07:40 -0400 |
commit | a2fed573f065e526bfd5cbf26e5491973d9e9aaa (patch) | |
tree | 069ea4932051dd4535de4bf896e09deff836e0b9 /arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |
parent | d65ad45cd82a0db9544469b8c54f5dc5cafbb2d8 (diff) |
x86, cpufreq: Add APERF/MPERF support for AMD processors
Starting with model 10 of Family 0x10, AMD processors may have
support for APERF/MPERF. Add support for identifying it and using
it within cpufreq. Move the APERF/MPERF functions out of the
acpi-cpufreq code and into their own file so they can easily be
shared.
Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
LKML-Reference: <20100401141956.GA1930@aftab>
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Reviewed-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c')
-rw-r--r-- | arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 44 |
1 files changed, 2 insertions, 42 deletions
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 1b1920fa7c80..dc68e5c2c071 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/msr.h> | 45 | #include <asm/msr.h> |
46 | #include <asm/processor.h> | 46 | #include <asm/processor.h> |
47 | #include <asm/cpufeature.h> | 47 | #include <asm/cpufeature.h> |
48 | #include "mperf.h" | ||
48 | 49 | ||
49 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ | 50 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ |
50 | "acpi-cpufreq", msg) | 51 | "acpi-cpufreq", msg) |
@@ -70,8 +71,6 @@ struct acpi_cpufreq_data { | |||
70 | 71 | ||
71 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); | 72 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); |
72 | 73 | ||
73 | static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); | ||
74 | |||
75 | /* acpi_perf_data is a pointer to percpu data. */ | 74 | /* acpi_perf_data is a pointer to percpu data. */ |
76 | static struct acpi_processor_performance *acpi_perf_data; | 75 | static struct acpi_processor_performance *acpi_perf_data; |
77 | 76 | ||
@@ -239,45 +238,6 @@ static u32 get_cur_val(const struct cpumask *mask) | |||
239 | return cmd.val; | 238 | return cmd.val; |
240 | } | 239 | } |
241 | 240 | ||
242 | /* Called via smp_call_function_single(), on the target CPU */ | ||
243 | static void read_measured_perf_ctrs(void *_cur) | ||
244 | { | ||
245 | struct aperfmperf *am = _cur; | ||
246 | |||
247 | get_aperfmperf(am); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Return the measured active (C0) frequency on this CPU since last call | ||
252 | * to this function. | ||
253 | * Input: cpu number | ||
254 | * Return: Average CPU frequency in terms of max frequency (zero on error) | ||
255 | * | ||
256 | * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance | ||
257 | * over a period of time, while CPU is in C0 state. | ||
258 | * IA32_MPERF counts at the rate of max advertised frequency | ||
259 | * IA32_APERF counts at the rate of actual CPU frequency | ||
260 | * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and | ||
261 | * no meaning should be associated with absolute values of these MSRs. | ||
262 | */ | ||
263 | static unsigned int get_measured_perf(struct cpufreq_policy *policy, | ||
264 | unsigned int cpu) | ||
265 | { | ||
266 | struct aperfmperf perf; | ||
267 | unsigned long ratio; | ||
268 | unsigned int retval; | ||
269 | |||
270 | if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) | ||
271 | return 0; | ||
272 | |||
273 | ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); | ||
274 | per_cpu(acfreq_old_perf, cpu) = perf; | ||
275 | |||
276 | retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; | ||
277 | |||
278 | return retval; | ||
279 | } | ||
280 | |||
281 | static unsigned int get_cur_freq_on_cpu(unsigned int cpu) | 241 | static unsigned int get_cur_freq_on_cpu(unsigned int cpu) |
282 | { | 242 | { |
283 | struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); | 243 | struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); |
@@ -701,7 +661,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
701 | 661 | ||
702 | /* Check for APERF/MPERF support in hardware */ | 662 | /* Check for APERF/MPERF support in hardware */ |
703 | if (cpu_has(c, X86_FEATURE_APERFMPERF)) | 663 | if (cpu_has(c, X86_FEATURE_APERFMPERF)) |
704 | acpi_cpufreq_driver.getavg = get_measured_perf; | 664 | acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; |
705 | 665 | ||
706 | dprintk("CPU%u - ACPI performance management activated.\n", cpu); | 666 | dprintk("CPU%u - ACPI performance management activated.\n", cpu); |
707 | for (i = 0; i < perf->state_count; i++) | 667 | for (i = 0; i < perf->state_count; i++) |