Commit c52851b60cc0aaaf974ff0e49989fb698220447d
Committed by
Len Brown
1 parent
09b4d1ee88
Exists in
master
and in
7 other branches
P-state software coordination for speedstep-centrino
http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Showing 1 changed file with 180 additions and 66 deletions Inline Diff
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
1 | /* | 1 | /* |
2 | * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium | 2 | * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium |
3 | * M (part of the Centrino chipset). | 3 | * M (part of the Centrino chipset). |
4 | * | 4 | * |
5 | * Despite the "SpeedStep" in the name, this is almost entirely unlike | 5 | * Despite the "SpeedStep" in the name, this is almost entirely unlike |
6 | * traditional SpeedStep. | 6 | * traditional SpeedStep. |
7 | * | 7 | * |
8 | * Modelled on speedstep.c | 8 | * Modelled on speedstep.c |
9 | * | 9 | * |
10 | * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org> | 10 | * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org> |
11 | * | 11 | * |
12 | * WARNING WARNING WARNING | 12 | * WARNING WARNING WARNING |
13 | * | 13 | * |
14 | * This driver manipulates the PERF_CTL MSR, which is only somewhat | 14 | * This driver manipulates the PERF_CTL MSR, which is only somewhat |
15 | * documented. While it seems to work on my laptop, it has not been | 15 | * documented. While it seems to work on my laptop, it has not been |
16 | * tested anywhere else, and it may not work for you, do strange | 16 | * tested anywhere else, and it may not work for you, do strange |
17 | * things or simply crash. | 17 | * things or simply crash. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/cpufreq.h> | 23 | #include <linux/cpufreq.h> |
24 | #include <linux/config.h> | 24 | #include <linux/config.h> |
25 | #include <linux/sched.h> /* current */ | 25 | #include <linux/sched.h> /* current */ |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
28 | 28 | ||
29 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | 29 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI |
30 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
31 | #include <acpi/processor.h> | 31 | #include <acpi/processor.h> |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | #include <asm/msr.h> | 34 | #include <asm/msr.h> |
35 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
36 | #include <asm/cpufeature.h> | 36 | #include <asm/cpufeature.h> |
37 | 37 | ||
38 | #define PFX "speedstep-centrino: " | 38 | #define PFX "speedstep-centrino: " |
39 | #define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>" | 39 | #define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>" |
40 | 40 | ||
41 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) | 41 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) |
42 | 42 | ||
43 | 43 | ||
44 | struct cpu_id | 44 | struct cpu_id |
45 | { | 45 | { |
46 | __u8 x86; /* CPU family */ | 46 | __u8 x86; /* CPU family */ |
47 | __u8 x86_model; /* model */ | 47 | __u8 x86_model; /* model */ |
48 | __u8 x86_mask; /* stepping */ | 48 | __u8 x86_mask; /* stepping */ |
49 | }; | 49 | }; |
50 | 50 | ||
51 | enum { | 51 | enum { |
52 | CPU_BANIAS, | 52 | CPU_BANIAS, |
53 | CPU_DOTHAN_A1, | 53 | CPU_DOTHAN_A1, |
54 | CPU_DOTHAN_A2, | 54 | CPU_DOTHAN_A2, |
55 | CPU_DOTHAN_B0, | 55 | CPU_DOTHAN_B0, |
56 | CPU_MP4HT_D0, | 56 | CPU_MP4HT_D0, |
57 | CPU_MP4HT_E0, | 57 | CPU_MP4HT_E0, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static const struct cpu_id cpu_ids[] = { | 60 | static const struct cpu_id cpu_ids[] = { |
61 | [CPU_BANIAS] = { 6, 9, 5 }, | 61 | [CPU_BANIAS] = { 6, 9, 5 }, |
62 | [CPU_DOTHAN_A1] = { 6, 13, 1 }, | 62 | [CPU_DOTHAN_A1] = { 6, 13, 1 }, |
63 | [CPU_DOTHAN_A2] = { 6, 13, 2 }, | 63 | [CPU_DOTHAN_A2] = { 6, 13, 2 }, |
64 | [CPU_DOTHAN_B0] = { 6, 13, 6 }, | 64 | [CPU_DOTHAN_B0] = { 6, 13, 6 }, |
65 | [CPU_MP4HT_D0] = {15, 3, 4 }, | 65 | [CPU_MP4HT_D0] = {15, 3, 4 }, |
66 | [CPU_MP4HT_E0] = {15, 4, 1 }, | 66 | [CPU_MP4HT_E0] = {15, 4, 1 }, |
67 | }; | 67 | }; |
68 | #define N_IDS ARRAY_SIZE(cpu_ids) | 68 | #define N_IDS ARRAY_SIZE(cpu_ids) |
69 | 69 | ||
70 | struct cpu_model | 70 | struct cpu_model |
71 | { | 71 | { |
72 | const struct cpu_id *cpu_id; | 72 | const struct cpu_id *cpu_id; |
73 | const char *model_name; | 73 | const char *model_name; |
74 | unsigned max_freq; /* max clock in kHz */ | 74 | unsigned max_freq; /* max clock in kHz */ |
75 | 75 | ||
76 | struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ | 76 | struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ |
77 | }; | 77 | }; |
78 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x); | 78 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x); |
79 | 79 | ||
80 | /* Operating points for current CPU */ | 80 | /* Operating points for current CPU */ |
81 | static struct cpu_model *centrino_model[NR_CPUS]; | 81 | static struct cpu_model *centrino_model[NR_CPUS]; |
82 | static const struct cpu_id *centrino_cpu[NR_CPUS]; | 82 | static const struct cpu_id *centrino_cpu[NR_CPUS]; |
83 | 83 | ||
84 | static struct cpufreq_driver centrino_driver; | 84 | static struct cpufreq_driver centrino_driver; |
85 | 85 | ||
86 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE | 86 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE |
87 | 87 | ||
88 | /* Computes the correct form for IA32_PERF_CTL MSR for a particular | 88 | /* Computes the correct form for IA32_PERF_CTL MSR for a particular |
89 | frequency/voltage operating point; frequency in MHz, volts in mV. | 89 | frequency/voltage operating point; frequency in MHz, volts in mV. |
90 | This is stored as "index" in the structure. */ | 90 | This is stored as "index" in the structure. */ |
91 | #define OP(mhz, mv) \ | 91 | #define OP(mhz, mv) \ |
92 | { \ | 92 | { \ |
93 | .frequency = (mhz) * 1000, \ | 93 | .frequency = (mhz) * 1000, \ |
94 | .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \ | 94 | .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \ |
95 | } | 95 | } |
96 | 96 | ||
97 | /* | 97 | /* |
98 | * These voltage tables were derived from the Intel Pentium M | 98 | * These voltage tables were derived from the Intel Pentium M |
99 | * datasheet, document 25261202.pdf, Table 5. I have verified they | 99 | * datasheet, document 25261202.pdf, Table 5. I have verified they |
100 | * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium | 100 | * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium |
101 | * M. | 101 | * M. |
102 | */ | 102 | */ |
103 | 103 | ||
104 | /* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */ | 104 | /* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */ |
105 | static struct cpufreq_frequency_table banias_900[] = | 105 | static struct cpufreq_frequency_table banias_900[] = |
106 | { | 106 | { |
107 | OP(600, 844), | 107 | OP(600, 844), |
108 | OP(800, 988), | 108 | OP(800, 988), |
109 | OP(900, 1004), | 109 | OP(900, 1004), |
110 | { .frequency = CPUFREQ_TABLE_END } | 110 | { .frequency = CPUFREQ_TABLE_END } |
111 | }; | 111 | }; |
112 | 112 | ||
113 | /* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */ | 113 | /* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */ |
114 | static struct cpufreq_frequency_table banias_1000[] = | 114 | static struct cpufreq_frequency_table banias_1000[] = |
115 | { | 115 | { |
116 | OP(600, 844), | 116 | OP(600, 844), |
117 | OP(800, 972), | 117 | OP(800, 972), |
118 | OP(900, 988), | 118 | OP(900, 988), |
119 | OP(1000, 1004), | 119 | OP(1000, 1004), |
120 | { .frequency = CPUFREQ_TABLE_END } | 120 | { .frequency = CPUFREQ_TABLE_END } |
121 | }; | 121 | }; |
122 | 122 | ||
123 | /* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */ | 123 | /* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */ |
124 | static struct cpufreq_frequency_table banias_1100[] = | 124 | static struct cpufreq_frequency_table banias_1100[] = |
125 | { | 125 | { |
126 | OP( 600, 956), | 126 | OP( 600, 956), |
127 | OP( 800, 1020), | 127 | OP( 800, 1020), |
128 | OP( 900, 1100), | 128 | OP( 900, 1100), |
129 | OP(1000, 1164), | 129 | OP(1000, 1164), |
130 | OP(1100, 1180), | 130 | OP(1100, 1180), |
131 | { .frequency = CPUFREQ_TABLE_END } | 131 | { .frequency = CPUFREQ_TABLE_END } |
132 | }; | 132 | }; |
133 | 133 | ||
134 | 134 | ||
135 | /* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */ | 135 | /* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */ |
136 | static struct cpufreq_frequency_table banias_1200[] = | 136 | static struct cpufreq_frequency_table banias_1200[] = |
137 | { | 137 | { |
138 | OP( 600, 956), | 138 | OP( 600, 956), |
139 | OP( 800, 1004), | 139 | OP( 800, 1004), |
140 | OP( 900, 1020), | 140 | OP( 900, 1020), |
141 | OP(1000, 1100), | 141 | OP(1000, 1100), |
142 | OP(1100, 1164), | 142 | OP(1100, 1164), |
143 | OP(1200, 1180), | 143 | OP(1200, 1180), |
144 | { .frequency = CPUFREQ_TABLE_END } | 144 | { .frequency = CPUFREQ_TABLE_END } |
145 | }; | 145 | }; |
146 | 146 | ||
147 | /* Intel Pentium M processor 1.30GHz (Banias) */ | 147 | /* Intel Pentium M processor 1.30GHz (Banias) */ |
148 | static struct cpufreq_frequency_table banias_1300[] = | 148 | static struct cpufreq_frequency_table banias_1300[] = |
149 | { | 149 | { |
150 | OP( 600, 956), | 150 | OP( 600, 956), |
151 | OP( 800, 1260), | 151 | OP( 800, 1260), |
152 | OP(1000, 1292), | 152 | OP(1000, 1292), |
153 | OP(1200, 1356), | 153 | OP(1200, 1356), |
154 | OP(1300, 1388), | 154 | OP(1300, 1388), |
155 | { .frequency = CPUFREQ_TABLE_END } | 155 | { .frequency = CPUFREQ_TABLE_END } |
156 | }; | 156 | }; |
157 | 157 | ||
158 | /* Intel Pentium M processor 1.40GHz (Banias) */ | 158 | /* Intel Pentium M processor 1.40GHz (Banias) */ |
159 | static struct cpufreq_frequency_table banias_1400[] = | 159 | static struct cpufreq_frequency_table banias_1400[] = |
160 | { | 160 | { |
161 | OP( 600, 956), | 161 | OP( 600, 956), |
162 | OP( 800, 1180), | 162 | OP( 800, 1180), |
163 | OP(1000, 1308), | 163 | OP(1000, 1308), |
164 | OP(1200, 1436), | 164 | OP(1200, 1436), |
165 | OP(1400, 1484), | 165 | OP(1400, 1484), |
166 | { .frequency = CPUFREQ_TABLE_END } | 166 | { .frequency = CPUFREQ_TABLE_END } |
167 | }; | 167 | }; |
168 | 168 | ||
169 | /* Intel Pentium M processor 1.50GHz (Banias) */ | 169 | /* Intel Pentium M processor 1.50GHz (Banias) */ |
170 | static struct cpufreq_frequency_table banias_1500[] = | 170 | static struct cpufreq_frequency_table banias_1500[] = |
171 | { | 171 | { |
172 | OP( 600, 956), | 172 | OP( 600, 956), |
173 | OP( 800, 1116), | 173 | OP( 800, 1116), |
174 | OP(1000, 1228), | 174 | OP(1000, 1228), |
175 | OP(1200, 1356), | 175 | OP(1200, 1356), |
176 | OP(1400, 1452), | 176 | OP(1400, 1452), |
177 | OP(1500, 1484), | 177 | OP(1500, 1484), |
178 | { .frequency = CPUFREQ_TABLE_END } | 178 | { .frequency = CPUFREQ_TABLE_END } |
179 | }; | 179 | }; |
180 | 180 | ||
181 | /* Intel Pentium M processor 1.60GHz (Banias) */ | 181 | /* Intel Pentium M processor 1.60GHz (Banias) */ |
182 | static struct cpufreq_frequency_table banias_1600[] = | 182 | static struct cpufreq_frequency_table banias_1600[] = |
183 | { | 183 | { |
184 | OP( 600, 956), | 184 | OP( 600, 956), |
185 | OP( 800, 1036), | 185 | OP( 800, 1036), |
186 | OP(1000, 1164), | 186 | OP(1000, 1164), |
187 | OP(1200, 1276), | 187 | OP(1200, 1276), |
188 | OP(1400, 1420), | 188 | OP(1400, 1420), |
189 | OP(1600, 1484), | 189 | OP(1600, 1484), |
190 | { .frequency = CPUFREQ_TABLE_END } | 190 | { .frequency = CPUFREQ_TABLE_END } |
191 | }; | 191 | }; |
192 | 192 | ||
193 | /* Intel Pentium M processor 1.70GHz (Banias) */ | 193 | /* Intel Pentium M processor 1.70GHz (Banias) */ |
194 | static struct cpufreq_frequency_table banias_1700[] = | 194 | static struct cpufreq_frequency_table banias_1700[] = |
195 | { | 195 | { |
196 | OP( 600, 956), | 196 | OP( 600, 956), |
197 | OP( 800, 1004), | 197 | OP( 800, 1004), |
198 | OP(1000, 1116), | 198 | OP(1000, 1116), |
199 | OP(1200, 1228), | 199 | OP(1200, 1228), |
200 | OP(1400, 1308), | 200 | OP(1400, 1308), |
201 | OP(1700, 1484), | 201 | OP(1700, 1484), |
202 | { .frequency = CPUFREQ_TABLE_END } | 202 | { .frequency = CPUFREQ_TABLE_END } |
203 | }; | 203 | }; |
204 | #undef OP | 204 | #undef OP |
205 | 205 | ||
206 | #define _BANIAS(cpuid, max, name) \ | 206 | #define _BANIAS(cpuid, max, name) \ |
207 | { .cpu_id = cpuid, \ | 207 | { .cpu_id = cpuid, \ |
208 | .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \ | 208 | .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \ |
209 | .max_freq = (max)*1000, \ | 209 | .max_freq = (max)*1000, \ |
210 | .op_points = banias_##max, \ | 210 | .op_points = banias_##max, \ |
211 | } | 211 | } |
212 | #define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max) | 212 | #define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max) |
213 | 213 | ||
214 | /* CPU models, their operating frequency range, and freq/voltage | 214 | /* CPU models, their operating frequency range, and freq/voltage |
215 | operating points */ | 215 | operating points */ |
216 | static struct cpu_model models[] = | 216 | static struct cpu_model models[] = |
217 | { | 217 | { |
218 | _BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"), | 218 | _BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"), |
219 | BANIAS(1000), | 219 | BANIAS(1000), |
220 | BANIAS(1100), | 220 | BANIAS(1100), |
221 | BANIAS(1200), | 221 | BANIAS(1200), |
222 | BANIAS(1300), | 222 | BANIAS(1300), |
223 | BANIAS(1400), | 223 | BANIAS(1400), |
224 | BANIAS(1500), | 224 | BANIAS(1500), |
225 | BANIAS(1600), | 225 | BANIAS(1600), |
226 | BANIAS(1700), | 226 | BANIAS(1700), |
227 | 227 | ||
228 | /* NULL model_name is a wildcard */ | 228 | /* NULL model_name is a wildcard */ |
229 | { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, | 229 | { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, |
230 | { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, | 230 | { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, |
231 | { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, | 231 | { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, |
232 | { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, | 232 | { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, |
233 | { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, | 233 | { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, |
234 | 234 | ||
235 | { NULL, } | 235 | { NULL, } |
236 | }; | 236 | }; |
237 | #undef _BANIAS | 237 | #undef _BANIAS |
238 | #undef BANIAS | 238 | #undef BANIAS |
239 | 239 | ||
240 | static int centrino_cpu_init_table(struct cpufreq_policy *policy) | 240 | static int centrino_cpu_init_table(struct cpufreq_policy *policy) |
241 | { | 241 | { |
242 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; | 242 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; |
243 | struct cpu_model *model; | 243 | struct cpu_model *model; |
244 | 244 | ||
245 | for(model = models; model->cpu_id != NULL; model++) | 245 | for(model = models; model->cpu_id != NULL; model++) |
246 | if (centrino_verify_cpu_id(cpu, model->cpu_id) && | 246 | if (centrino_verify_cpu_id(cpu, model->cpu_id) && |
247 | (model->model_name == NULL || | 247 | (model->model_name == NULL || |
248 | strcmp(cpu->x86_model_id, model->model_name) == 0)) | 248 | strcmp(cpu->x86_model_id, model->model_name) == 0)) |
249 | break; | 249 | break; |
250 | 250 | ||
251 | if (model->cpu_id == NULL) { | 251 | if (model->cpu_id == NULL) { |
252 | /* No match at all */ | 252 | /* No match at all */ |
253 | dprintk(KERN_INFO PFX "no support for CPU model \"%s\": " | 253 | dprintk(KERN_INFO PFX "no support for CPU model \"%s\": " |
254 | "send /proc/cpuinfo to " MAINTAINER "\n", | 254 | "send /proc/cpuinfo to " MAINTAINER "\n", |
255 | cpu->x86_model_id); | 255 | cpu->x86_model_id); |
256 | return -ENOENT; | 256 | return -ENOENT; |
257 | } | 257 | } |
258 | 258 | ||
259 | if (model->op_points == NULL) { | 259 | if (model->op_points == NULL) { |
260 | /* Matched a non-match */ | 260 | /* Matched a non-match */ |
261 | dprintk(KERN_INFO PFX "no table support for CPU model \"%s\"\n", | 261 | dprintk(KERN_INFO PFX "no table support for CPU model \"%s\"\n", |
262 | cpu->x86_model_id); | 262 | cpu->x86_model_id); |
263 | #ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | 263 | #ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI |
264 | dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n"); | 264 | dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n"); |
265 | #endif | 265 | #endif |
266 | return -ENOENT; | 266 | return -ENOENT; |
267 | } | 267 | } |
268 | 268 | ||
269 | centrino_model[policy->cpu] = model; | 269 | centrino_model[policy->cpu] = model; |
270 | 270 | ||
271 | dprintk("found \"%s\": max frequency: %dkHz\n", | 271 | dprintk("found \"%s\": max frequency: %dkHz\n", |
272 | model->model_name, model->max_freq); | 272 | model->model_name, model->max_freq); |
273 | 273 | ||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
276 | 276 | ||
277 | #else | 277 | #else |
278 | static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } | 278 | static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } |
279 | #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ | 279 | #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ |
280 | 280 | ||
281 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x) | 281 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x) |
282 | { | 282 | { |
283 | if ((c->x86 == x->x86) && | 283 | if ((c->x86 == x->x86) && |
284 | (c->x86_model == x->x86_model) && | 284 | (c->x86_model == x->x86_model) && |
285 | (c->x86_mask == x->x86_mask)) | 285 | (c->x86_mask == x->x86_mask)) |
286 | return 1; | 286 | return 1; |
287 | return 0; | 287 | return 0; |
288 | } | 288 | } |
289 | 289 | ||
290 | /* To be called only after centrino_model is initialized */ | 290 | /* To be called only after centrino_model is initialized */ |
291 | static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe) | 291 | static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe) |
292 | { | 292 | { |
293 | int i; | 293 | int i; |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * Extract clock in kHz from PERF_CTL value | 296 | * Extract clock in kHz from PERF_CTL value |
297 | * for centrino, as some DSDTs are buggy. | 297 | * for centrino, as some DSDTs are buggy. |
298 | * Ideally, this can be done using the acpi_data structure. | 298 | * Ideally, this can be done using the acpi_data structure. |
299 | */ | 299 | */ |
300 | if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) || | 300 | if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) || |
301 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) || | 301 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) || |
302 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) { | 302 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) { |
303 | msr = (msr >> 8) & 0xff; | 303 | msr = (msr >> 8) & 0xff; |
304 | return msr * 100000; | 304 | return msr * 100000; |
305 | } | 305 | } |
306 | 306 | ||
307 | if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points)) | 307 | if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points)) |
308 | return 0; | 308 | return 0; |
309 | 309 | ||
310 | msr &= 0xffff; | 310 | msr &= 0xffff; |
311 | for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) { | 311 | for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) { |
312 | if (msr == centrino_model[cpu]->op_points[i].index) | 312 | if (msr == centrino_model[cpu]->op_points[i].index) |
313 | return centrino_model[cpu]->op_points[i].frequency; | 313 | return centrino_model[cpu]->op_points[i].frequency; |
314 | } | 314 | } |
315 | if (failsafe) | 315 | if (failsafe) |
316 | return centrino_model[cpu]->op_points[i-1].frequency; | 316 | return centrino_model[cpu]->op_points[i-1].frequency; |
317 | else | 317 | else |
318 | return 0; | 318 | return 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | /* Return the current CPU frequency in kHz */ | 321 | /* Return the current CPU frequency in kHz */ |
322 | static unsigned int get_cur_freq(unsigned int cpu) | 322 | static unsigned int get_cur_freq(unsigned int cpu) |
323 | { | 323 | { |
324 | unsigned l, h; | 324 | unsigned l, h; |
325 | unsigned clock_freq; | 325 | unsigned clock_freq; |
326 | cpumask_t saved_mask; | 326 | cpumask_t saved_mask; |
327 | 327 | ||
328 | saved_mask = current->cpus_allowed; | 328 | saved_mask = current->cpus_allowed; |
329 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 329 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
330 | if (smp_processor_id() != cpu) | 330 | if (smp_processor_id() != cpu) |
331 | return 0; | 331 | return 0; |
332 | 332 | ||
333 | rdmsr(MSR_IA32_PERF_STATUS, l, h); | 333 | rdmsr(MSR_IA32_PERF_STATUS, l, h); |
334 | clock_freq = extract_clock(l, cpu, 0); | 334 | clock_freq = extract_clock(l, cpu, 0); |
335 | 335 | ||
336 | if (unlikely(clock_freq == 0)) { | 336 | if (unlikely(clock_freq == 0)) { |
337 | /* | 337 | /* |
338 | * On some CPUs, we can see transient MSR values (which are | 338 | * On some CPUs, we can see transient MSR values (which are |
339 | * not present in _PSS), while CPU is doing some automatic | 339 | * not present in _PSS), while CPU is doing some automatic |
340 | * P-state transition (like TM2). Get the last freq set | 340 | * P-state transition (like TM2). Get the last freq set |
341 | * in PERF_CTL. | 341 | * in PERF_CTL. |
342 | */ | 342 | */ |
343 | rdmsr(MSR_IA32_PERF_CTL, l, h); | 343 | rdmsr(MSR_IA32_PERF_CTL, l, h); |
344 | clock_freq = extract_clock(l, cpu, 1); | 344 | clock_freq = extract_clock(l, cpu, 1); |
345 | } | 345 | } |
346 | 346 | ||
347 | set_cpus_allowed(current, saved_mask); | 347 | set_cpus_allowed(current, saved_mask); |
348 | return clock_freq; | 348 | return clock_freq; |
349 | } | 349 | } |
350 | 350 | ||
351 | 351 | ||
352 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | 352 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI |
353 | 353 | ||
354 | static struct acpi_processor_performance p; | 354 | static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; |
355 | 355 | ||
356 | /* | 356 | /* |
357 | * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States | ||
358 | * library | ||
359 | * | ||
360 | * Before doing the actual init, we need to do _PSD related setup whenever | ||
361 | * supported by the BIOS. These are handled by this early_init routine. | ||
362 | */ | ||
363 | static int centrino_cpu_early_init_acpi(void) | ||
364 | { | ||
365 | unsigned int i, j; | ||
366 | struct acpi_processor_performance *data; | ||
367 | |||
368 | for_each_cpu(i) { | ||
369 | data = kzalloc(sizeof(struct acpi_processor_performance), | ||
370 | GFP_KERNEL); | ||
371 | if (!data) { | ||
372 | for_each_cpu(j) { | ||
373 | kfree(acpi_perf_data[j]); | ||
374 | acpi_perf_data[j] = NULL; | ||
375 | } | ||
376 | return (-ENOMEM); | ||
377 | } | ||
378 | acpi_perf_data[i] = data; | ||
379 | } | ||
380 | |||
381 | acpi_processor_preregister_performance(acpi_perf_data); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | /* | ||
357 | * centrino_cpu_init_acpi - register with ACPI P-States library | 386 | * centrino_cpu_init_acpi - register with ACPI P-States library |
358 | * | 387 | * |
359 | * Register with the ACPI P-States library (part of drivers/acpi/processor.c) | 388 | * Register with the ACPI P-States library (part of drivers/acpi/processor.c) |
360 | * in order to determine correct frequency and voltage pairings by reading | 389 | * in order to determine correct frequency and voltage pairings by reading |
361 | * the _PSS of the ACPI DSDT or SSDT tables. | 390 | * the _PSS of the ACPI DSDT or SSDT tables. |
362 | */ | 391 | */ |
363 | static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) | 392 | static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) |
364 | { | 393 | { |
365 | unsigned long cur_freq; | 394 | unsigned long cur_freq; |
366 | int result = 0, i; | 395 | int result = 0, i; |
367 | unsigned int cpu = policy->cpu; | 396 | unsigned int cpu = policy->cpu; |
397 | struct acpi_processor_performance *p; | ||
368 | 398 | ||
399 | p = acpi_perf_data[cpu]; | ||
400 | |||
369 | /* register with ACPI core */ | 401 | /* register with ACPI core */ |
370 | if (acpi_processor_register_performance(&p, cpu)) { | 402 | if (acpi_processor_register_performance(p, cpu)) { |
371 | dprintk(KERN_INFO PFX "obtaining ACPI data failed\n"); | 403 | dprintk(KERN_INFO PFX "obtaining ACPI data failed\n"); |
372 | return -EIO; | 404 | return -EIO; |
373 | } | 405 | } |
406 | policy->cpus = p->shared_cpu_map; | ||
407 | policy->shared_type = p->shared_type; | ||
374 | 408 | ||
375 | /* verify the acpi_data */ | 409 | /* verify the acpi_data */ |
376 | if (p.state_count <= 1) { | 410 | if (p->state_count <= 1) { |
377 | dprintk("No P-States\n"); | 411 | dprintk("No P-States\n"); |
378 | result = -ENODEV; | 412 | result = -ENODEV; |
379 | goto err_unreg; | 413 | goto err_unreg; |
380 | } | 414 | } |
381 | 415 | ||
382 | if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || | 416 | if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || |
383 | (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { | 417 | (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { |
384 | dprintk("Invalid control/status registers (%x - %x)\n", | 418 | dprintk("Invalid control/status registers (%x - %x)\n", |
385 | p.control_register.space_id, p.status_register.space_id); | 419 | p->control_register.space_id, p->status_register.space_id); |
386 | result = -EIO; | 420 | result = -EIO; |
387 | goto err_unreg; | 421 | goto err_unreg; |
388 | } | 422 | } |
389 | 423 | ||
390 | for (i=0; i<p.state_count; i++) { | 424 | for (i=0; i<p->state_count; i++) { |
391 | if (p.states[i].control != p.states[i].status) { | 425 | if (p->states[i].control != p->states[i].status) { |
392 | dprintk("Different control (%llu) and status values (%llu)\n", | 426 | dprintk("Different control (%llu) and status values (%llu)\n", |
393 | p.states[i].control, p.states[i].status); | 427 | p->states[i].control, p->states[i].status); |
394 | result = -EINVAL; | 428 | result = -EINVAL; |
395 | goto err_unreg; | 429 | goto err_unreg; |
396 | } | 430 | } |
397 | 431 | ||
398 | if (!p.states[i].core_frequency) { | 432 | if (!p->states[i].core_frequency) { |
399 | dprintk("Zero core frequency for state %u\n", i); | 433 | dprintk("Zero core frequency for state %u\n", i); |
400 | result = -EINVAL; | 434 | result = -EINVAL; |
401 | goto err_unreg; | 435 | goto err_unreg; |
402 | } | 436 | } |
403 | 437 | ||
404 | if (p.states[i].core_frequency > p.states[0].core_frequency) { | 438 | if (p->states[i].core_frequency > p->states[0].core_frequency) { |
405 | dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i, | 439 | dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i, |
406 | p.states[i].core_frequency, p.states[0].core_frequency); | 440 | p->states[i].core_frequency, p->states[0].core_frequency); |
407 | p.states[i].core_frequency = 0; | 441 | p->states[i].core_frequency = 0; |
408 | continue; | 442 | continue; |
409 | } | 443 | } |
410 | } | 444 | } |
411 | 445 | ||
412 | centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL); | 446 | centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL); |
413 | if (!centrino_model[cpu]) { | 447 | if (!centrino_model[cpu]) { |
414 | result = -ENOMEM; | 448 | result = -ENOMEM; |
415 | goto err_unreg; | 449 | goto err_unreg; |
416 | } | 450 | } |
417 | 451 | ||
418 | centrino_model[cpu]->model_name=NULL; | 452 | centrino_model[cpu]->model_name=NULL; |
419 | centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000; | 453 | centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000; |
420 | centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * | 454 | centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * |
421 | (p.state_count + 1), GFP_KERNEL); | 455 | (p->state_count + 1), GFP_KERNEL); |
422 | if (!centrino_model[cpu]->op_points) { | 456 | if (!centrino_model[cpu]->op_points) { |
423 | result = -ENOMEM; | 457 | result = -ENOMEM; |
424 | goto err_kfree; | 458 | goto err_kfree; |
425 | } | 459 | } |
426 | 460 | ||
427 | for (i=0; i<p.state_count; i++) { | 461 | for (i=0; i<p->state_count; i++) { |
428 | centrino_model[cpu]->op_points[i].index = p.states[i].control; | 462 | centrino_model[cpu]->op_points[i].index = p->states[i].control; |
429 | centrino_model[cpu]->op_points[i].frequency = p.states[i].core_frequency * 1000; | 463 | centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000; |
430 | dprintk("adding state %i with frequency %u and control value %04x\n", | 464 | dprintk("adding state %i with frequency %u and control value %04x\n", |
431 | i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); | 465 | i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); |
432 | } | 466 | } |
433 | centrino_model[cpu]->op_points[p.state_count].frequency = CPUFREQ_TABLE_END; | 467 | centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END; |
434 | 468 | ||
435 | cur_freq = get_cur_freq(cpu); | 469 | cur_freq = get_cur_freq(cpu); |
436 | 470 | ||
437 | for (i=0; i<p.state_count; i++) { | 471 | for (i=0; i<p->state_count; i++) { |
438 | if (!p.states[i].core_frequency) { | 472 | if (!p->states[i].core_frequency) { |
439 | dprintk("skipping state %u\n", i); | 473 | dprintk("skipping state %u\n", i); |
440 | centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID; | 474 | centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID; |
441 | continue; | 475 | continue; |
442 | } | 476 | } |
443 | 477 | ||
444 | if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) != | 478 | if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) != |
445 | (centrino_model[cpu]->op_points[i].frequency)) { | 479 | (centrino_model[cpu]->op_points[i].frequency)) { |
446 | dprintk("Invalid encoded frequency (%u vs. %u)\n", | 480 | dprintk("Invalid encoded frequency (%u vs. %u)\n", |
447 | extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0), | 481 | extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0), |
448 | centrino_model[cpu]->op_points[i].frequency); | 482 | centrino_model[cpu]->op_points[i].frequency); |
449 | result = -EINVAL; | 483 | result = -EINVAL; |
450 | goto err_kfree_all; | 484 | goto err_kfree_all; |
451 | } | 485 | } |
452 | 486 | ||
453 | if (cur_freq == centrino_model[cpu]->op_points[i].frequency) | 487 | if (cur_freq == centrino_model[cpu]->op_points[i].frequency) |
454 | p.state = i; | 488 | p->state = i; |
455 | } | 489 | } |
456 | 490 | ||
457 | /* notify BIOS that we exist */ | 491 | /* notify BIOS that we exist */ |
458 | acpi_processor_notify_smm(THIS_MODULE); | 492 | acpi_processor_notify_smm(THIS_MODULE); |
459 | 493 | ||
460 | return 0; | 494 | return 0; |
461 | 495 | ||
462 | err_kfree_all: | 496 | err_kfree_all: |
463 | kfree(centrino_model[cpu]->op_points); | 497 | kfree(centrino_model[cpu]->op_points); |
464 | err_kfree: | 498 | err_kfree: |
465 | kfree(centrino_model[cpu]); | 499 | kfree(centrino_model[cpu]); |
466 | err_unreg: | 500 | err_unreg: |
467 | acpi_processor_unregister_performance(&p, cpu); | 501 | acpi_processor_unregister_performance(p, cpu); |
468 | dprintk(KERN_INFO PFX "invalid ACPI data\n"); | 502 | dprintk(KERN_INFO PFX "invalid ACPI data\n"); |
469 | return (result); | 503 | return (result); |
470 | } | 504 | } |
471 | #else | 505 | #else |
472 | static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; } | 506 | static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; } |
507 | static inline int centrino_cpu_early_init_acpi(void) { return 0; } | ||
473 | #endif | 508 | #endif |
474 | 509 | ||
475 | static int centrino_cpu_init(struct cpufreq_policy *policy) | 510 | static int centrino_cpu_init(struct cpufreq_policy *policy) |
476 | { | 511 | { |
477 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; | 512 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; |
478 | unsigned freq; | 513 | unsigned freq; |
479 | unsigned l, h; | 514 | unsigned l, h; |
480 | int ret; | 515 | int ret; |
481 | int i; | 516 | int i; |
482 | struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; | 517 | struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; |
483 | 518 | ||
484 | /* Only Intel makes Enhanced Speedstep-capable CPUs */ | 519 | /* Only Intel makes Enhanced Speedstep-capable CPUs */ |
485 | if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST)) | 520 | if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST)) |
486 | return -ENODEV; | 521 | return -ENODEV; |
487 | 522 | ||
488 | if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { | 523 | if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { |
489 | centrino_driver.flags |= CPUFREQ_CONST_LOOPS; | 524 | centrino_driver.flags |= CPUFREQ_CONST_LOOPS; |
490 | } | 525 | } |
491 | 526 | ||
492 | if (centrino_cpu_init_acpi(policy)) { | 527 | if (centrino_cpu_init_acpi(policy)) { |
493 | if (policy->cpu != 0) | 528 | if (policy->cpu != 0) |
494 | return -ENODEV; | 529 | return -ENODEV; |
495 | 530 | ||
496 | for (i = 0; i < N_IDS; i++) | 531 | for (i = 0; i < N_IDS; i++) |
497 | if (centrino_verify_cpu_id(cpu, &cpu_ids[i])) | 532 | if (centrino_verify_cpu_id(cpu, &cpu_ids[i])) |
498 | break; | 533 | break; |
499 | 534 | ||
500 | if (i != N_IDS) | 535 | if (i != N_IDS) |
501 | centrino_cpu[policy->cpu] = &cpu_ids[i]; | 536 | centrino_cpu[policy->cpu] = &cpu_ids[i]; |
502 | 537 | ||
503 | if (!centrino_cpu[policy->cpu]) { | 538 | if (!centrino_cpu[policy->cpu]) { |
504 | dprintk(KERN_INFO PFX "found unsupported CPU with " | 539 | dprintk(KERN_INFO PFX "found unsupported CPU with " |
505 | "Enhanced SpeedStep: send /proc/cpuinfo to " | 540 | "Enhanced SpeedStep: send /proc/cpuinfo to " |
506 | MAINTAINER "\n"); | 541 | MAINTAINER "\n"); |
507 | return -ENODEV; | 542 | return -ENODEV; |
508 | } | 543 | } |
509 | 544 | ||
510 | if (centrino_cpu_init_table(policy)) { | 545 | if (centrino_cpu_init_table(policy)) { |
511 | return -ENODEV; | 546 | return -ENODEV; |
512 | } | 547 | } |
513 | } | 548 | } |
514 | 549 | ||
515 | /* Check to see if Enhanced SpeedStep is enabled, and try to | 550 | /* Check to see if Enhanced SpeedStep is enabled, and try to |
516 | enable it if not. */ | 551 | enable it if not. */ |
517 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | 552 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); |
518 | 553 | ||
519 | if (!(l & (1<<16))) { | 554 | if (!(l & (1<<16))) { |
520 | l |= (1<<16); | 555 | l |= (1<<16); |
521 | dprintk("trying to enable Enhanced SpeedStep (%x)\n", l); | 556 | dprintk("trying to enable Enhanced SpeedStep (%x)\n", l); |
522 | wrmsr(MSR_IA32_MISC_ENABLE, l, h); | 557 | wrmsr(MSR_IA32_MISC_ENABLE, l, h); |
523 | 558 | ||
524 | /* check to see if it stuck */ | 559 | /* check to see if it stuck */ |
525 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | 560 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); |
526 | if (!(l & (1<<16))) { | 561 | if (!(l & (1<<16))) { |
527 | printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n"); | 562 | printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n"); |
528 | return -ENODEV; | 563 | return -ENODEV; |
529 | } | 564 | } |
530 | } | 565 | } |
531 | 566 | ||
532 | freq = get_cur_freq(policy->cpu); | 567 | freq = get_cur_freq(policy->cpu); |
533 | 568 | ||
534 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | 569 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; |
535 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ | 570 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ |
536 | policy->cur = freq; | 571 | policy->cur = freq; |
537 | 572 | ||
538 | dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur); | 573 | dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur); |
539 | 574 | ||
540 | ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model[policy->cpu]->op_points); | 575 | ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model[policy->cpu]->op_points); |
541 | if (ret) | 576 | if (ret) |
542 | return (ret); | 577 | return (ret); |
543 | 578 | ||
544 | cpufreq_frequency_table_get_attr(centrino_model[policy->cpu]->op_points, policy->cpu); | 579 | cpufreq_frequency_table_get_attr(centrino_model[policy->cpu]->op_points, policy->cpu); |
545 | 580 | ||
546 | return 0; | 581 | return 0; |
547 | } | 582 | } |
548 | 583 | ||
549 | static int centrino_cpu_exit(struct cpufreq_policy *policy) | 584 | static int centrino_cpu_exit(struct cpufreq_policy *policy) |
550 | { | 585 | { |
551 | unsigned int cpu = policy->cpu; | 586 | unsigned int cpu = policy->cpu; |
552 | 587 | ||
553 | if (!centrino_model[cpu]) | 588 | if (!centrino_model[cpu]) |
554 | return -ENODEV; | 589 | return -ENODEV; |
555 | 590 | ||
556 | cpufreq_frequency_table_put_attr(cpu); | 591 | cpufreq_frequency_table_put_attr(cpu); |
557 | 592 | ||
558 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | 593 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI |
559 | if (!centrino_model[cpu]->model_name) { | 594 | if (!centrino_model[cpu]->model_name) { |
560 | dprintk("unregistering and freeing ACPI data\n"); | 595 | static struct acpi_processor_performance *p; |
561 | acpi_processor_unregister_performance(&p, cpu); | 596 | |
562 | kfree(centrino_model[cpu]->op_points); | 597 | if (acpi_perf_data[cpu]) { |
563 | kfree(centrino_model[cpu]); | 598 | p = acpi_perf_data[cpu]; |
599 | dprintk("unregistering and freeing ACPI data\n"); | ||
600 | acpi_processor_unregister_performance(p, cpu); | ||
601 | kfree(centrino_model[cpu]->op_points); | ||
602 | kfree(centrino_model[cpu]); | ||
603 | } | ||
564 | } | 604 | } |
565 | #endif | 605 | #endif |
566 | 606 | ||
567 | centrino_model[cpu] = NULL; | 607 | centrino_model[cpu] = NULL; |
568 | 608 | ||
569 | return 0; | 609 | return 0; |
570 | } | 610 | } |
571 | 611 | ||
572 | /** | 612 | /** |
573 | * centrino_verify - verifies a new CPUFreq policy | 613 | * centrino_verify - verifies a new CPUFreq policy |
574 | * @policy: new policy | 614 | * @policy: new policy |
575 | * | 615 | * |
576 | * Limit must be within this model's frequency range at least one | 616 | * Limit must be within this model's frequency range at least one |
577 | * border included. | 617 | * border included. |
578 | */ | 618 | */ |
579 | static int centrino_verify (struct cpufreq_policy *policy) | 619 | static int centrino_verify (struct cpufreq_policy *policy) |
580 | { | 620 | { |
581 | return cpufreq_frequency_table_verify(policy, centrino_model[policy->cpu]->op_points); | 621 | return cpufreq_frequency_table_verify(policy, centrino_model[policy->cpu]->op_points); |
582 | } | 622 | } |
583 | 623 | ||
584 | /** | 624 | /** |
585 | * centrino_setpolicy - set a new CPUFreq policy | 625 | * centrino_setpolicy - set a new CPUFreq policy |
586 | * @policy: new policy | 626 | * @policy: new policy |
587 | * @target_freq: the target frequency | 627 | * @target_freq: the target frequency |
588 | * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) | 628 | * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) |
589 | * | 629 | * |
590 | * Sets a new CPUFreq policy. | 630 | * Sets a new CPUFreq policy. |
591 | */ | 631 | */ |
592 | static int centrino_target (struct cpufreq_policy *policy, | 632 | static int centrino_target (struct cpufreq_policy *policy, |
593 | unsigned int target_freq, | 633 | unsigned int target_freq, |
594 | unsigned int relation) | 634 | unsigned int relation) |
595 | { | 635 | { |
596 | unsigned int newstate = 0; | 636 | unsigned int newstate = 0; |
597 | unsigned int msr, oldmsr, h, cpu = policy->cpu; | 637 | unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu; |
598 | struct cpufreq_freqs freqs; | 638 | struct cpufreq_freqs freqs; |
639 | cpumask_t online_policy_cpus; | ||
599 | cpumask_t saved_mask; | 640 | cpumask_t saved_mask; |
600 | int retval; | 641 | cpumask_t set_mask; |
642 | cpumask_t covered_cpus; | ||
643 | int retval = 0; | ||
644 | unsigned int j, k, first_cpu, tmp; | ||
601 | 645 | ||
602 | if (centrino_model[cpu] == NULL) | 646 | if (unlikely(centrino_model[cpu] == NULL)) |
603 | return -ENODEV; | 647 | return -ENODEV; |
604 | 648 | ||
605 | /* | 649 | if (unlikely(cpufreq_frequency_table_target(policy, |
606 | * Support for SMP systems. | 650 | centrino_model[cpu]->op_points, |
607 | * Make sure we are running on the CPU that wants to change frequency | 651 | target_freq, |
608 | */ | 652 | relation, |
609 | saved_mask = current->cpus_allowed; | 653 | &newstate))) { |
610 | set_cpus_allowed(current, policy->cpus); | 654 | return -EINVAL; |
611 | if (!cpu_isset(smp_processor_id(), policy->cpus)) { | ||
612 | dprintk("couldn't limit to CPUs in this domain\n"); | ||
613 | return(-EAGAIN); | ||
614 | } | 655 | } |
615 | 656 | ||
616 | if (cpufreq_frequency_table_target(policy, centrino_model[cpu]->op_points, target_freq, | 657 | /* cpufreq holds the hotplug lock, so we are safe from here on */ |
617 | relation, &newstate)) { | 658 | cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); |
618 | retval = -EINVAL; | ||
619 | goto migrate_end; | ||
620 | } | ||
621 | 659 | ||
622 | msr = centrino_model[cpu]->op_points[newstate].index; | 660 | saved_mask = current->cpus_allowed; |
623 | rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); | 661 | first_cpu = 1; |
662 | cpus_clear(covered_cpus); | ||
663 | for_each_cpu_mask(j, online_policy_cpus) { | ||
664 | /* | ||
665 | * Support for SMP systems. | ||
666 | * Make sure we are running on CPU that wants to change freq | ||
667 | */ | ||
668 | cpus_clear(set_mask); | ||
669 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) | ||
670 | cpus_or(set_mask, set_mask, online_policy_cpus); | ||
671 | else | ||
672 | cpu_set(j, set_mask); | ||
624 | 673 | ||
625 | if (msr == (oldmsr & 0xffff)) { | 674 | set_cpus_allowed(current, set_mask); |
626 | retval = 0; | 675 | if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) { |
627 | dprintk("no change needed - msr was and needs to be %x\n", oldmsr); | 676 | dprintk("couldn't limit to CPUs in this domain\n"); |
628 | goto migrate_end; | 677 | retval = -EAGAIN; |
629 | } | 678 | if (first_cpu) { |
679 | /* We haven't started the transition yet. */ | ||
680 | goto migrate_end; | ||
681 | } | ||
682 | break; | ||
683 | } | ||
630 | 684 | ||
631 | freqs.cpu = cpu; | 685 | msr = centrino_model[cpu]->op_points[newstate].index; |
632 | freqs.old = extract_clock(oldmsr, cpu, 0); | ||
633 | freqs.new = extract_clock(msr, cpu, 0); | ||
634 | 686 | ||
635 | dprintk("target=%dkHz old=%d new=%d msr=%04x\n", | 687 | if (first_cpu) { |
636 | target_freq, freqs.old, freqs.new, msr); | 688 | rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); |
689 | if (msr == (oldmsr & 0xffff)) { | ||
690 | dprintk("no change needed - msr was and needs " | ||
691 | "to be %x\n", oldmsr); | ||
692 | retval = 0; | ||
693 | goto migrate_end; | ||
694 | } | ||
637 | 695 | ||
638 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 696 | freqs.old = extract_clock(oldmsr, cpu, 0); |
697 | freqs.new = extract_clock(msr, cpu, 0); | ||
639 | 698 | ||
640 | /* all but 16 LSB are "reserved", so treat them with | 699 | dprintk("target=%dkHz old=%d new=%d msr=%04x\n", |
641 | care */ | 700 | target_freq, freqs.old, freqs.new, msr); |
642 | oldmsr &= ~0xffff; | ||
643 | msr &= 0xffff; | ||
644 | oldmsr |= msr; | ||
645 | 701 | ||
646 | wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); | 702 | for_each_cpu_mask(k, online_policy_cpus) { |
703 | freqs.cpu = k; | ||
704 | cpufreq_notify_transition(&freqs, | ||
705 | CPUFREQ_PRECHANGE); | ||
706 | } | ||
647 | 707 | ||
648 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 708 | first_cpu = 0; |
709 | /* all but 16 LSB are reserved, treat them with care */ | ||
710 | oldmsr &= ~0xffff; | ||
711 | msr &= 0xffff; | ||
712 | oldmsr |= msr; | ||
713 | } | ||
649 | 714 | ||
650 | retval = 0; | 715 | wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); |
716 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) | ||
717 | break; | ||
718 | |||
719 | cpu_set(j, covered_cpus); | ||
720 | } | ||
721 | |||
722 | for_each_cpu_mask(k, online_policy_cpus) { | ||
723 | freqs.cpu = k; | ||
724 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
725 | } | ||
726 | |||
727 | if (unlikely(retval)) { | ||
728 | /* | ||
729 | * We have failed halfway through the frequency change. | ||
730 | * We have sent callbacks to policy->cpus and | ||
731 | * MSRs have already been written on coverd_cpus. | ||
732 | * Best effort undo.. | ||
733 | */ | ||
734 | |||
735 | if (!cpus_empty(covered_cpus)) { | ||
736 | for_each_cpu_mask(j, covered_cpus) { | ||
737 | set_cpus_allowed(current, cpumask_of_cpu(j)); | ||
738 | wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | tmp = freqs.new; | ||
743 | freqs.new = freqs.old; | ||
744 | freqs.old = tmp; | ||
745 | for_each_cpu_mask(j, online_policy_cpus) { | ||
746 | freqs.cpu = j; | ||
747 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
748 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
749 | } | ||
750 | } | ||
751 | |||
651 | migrate_end: | 752 | migrate_end: |
652 | set_cpus_allowed(current, saved_mask); | 753 | set_cpus_allowed(current, saved_mask); |
653 | return (retval); | 754 | return 0; |
654 | } | 755 | } |
655 | 756 | ||
656 | static struct freq_attr* centrino_attr[] = { | 757 | static struct freq_attr* centrino_attr[] = { |
657 | &cpufreq_freq_attr_scaling_available_freqs, | 758 | &cpufreq_freq_attr_scaling_available_freqs, |
658 | NULL, | 759 | NULL, |
659 | }; | 760 | }; |
660 | 761 | ||
661 | static struct cpufreq_driver centrino_driver = { | 762 | static struct cpufreq_driver centrino_driver = { |
662 | .name = "centrino", /* should be speedstep-centrino, | 763 | .name = "centrino", /* should be speedstep-centrino, |
663 | but there's a 16 char limit */ | 764 | but there's a 16 char limit */ |
664 | .init = centrino_cpu_init, | 765 | .init = centrino_cpu_init, |
665 | .exit = centrino_cpu_exit, | 766 | .exit = centrino_cpu_exit, |
666 | .verify = centrino_verify, | 767 | .verify = centrino_verify, |
667 | .target = centrino_target, | 768 | .target = centrino_target, |
668 | .get = get_cur_freq, | 769 | .get = get_cur_freq, |
669 | .attr = centrino_attr, | 770 | .attr = centrino_attr, |
670 | .owner = THIS_MODULE, | 771 | .owner = THIS_MODULE, |
671 | }; | 772 | }; |
672 | 773 | ||
673 | 774 | ||
674 | /** | 775 | /** |
675 | * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver | 776 | * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver |
676 | * | 777 | * |
677 | * Initializes the Enhanced SpeedStep support. Returns -ENODEV on | 778 | * Initializes the Enhanced SpeedStep support. Returns -ENODEV on |
678 | * unsupported devices, -ENOENT if there's no voltage table for this | 779 | * unsupported devices, -ENOENT if there's no voltage table for this |
679 | * particular CPU model, -EINVAL on problems during initiatization, | 780 | * particular CPU model, -EINVAL on problems during initiatization, |
680 | * and zero on success. | 781 | * and zero on success. |
681 | * | 782 | * |
682 | * This is quite picky. Not only does the CPU have to advertise the | 783 | * This is quite picky. Not only does the CPU have to advertise the |
683 | * "est" flag in the cpuid capability flags, we look for a specific | 784 | * "est" flag in the cpuid capability flags, we look for a specific |
684 | * CPU model and stepping, and we need to have the exact model name in | 785 | * CPU model and stepping, and we need to have the exact model name in |
685 | * our voltage tables. That is, be paranoid about not releasing | 786 | * our voltage tables. That is, be paranoid about not releasing |
686 | * someone's valuable magic smoke. | 787 | * someone's valuable magic smoke. |
687 | */ | 788 | */ |
688 | static int __init centrino_init(void) | 789 | static int __init centrino_init(void) |
689 | { | 790 | { |
690 | struct cpuinfo_x86 *cpu = cpu_data; | 791 | struct cpuinfo_x86 *cpu = cpu_data; |
691 | 792 | ||
692 | if (!cpu_has(cpu, X86_FEATURE_EST)) | 793 | if (!cpu_has(cpu, X86_FEATURE_EST)) |
693 | return -ENODEV; | 794 | return -ENODEV; |
694 | 795 | ||
796 | centrino_cpu_early_init_acpi(); | ||
797 | |||
695 | return cpufreq_register_driver(¢rino_driver); | 798 | return cpufreq_register_driver(¢rino_driver); |
696 | } | 799 | } |
697 | 800 | ||
698 | static void __exit centrino_exit(void) | 801 | static void __exit centrino_exit(void) |
699 | { | 802 | { |
803 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
804 | unsigned int j; | ||
805 | #endif | ||
806 | |||
700 | cpufreq_unregister_driver(¢rino_driver); | 807 | cpufreq_unregister_driver(¢rino_driver); |
808 | |||
809 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
810 | for_each_cpu(j) { | ||
811 | kfree(acpi_perf_data[j]); | ||
812 | acpi_perf_data[j] = NULL; |