aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/cpu-freq/governors.txt21
-rw-r--r--arch/x86/include/asm/cpufeature.h1
-rw-r--r--arch/x86/kernel/cpu/scattered.c3
-rw-r--r--drivers/cpufreq/Kconfig.x8617
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/amd_freq_sensitivity.c148
6 files changed, 190 insertions, 1 deletions
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 4dfed30b7fda..66f9cc310686 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -167,6 +167,27 @@ of load evaluation and helping the CPU stay at its top speed when truly
167busy, rather than shifting back and forth in speed. This tunable has no 167busy, rather than shifting back and forth in speed. This tunable has no
168effect on behavior at lower speeds/lower CPU loads. 168effect on behavior at lower speeds/lower CPU loads.
169 169
170powersave_bias: this parameter takes a value between 0 to 1000. It
171defines the percentage (times 10) value of the target frequency that
172will be shaved off of the target. For example, when set to 100 -- 10%,
173when ondemand governor would have targeted 1000 MHz, it will target
1741000 MHz - (10% of 1000 MHz) = 900 MHz instead. This is set to 0
175(disabled) by default.
176When AMD frequency sensitivity powersave bias driver --
177drivers/cpufreq/amd_freq_sensitivity.c is loaded, this parameter
178defines the workload frequency sensitivity threshold in which a lower
179frequency is chosen instead of ondemand governor's original target.
180The frequency sensitivity is a hardware reported (on AMD Family 16h
181Processors and above) value between 0 to 100% that tells software how
182the performance of the workload running on a CPU will change when
183frequency changes. A workload with sensitivity of 0% (memory/IO-bound)
184will not perform any better on higher core frequency, whereas a
185workload with sensitivity of 100% (CPU-bound) will perform better
186higher the frequency. When the driver is loaded, this is set to 400
187by default -- for CPUs running workloads with sensitivity value below
18840%, a lower frequency is chosen. Unloading the driver or writing 0
189will disable this feature.
190
170 191
1712.5 Conservative 1922.5 Conservative
172---------------- 193----------------
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 93fe929d1cee..9e22520a97ee 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -182,6 +182,7 @@
182#define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ 182#define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */
183#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ 183#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */
184#define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ 184#define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */
185#define X86_FEATURE_PROC_FEEDBACK (7*32+ 9) /* AMD ProcFeedbackInterface */
185 186
186/* Virtualization flags: Linux defined, word 8 */ 187/* Virtualization flags: Linux defined, word 8 */
187#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ 188#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index ee8e9abc859f..d92b5dad15dd 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -39,8 +39,9 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
39 { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 }, 39 { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 },
40 { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, 40 { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 },
41 { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, 41 { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 },
42 { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 },
43 { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, 42 { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 },
43 { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 },
44 { X86_FEATURE_PROC_FEEDBACK, CR_EDX,11, 0x80000007, 0 },
44 { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, 45 { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 },
45 { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, 46 { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 },
46 { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, 47 { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 },
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index d7dc0ed6adb0..2b8a8c374548 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -129,6 +129,23 @@ config X86_POWERNOW_K8
129 129
130 For details, take a look at <file:Documentation/cpu-freq/>. 130 For details, take a look at <file:Documentation/cpu-freq/>.
131 131
132config X86_AMD_FREQ_SENSITIVITY
133 tristate "AMD frequency sensitivity feedback powersave bias"
134 depends on CPU_FREQ_GOV_ONDEMAND && X86_ACPI_CPUFREQ && CPU_SUP_AMD
135 help
136 This adds AMD-specific powersave bias function to the ondemand
137 governor, which allows it to make more power-conscious frequency
138 change decisions based on feedback from hardware (availble on AMD
139 Family 16h and above).
140
141 Hardware feedback tells software how "sensitive" to frequency changes
142 the CPUs' workloads are. CPU-bound workloads will be more sensitive
143 -- they will perform better as frequency increases. Memory/IO-bound
144 workloads will be less sensitive -- they will not necessarily perform
145 better as frequency increases.
146
147 If in doubt, say N.
148
132config X86_GX_SUSPMOD 149config X86_GX_SUSPMOD
133 tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" 150 tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
134 depends on X86_32 && PCI 151 depends on X86_32 && PCI
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 17417c7ee135..a264dd302c34 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
41obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o 41obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
42obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o 42obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
43obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o 43obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o
44obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o
44 45
45################################################################################## 46##################################################################################
46# ARM SoC drivers 47# ARM SoC drivers
diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c
new file mode 100644
index 000000000000..f6b79ab0070b
--- /dev/null
+++ b/drivers/cpufreq/amd_freq_sensitivity.c
@@ -0,0 +1,148 @@
1/*
2 * amd_freq_sensitivity.c: AMD frequency sensitivity feedback powersave bias
3 * for the ondemand governor.
4 *
5 * Copyright (C) 2013 Advanced Micro Devices, Inc.
6 *
7 * Author: Jacob Shin <jacob.shin@amd.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/percpu-defs.h>
18#include <linux/init.h>
19#include <linux/mod_devicetable.h>
20
21#include <asm/msr.h>
22#include <asm/cpufeature.h>
23
24#include "cpufreq_governor.h"
25
26#define MSR_AMD64_FREQ_SENSITIVITY_ACTUAL 0xc0010080
27#define MSR_AMD64_FREQ_SENSITIVITY_REFERENCE 0xc0010081
28#define CLASS_CODE_SHIFT 56
29#define POWERSAVE_BIAS_MAX 1000
30#define POWERSAVE_BIAS_DEF 400
31
32struct cpu_data_t {
33 u64 actual;
34 u64 reference;
35 unsigned int freq_prev;
36};
37
38static DEFINE_PER_CPU(struct cpu_data_t, cpu_data);
39
40static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
41 unsigned int freq_next,
42 unsigned int relation)
43{
44 int sensitivity;
45 long d_actual, d_reference;
46 struct msr actual, reference;
47 struct cpu_data_t *data = &per_cpu(cpu_data, policy->cpu);
48 struct dbs_data *od_data = policy->governor_data;
49 struct od_dbs_tuners *od_tuners = od_data->tuners;
50 struct od_cpu_dbs_info_s *od_info =
51 od_data->cdata->get_cpu_dbs_info_s(policy->cpu);
52
53 if (!od_info->freq_table)
54 return freq_next;
55
56 rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL,
57 &actual.l, &actual.h);
58 rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_REFERENCE,
59 &reference.l, &reference.h);
60 actual.h &= 0x00ffffff;
61 reference.h &= 0x00ffffff;
62
63 /* counter wrapped around, so stay on current frequency */
64 if (actual.q < data->actual || reference.q < data->reference) {
65 freq_next = policy->cur;
66 goto out;
67 }
68
69 d_actual = actual.q - data->actual;
70 d_reference = reference.q - data->reference;
71
72 /* divide by 0, so stay on current frequency as well */
73 if (d_reference == 0) {
74 freq_next = policy->cur;
75 goto out;
76 }
77
78 sensitivity = POWERSAVE_BIAS_MAX -
79 (POWERSAVE_BIAS_MAX * (d_reference - d_actual) / d_reference);
80
81 clamp(sensitivity, 0, POWERSAVE_BIAS_MAX);
82
83 /* this workload is not CPU bound, so choose a lower freq */
84 if (sensitivity < od_tuners->powersave_bias) {
85 if (data->freq_prev == policy->cur)
86 freq_next = policy->cur;
87
88 if (freq_next > policy->cur)
89 freq_next = policy->cur;
90 else if (freq_next < policy->cur)
91 freq_next = policy->min;
92 else {
93 unsigned int index;
94
95 cpufreq_frequency_table_target(policy,
96 od_info->freq_table, policy->cur - 1,
97 CPUFREQ_RELATION_H, &index);
98 freq_next = od_info->freq_table[index].frequency;
99 }
100
101 data->freq_prev = freq_next;
102 } else
103 data->freq_prev = 0;
104
105out:
106 data->actual = actual.q;
107 data->reference = reference.q;
108 return freq_next;
109}
110
111static int __init amd_freq_sensitivity_init(void)
112{
113 u64 val;
114
115 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
116 return -ENODEV;
117
118 if (!static_cpu_has(X86_FEATURE_PROC_FEEDBACK))
119 return -ENODEV;
120
121 if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val))
122 return -ENODEV;
123
124 if (!(val >> CLASS_CODE_SHIFT))
125 return -ENODEV;
126
127 od_register_powersave_bias_handler(amd_powersave_bias_target,
128 POWERSAVE_BIAS_DEF);
129 return 0;
130}
131late_initcall(amd_freq_sensitivity_init);
132
133static void __exit amd_freq_sensitivity_exit(void)
134{
135 od_unregister_powersave_bias_handler();
136}
137module_exit(amd_freq_sensitivity_exit);
138
139static const struct x86_cpu_id amd_freq_sensitivity_ids[] = {
140 X86_FEATURE_MATCH(X86_FEATURE_PROC_FEEDBACK),
141 {}
142};
143MODULE_DEVICE_TABLE(x86cpu, amd_freq_sensitivity_ids);
144
145MODULE_AUTHOR("Jacob Shin <jacob.shin@amd.com>");
146MODULE_DESCRIPTION("AMD frequency sensitivity feedback powersave bias for "
147 "the ondemand governor.");
148MODULE_LICENSE("GPL");