diff options
| -rw-r--r-- | arch/x86/kernel/cpu/cpufreq/Makefile | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 44 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/cpufreq/mperf.c | 51 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/cpufreq/mperf.h | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 8 |
5 files changed, 72 insertions, 44 deletions
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile index 1840c0a5170b..bd54bf67e6fb 100644 --- a/arch/x86/kernel/cpu/cpufreq/Makefile +++ b/arch/x86/kernel/cpu/cpufreq/Makefile | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | # K8 systems. ACPI is preferred to all other hardware-specific drivers. | 2 | # K8 systems. ACPI is preferred to all other hardware-specific drivers. |
| 3 | # speedstep-* is preferred over p4-clockmod. | 3 | # speedstep-* is preferred over p4-clockmod. |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o | 5 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o mperf.o |
| 6 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o | 6 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o |
| 7 | obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o | 7 | obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o |
| 8 | obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o | 8 | obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o |
| 9 | obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o | 9 | obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o |
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++) |
diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.c b/arch/x86/kernel/cpu/cpufreq/mperf.c new file mode 100644 index 000000000000..911e193018ae --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/mperf.c | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #include <linux/kernel.h> | ||
| 2 | #include <linux/smp.h> | ||
| 3 | #include <linux/module.h> | ||
| 4 | #include <linux/init.h> | ||
| 5 | #include <linux/cpufreq.h> | ||
| 6 | #include <linux/slab.h> | ||
| 7 | |||
| 8 | #include "mperf.h" | ||
| 9 | |||
| 10 | static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); | ||
| 11 | |||
| 12 | /* Called via smp_call_function_single(), on the target CPU */ | ||
| 13 | static void read_measured_perf_ctrs(void *_cur) | ||
| 14 | { | ||
| 15 | struct aperfmperf *am = _cur; | ||
| 16 | |||
| 17 | get_aperfmperf(am); | ||
| 18 | } | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Return the measured active (C0) frequency on this CPU since last call | ||
| 22 | * to this function. | ||
| 23 | * Input: cpu number | ||
| 24 | * Return: Average CPU frequency in terms of max frequency (zero on error) | ||
| 25 | * | ||
| 26 | * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance | ||
| 27 | * over a period of time, while CPU is in C0 state. | ||
| 28 | * IA32_MPERF counts at the rate of max advertised frequency | ||
| 29 | * IA32_APERF counts at the rate of actual CPU frequency | ||
| 30 | * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and | ||
| 31 | * no meaning should be associated with absolute values of these MSRs. | ||
| 32 | */ | ||
| 33 | unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, | ||
| 34 | unsigned int cpu) | ||
| 35 | { | ||
| 36 | struct aperfmperf perf; | ||
| 37 | unsigned long ratio; | ||
| 38 | unsigned int retval; | ||
| 39 | |||
| 40 | if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) | ||
| 41 | return 0; | ||
| 42 | |||
| 43 | ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); | ||
| 44 | per_cpu(acfreq_old_perf, cpu) = perf; | ||
| 45 | |||
| 46 | retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; | ||
| 47 | |||
| 48 | return retval; | ||
| 49 | } | ||
| 50 | EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf); | ||
| 51 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.h b/arch/x86/kernel/cpu/cpufreq/mperf.h new file mode 100644 index 000000000000..5dbf2950dc22 --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/mperf.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | /* | ||
| 2 | * (c) 2010 Advanced Micro Devices, Inc. | ||
| 3 | * Your use of this code is subject to the terms and conditions of the | ||
| 4 | * GNU general public license version 2. See "COPYING" or | ||
| 5 | * http://www.gnu.org/licenses/gpl.html | ||
| 6 | */ | ||
| 7 | |||
| 8 | unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, | ||
| 9 | unsigned int cpu); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 74ca34b5c003..52fce638f444 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #define PFX "powernow-k8: " | 45 | #define PFX "powernow-k8: " |
| 46 | #define VERSION "version 2.20.00" | 46 | #define VERSION "version 2.20.00" |
| 47 | #include "powernow-k8.h" | 47 | #include "powernow-k8.h" |
| 48 | #include "mperf.h" | ||
| 48 | 49 | ||
| 49 | /* serialize freq changes */ | 50 | /* serialize freq changes */ |
| 50 | static DEFINE_MUTEX(fidvid_mutex); | 51 | static DEFINE_MUTEX(fidvid_mutex); |
| @@ -57,6 +58,8 @@ static int cpu_family = CPU_OPTERON; | |||
| 57 | static bool cpb_capable, cpb_enabled; | 58 | static bool cpb_capable, cpb_enabled; |
| 58 | static struct msr __percpu *msrs; | 59 | static struct msr __percpu *msrs; |
| 59 | 60 | ||
| 61 | static struct cpufreq_driver cpufreq_amd64_driver; | ||
| 62 | |||
| 60 | #ifndef CONFIG_SMP | 63 | #ifndef CONFIG_SMP |
| 61 | static inline const struct cpumask *cpu_core_mask(int cpu) | 64 | static inline const struct cpumask *cpu_core_mask(int cpu) |
| 62 | { | 65 | { |
| @@ -1251,6 +1254,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
| 1251 | struct powernow_k8_data *data; | 1254 | struct powernow_k8_data *data; |
| 1252 | struct init_on_cpu init_on_cpu; | 1255 | struct init_on_cpu init_on_cpu; |
| 1253 | int rc; | 1256 | int rc; |
| 1257 | struct cpuinfo_x86 *c = &cpu_data(pol->cpu); | ||
| 1254 | 1258 | ||
| 1255 | if (!cpu_online(pol->cpu)) | 1259 | if (!cpu_online(pol->cpu)) |
| 1256 | return -ENODEV; | 1260 | return -ENODEV; |
| @@ -1325,6 +1329,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
| 1325 | return -EINVAL; | 1329 | return -EINVAL; |
| 1326 | } | 1330 | } |
| 1327 | 1331 | ||
| 1332 | /* Check for APERF/MPERF support in hardware */ | ||
| 1333 | if (cpu_has(c, X86_FEATURE_APERFMPERF)) | ||
| 1334 | cpufreq_amd64_driver.getavg = cpufreq_get_measured_perf; | ||
| 1335 | |||
| 1328 | cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); | 1336 | cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); |
| 1329 | 1337 | ||
| 1330 | if (cpu_family == CPU_HW_PSTATE) | 1338 | if (cpu_family == CPU_HW_PSTATE) |
