Commit 4b31e77455b868b43e665edceb111c9a330c8e0f

Authored by Dominik Brodowski
Committed by Len Brown
1 parent 45bea1555f

[ACPI] Always set P-state on initialization

Otherwise a platform that supports ACPI based cpufreq
and boots up at lowest possible speed could stay there
forever.  This because the governor may request max speed,
but the code doesn't update if there is no change in
speed, and it assumed the initial state of max speed.

http://bugzilla.kernel.org/show_bug.cgi?id=4634

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

Showing 1 changed file with 7 additions and 0 deletions Inline Diff

arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
1 /* 1 /*
2 * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $) 2 * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $)
3 * 3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de> 6 * Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
7 * 7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at 12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version. 13 * your option) any later version.
14 * 14 *
15 * This program is distributed in the hope that it will be useful, but 15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details. 18 * General Public License for more details.
19 * 19 *
20 * You should have received a copy of the GNU General Public License along 20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc., 21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 * 23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */ 25 */
26 26
27 #include <linux/config.h> 27 #include <linux/config.h>
28 #include <linux/kernel.h> 28 #include <linux/kernel.h>
29 #include <linux/module.h> 29 #include <linux/module.h>
30 #include <linux/init.h> 30 #include <linux/init.h>
31 #include <linux/cpufreq.h> 31 #include <linux/cpufreq.h>
32 #include <linux/proc_fs.h> 32 #include <linux/proc_fs.h>
33 #include <linux/seq_file.h> 33 #include <linux/seq_file.h>
34 #include <asm/io.h> 34 #include <asm/io.h>
35 #include <asm/delay.h> 35 #include <asm/delay.h>
36 #include <asm/uaccess.h> 36 #include <asm/uaccess.h>
37 37
38 #include <linux/acpi.h> 38 #include <linux/acpi.h>
39 #include <acpi/processor.h> 39 #include <acpi/processor.h>
40 40
41 #include "speedstep-est-common.h" 41 #include "speedstep-est-common.h"
42 42
43 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg) 43 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
44 44
45 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski"); 45 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
46 MODULE_DESCRIPTION("ACPI Processor P-States Driver"); 46 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
47 MODULE_LICENSE("GPL"); 47 MODULE_LICENSE("GPL");
48 48
49 49
50 struct cpufreq_acpi_io { 50 struct cpufreq_acpi_io {
51 struct acpi_processor_performance acpi_data; 51 struct acpi_processor_performance acpi_data;
52 struct cpufreq_frequency_table *freq_table; 52 struct cpufreq_frequency_table *freq_table;
53 unsigned int resume; 53 unsigned int resume;
54 }; 54 };
55 55
56 static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; 56 static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
57 57
58 static struct cpufreq_driver acpi_cpufreq_driver; 58 static struct cpufreq_driver acpi_cpufreq_driver;
59 59
60 static int 60 static int
61 acpi_processor_write_port( 61 acpi_processor_write_port(
62 u16 port, 62 u16 port,
63 u8 bit_width, 63 u8 bit_width,
64 u32 value) 64 u32 value)
65 { 65 {
66 if (bit_width <= 8) { 66 if (bit_width <= 8) {
67 outb(value, port); 67 outb(value, port);
68 } else if (bit_width <= 16) { 68 } else if (bit_width <= 16) {
69 outw(value, port); 69 outw(value, port);
70 } else if (bit_width <= 32) { 70 } else if (bit_width <= 32) {
71 outl(value, port); 71 outl(value, port);
72 } else { 72 } else {
73 return -ENODEV; 73 return -ENODEV;
74 } 74 }
75 return 0; 75 return 0;
76 } 76 }
77 77
78 static int 78 static int
79 acpi_processor_read_port( 79 acpi_processor_read_port(
80 u16 port, 80 u16 port,
81 u8 bit_width, 81 u8 bit_width,
82 u32 *ret) 82 u32 *ret)
83 { 83 {
84 *ret = 0; 84 *ret = 0;
85 if (bit_width <= 8) { 85 if (bit_width <= 8) {
86 *ret = inb(port); 86 *ret = inb(port);
87 } else if (bit_width <= 16) { 87 } else if (bit_width <= 16) {
88 *ret = inw(port); 88 *ret = inw(port);
89 } else if (bit_width <= 32) { 89 } else if (bit_width <= 32) {
90 *ret = inl(port); 90 *ret = inl(port);
91 } else { 91 } else {
92 return -ENODEV; 92 return -ENODEV;
93 } 93 }
94 return 0; 94 return 0;
95 } 95 }
96 96
97 static int 97 static int
98 acpi_processor_set_performance ( 98 acpi_processor_set_performance (
99 struct cpufreq_acpi_io *data, 99 struct cpufreq_acpi_io *data,
100 unsigned int cpu, 100 unsigned int cpu,
101 int state) 101 int state)
102 { 102 {
103 u16 port = 0; 103 u16 port = 0;
104 u8 bit_width = 0; 104 u8 bit_width = 0;
105 int ret = 0; 105 int ret = 0;
106 u32 value = 0; 106 u32 value = 0;
107 int i = 0; 107 int i = 0;
108 struct cpufreq_freqs cpufreq_freqs; 108 struct cpufreq_freqs cpufreq_freqs;
109 cpumask_t saved_mask; 109 cpumask_t saved_mask;
110 int retval; 110 int retval;
111 111
112 dprintk("acpi_processor_set_performance\n"); 112 dprintk("acpi_processor_set_performance\n");
113 113
114 /* 114 /*
115 * TBD: Use something other than set_cpus_allowed. 115 * TBD: Use something other than set_cpus_allowed.
116 * As set_cpus_allowed is a bit racy, 116 * As set_cpus_allowed is a bit racy,
117 * with any other set_cpus_allowed for this process. 117 * with any other set_cpus_allowed for this process.
118 */ 118 */
119 saved_mask = current->cpus_allowed; 119 saved_mask = current->cpus_allowed;
120 set_cpus_allowed(current, cpumask_of_cpu(cpu)); 120 set_cpus_allowed(current, cpumask_of_cpu(cpu));
121 if (smp_processor_id() != cpu) { 121 if (smp_processor_id() != cpu) {
122 return (-EAGAIN); 122 return (-EAGAIN);
123 } 123 }
124 124
125 if (state == data->acpi_data.state) { 125 if (state == data->acpi_data.state) {
126 if (unlikely(data->resume)) { 126 if (unlikely(data->resume)) {
127 dprintk("Called after resume, resetting to P%d\n", state); 127 dprintk("Called after resume, resetting to P%d\n", state);
128 data->resume = 0; 128 data->resume = 0;
129 } else { 129 } else {
130 dprintk("Already at target state (P%d)\n", state); 130 dprintk("Already at target state (P%d)\n", state);
131 retval = 0; 131 retval = 0;
132 goto migrate_end; 132 goto migrate_end;
133 } 133 }
134 } 134 }
135 135
136 dprintk("Transitioning from P%d to P%d\n", 136 dprintk("Transitioning from P%d to P%d\n",
137 data->acpi_data.state, state); 137 data->acpi_data.state, state);
138 138
139 /* cpufreq frequency struct */ 139 /* cpufreq frequency struct */
140 cpufreq_freqs.cpu = cpu; 140 cpufreq_freqs.cpu = cpu;
141 cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency; 141 cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
142 cpufreq_freqs.new = data->freq_table[state].frequency; 142 cpufreq_freqs.new = data->freq_table[state].frequency;
143 143
144 /* notify cpufreq */ 144 /* notify cpufreq */
145 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); 145 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
146 146
147 /* 147 /*
148 * First we write the target state's 'control' value to the 148 * First we write the target state's 'control' value to the
149 * control_register. 149 * control_register.
150 */ 150 */
151 151
152 port = data->acpi_data.control_register.address; 152 port = data->acpi_data.control_register.address;
153 bit_width = data->acpi_data.control_register.bit_width; 153 bit_width = data->acpi_data.control_register.bit_width;
154 value = (u32) data->acpi_data.states[state].control; 154 value = (u32) data->acpi_data.states[state].control;
155 155
156 dprintk("Writing 0x%08x to port 0x%04x\n", value, port); 156 dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
157 157
158 ret = acpi_processor_write_port(port, bit_width, value); 158 ret = acpi_processor_write_port(port, bit_width, value);
159 if (ret) { 159 if (ret) {
160 dprintk("Invalid port width 0x%04x\n", bit_width); 160 dprintk("Invalid port width 0x%04x\n", bit_width);
161 retval = ret; 161 retval = ret;
162 goto migrate_end; 162 goto migrate_end;
163 } 163 }
164 164
165 /* 165 /*
166 * Then we read the 'status_register' and compare the value with the 166 * Then we read the 'status_register' and compare the value with the
167 * target state's 'status' to make sure the transition was successful. 167 * target state's 'status' to make sure the transition was successful.
168 * Note that we'll poll for up to 1ms (100 cycles of 10us) before 168 * Note that we'll poll for up to 1ms (100 cycles of 10us) before
169 * giving up. 169 * giving up.
170 */ 170 */
171 171
172 port = data->acpi_data.status_register.address; 172 port = data->acpi_data.status_register.address;
173 bit_width = data->acpi_data.status_register.bit_width; 173 bit_width = data->acpi_data.status_register.bit_width;
174 174
175 dprintk("Looking for 0x%08x from port 0x%04x\n", 175 dprintk("Looking for 0x%08x from port 0x%04x\n",
176 (u32) data->acpi_data.states[state].status, port); 176 (u32) data->acpi_data.states[state].status, port);
177 177
178 for (i=0; i<100; i++) { 178 for (i=0; i<100; i++) {
179 ret = acpi_processor_read_port(port, bit_width, &value); 179 ret = acpi_processor_read_port(port, bit_width, &value);
180 if (ret) { 180 if (ret) {
181 dprintk("Invalid port width 0x%04x\n", bit_width); 181 dprintk("Invalid port width 0x%04x\n", bit_width);
182 retval = ret; 182 retval = ret;
183 goto migrate_end; 183 goto migrate_end;
184 } 184 }
185 if (value == (u32) data->acpi_data.states[state].status) 185 if (value == (u32) data->acpi_data.states[state].status)
186 break; 186 break;
187 udelay(10); 187 udelay(10);
188 } 188 }
189 189
190 /* notify cpufreq */ 190 /* notify cpufreq */
191 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); 191 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
192 192
193 if (value != (u32) data->acpi_data.states[state].status) { 193 if (value != (u32) data->acpi_data.states[state].status) {
194 unsigned int tmp = cpufreq_freqs.new; 194 unsigned int tmp = cpufreq_freqs.new;
195 cpufreq_freqs.new = cpufreq_freqs.old; 195 cpufreq_freqs.new = cpufreq_freqs.old;
196 cpufreq_freqs.old = tmp; 196 cpufreq_freqs.old = tmp;
197 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); 197 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
198 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); 198 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
199 printk(KERN_WARNING "acpi-cpufreq: Transition failed\n"); 199 printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
200 retval = -ENODEV; 200 retval = -ENODEV;
201 goto migrate_end; 201 goto migrate_end;
202 } 202 }
203 203
204 dprintk("Transition successful after %d microseconds\n", i * 10); 204 dprintk("Transition successful after %d microseconds\n", i * 10);
205 205
206 data->acpi_data.state = state; 206 data->acpi_data.state = state;
207 207
208 retval = 0; 208 retval = 0;
209 migrate_end: 209 migrate_end:
210 set_cpus_allowed(current, saved_mask); 210 set_cpus_allowed(current, saved_mask);
211 return (retval); 211 return (retval);
212 } 212 }
213 213
214 214
215 static int 215 static int
216 acpi_cpufreq_target ( 216 acpi_cpufreq_target (
217 struct cpufreq_policy *policy, 217 struct cpufreq_policy *policy,
218 unsigned int target_freq, 218 unsigned int target_freq,
219 unsigned int relation) 219 unsigned int relation)
220 { 220 {
221 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; 221 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
222 unsigned int next_state = 0; 222 unsigned int next_state = 0;
223 unsigned int result = 0; 223 unsigned int result = 0;
224 224
225 dprintk("acpi_cpufreq_setpolicy\n"); 225 dprintk("acpi_cpufreq_setpolicy\n");
226 226
227 result = cpufreq_frequency_table_target(policy, 227 result = cpufreq_frequency_table_target(policy,
228 data->freq_table, 228 data->freq_table,
229 target_freq, 229 target_freq,
230 relation, 230 relation,
231 &next_state); 231 &next_state);
232 if (result) 232 if (result)
233 return (result); 233 return (result);
234 234
235 result = acpi_processor_set_performance (data, policy->cpu, next_state); 235 result = acpi_processor_set_performance (data, policy->cpu, next_state);
236 236
237 return (result); 237 return (result);
238 } 238 }
239 239
240 240
241 static int 241 static int
242 acpi_cpufreq_verify ( 242 acpi_cpufreq_verify (
243 struct cpufreq_policy *policy) 243 struct cpufreq_policy *policy)
244 { 244 {
245 unsigned int result = 0; 245 unsigned int result = 0;
246 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; 246 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
247 247
248 dprintk("acpi_cpufreq_verify\n"); 248 dprintk("acpi_cpufreq_verify\n");
249 249
250 result = cpufreq_frequency_table_verify(policy, 250 result = cpufreq_frequency_table_verify(policy,
251 data->freq_table); 251 data->freq_table);
252 252
253 return (result); 253 return (result);
254 } 254 }
255 255
256 256
257 static unsigned long 257 static unsigned long
258 acpi_cpufreq_guess_freq ( 258 acpi_cpufreq_guess_freq (
259 struct cpufreq_acpi_io *data, 259 struct cpufreq_acpi_io *data,
260 unsigned int cpu) 260 unsigned int cpu)
261 { 261 {
262 if (cpu_khz) { 262 if (cpu_khz) {
263 /* search the closest match to cpu_khz */ 263 /* search the closest match to cpu_khz */
264 unsigned int i; 264 unsigned int i;
265 unsigned long freq; 265 unsigned long freq;
266 unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000; 266 unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
267 267
268 for (i=0; i < (data->acpi_data.state_count - 1); i++) { 268 for (i=0; i < (data->acpi_data.state_count - 1); i++) {
269 freq = freqn; 269 freq = freqn;
270 freqn = data->acpi_data.states[i+1].core_frequency * 1000; 270 freqn = data->acpi_data.states[i+1].core_frequency * 1000;
271 if ((2 * cpu_khz) > (freqn + freq)) { 271 if ((2 * cpu_khz) > (freqn + freq)) {
272 data->acpi_data.state = i; 272 data->acpi_data.state = i;
273 return (freq); 273 return (freq);
274 } 274 }
275 } 275 }
276 data->acpi_data.state = data->acpi_data.state_count - 1; 276 data->acpi_data.state = data->acpi_data.state_count - 1;
277 return (freqn); 277 return (freqn);
278 } else 278 } else
279 /* assume CPU is at P0... */ 279 /* assume CPU is at P0... */
280 data->acpi_data.state = 0; 280 data->acpi_data.state = 0;
281 return data->acpi_data.states[0].core_frequency * 1000; 281 return data->acpi_data.states[0].core_frequency * 1000;
282 282
283 } 283 }
284 284
285 285
286 /* 286 /*
287 * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities 287 * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
288 * of this driver 288 * of this driver
289 * @perf: processor-specific acpi_io_data struct 289 * @perf: processor-specific acpi_io_data struct
290 * @cpu: CPU being initialized 290 * @cpu: CPU being initialized
291 * 291 *
292 * To avoid issues with legacy OSes, some BIOSes require to be informed of 292 * To avoid issues with legacy OSes, some BIOSes require to be informed of
293 * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC 293 * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
294 * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in 294 * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
295 * driver/acpi/processor.c 295 * driver/acpi/processor.c
296 */ 296 */
297 static void 297 static void
298 acpi_processor_cpu_init_pdc_est( 298 acpi_processor_cpu_init_pdc_est(
299 struct acpi_processor_performance *perf, 299 struct acpi_processor_performance *perf,
300 unsigned int cpu, 300 unsigned int cpu,
301 struct acpi_object_list *obj_list 301 struct acpi_object_list *obj_list
302 ) 302 )
303 { 303 {
304 union acpi_object *obj; 304 union acpi_object *obj;
305 u32 *buf; 305 u32 *buf;
306 struct cpuinfo_x86 *c = cpu_data + cpu; 306 struct cpuinfo_x86 *c = cpu_data + cpu;
307 dprintk("acpi_processor_cpu_init_pdc_est\n"); 307 dprintk("acpi_processor_cpu_init_pdc_est\n");
308 308
309 if (!cpu_has(c, X86_FEATURE_EST)) 309 if (!cpu_has(c, X86_FEATURE_EST))
310 return; 310 return;
311 311
312 /* Initialize pdc. It will be used later. */ 312 /* Initialize pdc. It will be used later. */
313 if (!obj_list) 313 if (!obj_list)
314 return; 314 return;
315 315
316 if (!(obj_list->count && obj_list->pointer)) 316 if (!(obj_list->count && obj_list->pointer))
317 return; 317 return;
318 318
319 obj = obj_list->pointer; 319 obj = obj_list->pointer;
320 if ((obj->buffer.length == 12) && obj->buffer.pointer) { 320 if ((obj->buffer.length == 12) && obj->buffer.pointer) {
321 buf = (u32 *)obj->buffer.pointer; 321 buf = (u32 *)obj->buffer.pointer;
322 buf[0] = ACPI_PDC_REVISION_ID; 322 buf[0] = ACPI_PDC_REVISION_ID;
323 buf[1] = 1; 323 buf[1] = 1;
324 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; 324 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
325 perf->pdc = obj_list; 325 perf->pdc = obj_list;
326 } 326 }
327 return; 327 return;
328 } 328 }
329 329
330 330
331 /* CPU specific PDC initialization */ 331 /* CPU specific PDC initialization */
332 static void 332 static void
333 acpi_processor_cpu_init_pdc( 333 acpi_processor_cpu_init_pdc(
334 struct acpi_processor_performance *perf, 334 struct acpi_processor_performance *perf,
335 unsigned int cpu, 335 unsigned int cpu,
336 struct acpi_object_list *obj_list 336 struct acpi_object_list *obj_list
337 ) 337 )
338 { 338 {
339 struct cpuinfo_x86 *c = cpu_data + cpu; 339 struct cpuinfo_x86 *c = cpu_data + cpu;
340 dprintk("acpi_processor_cpu_init_pdc\n"); 340 dprintk("acpi_processor_cpu_init_pdc\n");
341 perf->pdc = NULL; 341 perf->pdc = NULL;
342 if (cpu_has(c, X86_FEATURE_EST)) 342 if (cpu_has(c, X86_FEATURE_EST))
343 acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list); 343 acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
344 return; 344 return;
345 } 345 }
346 346
347 347
348 static int 348 static int
349 acpi_cpufreq_cpu_init ( 349 acpi_cpufreq_cpu_init (
350 struct cpufreq_policy *policy) 350 struct cpufreq_policy *policy)
351 { 351 {
352 unsigned int i; 352 unsigned int i;
353 unsigned int cpu = policy->cpu; 353 unsigned int cpu = policy->cpu;
354 struct cpufreq_acpi_io *data; 354 struct cpufreq_acpi_io *data;
355 unsigned int result = 0; 355 unsigned int result = 0;
356 356
357 union acpi_object arg0 = {ACPI_TYPE_BUFFER}; 357 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
358 u32 arg0_buf[3]; 358 u32 arg0_buf[3];
359 struct acpi_object_list arg_list = {1, &arg0}; 359 struct acpi_object_list arg_list = {1, &arg0};
360 360
361 dprintk("acpi_cpufreq_cpu_init\n"); 361 dprintk("acpi_cpufreq_cpu_init\n");
362 /* setup arg_list for _PDC settings */ 362 /* setup arg_list for _PDC settings */
363 arg0.buffer.length = 12; 363 arg0.buffer.length = 12;
364 arg0.buffer.pointer = (u8 *) arg0_buf; 364 arg0.buffer.pointer = (u8 *) arg0_buf;
365 365
366 data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); 366 data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
367 if (!data) 367 if (!data)
368 return (-ENOMEM); 368 return (-ENOMEM);
369 memset(data, 0, sizeof(struct cpufreq_acpi_io)); 369 memset(data, 0, sizeof(struct cpufreq_acpi_io));
370 370
371 acpi_io_data[cpu] = data; 371 acpi_io_data[cpu] = data;
372 372
373 acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list); 373 acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
374 result = acpi_processor_register_performance(&data->acpi_data, cpu); 374 result = acpi_processor_register_performance(&data->acpi_data, cpu);
375 data->acpi_data.pdc = NULL; 375 data->acpi_data.pdc = NULL;
376 376
377 if (result) 377 if (result)
378 goto err_free; 378 goto err_free;
379 379
380 if (is_const_loops_cpu(cpu)) { 380 if (is_const_loops_cpu(cpu)) {
381 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; 381 acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
382 } 382 }
383 383
384 /* capability check */ 384 /* capability check */
385 if (data->acpi_data.state_count <= 1) { 385 if (data->acpi_data.state_count <= 1) {
386 dprintk("No P-States\n"); 386 dprintk("No P-States\n");
387 result = -ENODEV; 387 result = -ENODEV;
388 goto err_unreg; 388 goto err_unreg;
389 } 389 }
390 if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) || 390 if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
391 (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 391 (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
392 dprintk("Unsupported address space [%d, %d]\n", 392 dprintk("Unsupported address space [%d, %d]\n",
393 (u32) (data->acpi_data.control_register.space_id), 393 (u32) (data->acpi_data.control_register.space_id),
394 (u32) (data->acpi_data.status_register.space_id)); 394 (u32) (data->acpi_data.status_register.space_id));
395 result = -ENODEV; 395 result = -ENODEV;
396 goto err_unreg; 396 goto err_unreg;
397 } 397 }
398 398
399 /* alloc freq_table */ 399 /* alloc freq_table */
400 data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL); 400 data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL);
401 if (!data->freq_table) { 401 if (!data->freq_table) {
402 result = -ENOMEM; 402 result = -ENOMEM;
403 goto err_unreg; 403 goto err_unreg;
404 } 404 }
405 405
406 /* detect transition latency */ 406 /* detect transition latency */
407 policy->cpuinfo.transition_latency = 0; 407 policy->cpuinfo.transition_latency = 0;
408 for (i=0; i<data->acpi_data.state_count; i++) { 408 for (i=0; i<data->acpi_data.state_count; i++) {
409 if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) 409 if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
410 policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000; 410 policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
411 } 411 }
412 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 412 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
413 413
414 /* The current speed is unknown and not detectable by ACPI... */ 414 /* The current speed is unknown and not detectable by ACPI... */
415 policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); 415 policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
416 416
417 /* table init */ 417 /* table init */
418 for (i=0; i<=data->acpi_data.state_count; i++) 418 for (i=0; i<=data->acpi_data.state_count; i++)
419 { 419 {
420 data->freq_table[i].index = i; 420 data->freq_table[i].index = i;
421 if (i<data->acpi_data.state_count) 421 if (i<data->acpi_data.state_count)
422 data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; 422 data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
423 else 423 else
424 data->freq_table[i].frequency = CPUFREQ_TABLE_END; 424 data->freq_table[i].frequency = CPUFREQ_TABLE_END;
425 } 425 }
426 426
427 result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); 427 result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
428 if (result) { 428 if (result) {
429 goto err_freqfree; 429 goto err_freqfree;
430 } 430 }
431 431
432 /* notify BIOS that we exist */ 432 /* notify BIOS that we exist */
433 acpi_processor_notify_smm(THIS_MODULE); 433 acpi_processor_notify_smm(THIS_MODULE);
434 434
435 printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n", 435 printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
436 cpu); 436 cpu);
437 for (i = 0; i < data->acpi_data.state_count; i++) 437 for (i = 0; i < data->acpi_data.state_count; i++)
438 dprintk(" %cP%d: %d MHz, %d mW, %d uS\n", 438 dprintk(" %cP%d: %d MHz, %d mW, %d uS\n",
439 (i == data->acpi_data.state?'*':' '), i, 439 (i == data->acpi_data.state?'*':' '), i,
440 (u32) data->acpi_data.states[i].core_frequency, 440 (u32) data->acpi_data.states[i].core_frequency,
441 (u32) data->acpi_data.states[i].power, 441 (u32) data->acpi_data.states[i].power,
442 (u32) data->acpi_data.states[i].transition_latency); 442 (u32) data->acpi_data.states[i].transition_latency);
443 443
444 cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); 444 cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
445
446 /*
447 * the first call to ->target() should result in us actually
448 * writing something to the appropriate registers.
449 */
450 data->resume = 1;
451
445 return (result); 452 return (result);
446 453
447 err_freqfree: 454 err_freqfree:
448 kfree(data->freq_table); 455 kfree(data->freq_table);
449 err_unreg: 456 err_unreg:
450 acpi_processor_unregister_performance(&data->acpi_data, cpu); 457 acpi_processor_unregister_performance(&data->acpi_data, cpu);
451 err_free: 458 err_free:
452 kfree(data); 459 kfree(data);
453 acpi_io_data[cpu] = NULL; 460 acpi_io_data[cpu] = NULL;
454 461
455 return (result); 462 return (result);
456 } 463 }
457 464
458 465
459 static int 466 static int
460 acpi_cpufreq_cpu_exit ( 467 acpi_cpufreq_cpu_exit (
461 struct cpufreq_policy *policy) 468 struct cpufreq_policy *policy)
462 { 469 {
463 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; 470 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
464 471
465 472
466 dprintk("acpi_cpufreq_cpu_exit\n"); 473 dprintk("acpi_cpufreq_cpu_exit\n");
467 474
468 if (data) { 475 if (data) {
469 cpufreq_frequency_table_put_attr(policy->cpu); 476 cpufreq_frequency_table_put_attr(policy->cpu);
470 acpi_io_data[policy->cpu] = NULL; 477 acpi_io_data[policy->cpu] = NULL;
471 acpi_processor_unregister_performance(&data->acpi_data, policy->cpu); 478 acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
472 kfree(data); 479 kfree(data);
473 } 480 }
474 481
475 return (0); 482 return (0);
476 } 483 }
477 484
478 static int 485 static int
479 acpi_cpufreq_resume ( 486 acpi_cpufreq_resume (
480 struct cpufreq_policy *policy) 487 struct cpufreq_policy *policy)
481 { 488 {
482 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; 489 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
483 490
484 491
485 dprintk("acpi_cpufreq_resume\n"); 492 dprintk("acpi_cpufreq_resume\n");
486 493
487 data->resume = 1; 494 data->resume = 1;
488 495
489 return (0); 496 return (0);
490 } 497 }
491 498
492 499
493 static struct freq_attr* acpi_cpufreq_attr[] = { 500 static struct freq_attr* acpi_cpufreq_attr[] = {
494 &cpufreq_freq_attr_scaling_available_freqs, 501 &cpufreq_freq_attr_scaling_available_freqs,
495 NULL, 502 NULL,
496 }; 503 };
497 504
498 static struct cpufreq_driver acpi_cpufreq_driver = { 505 static struct cpufreq_driver acpi_cpufreq_driver = {
499 .verify = acpi_cpufreq_verify, 506 .verify = acpi_cpufreq_verify,
500 .target = acpi_cpufreq_target, 507 .target = acpi_cpufreq_target,
501 .init = acpi_cpufreq_cpu_init, 508 .init = acpi_cpufreq_cpu_init,
502 .exit = acpi_cpufreq_cpu_exit, 509 .exit = acpi_cpufreq_cpu_exit,
503 .resume = acpi_cpufreq_resume, 510 .resume = acpi_cpufreq_resume,
504 .name = "acpi-cpufreq", 511 .name = "acpi-cpufreq",
505 .owner = THIS_MODULE, 512 .owner = THIS_MODULE,
506 .attr = acpi_cpufreq_attr, 513 .attr = acpi_cpufreq_attr,
507 }; 514 };
508 515
509 516
510 static int __init 517 static int __init
511 acpi_cpufreq_init (void) 518 acpi_cpufreq_init (void)
512 { 519 {
513 int result = 0; 520 int result = 0;
514 521
515 dprintk("acpi_cpufreq_init\n"); 522 dprintk("acpi_cpufreq_init\n");
516 523
517 result = cpufreq_register_driver(&acpi_cpufreq_driver); 524 result = cpufreq_register_driver(&acpi_cpufreq_driver);
518 525
519 return (result); 526 return (result);
520 } 527 }
521 528
522 529
523 static void __exit 530 static void __exit
524 acpi_cpufreq_exit (void) 531 acpi_cpufreq_exit (void)
525 { 532 {
526 dprintk("acpi_cpufreq_exit\n"); 533 dprintk("acpi_cpufreq_exit\n");
527 534
528 cpufreq_unregister_driver(&acpi_cpufreq_driver); 535 cpufreq_unregister_driver(&acpi_cpufreq_driver);
529 536
530 return; 537 return;
531 } 538 }
532 539
533 540
534 late_initcall(acpi_cpufreq_init); 541 late_initcall(acpi_cpufreq_init);
535 module_exit(acpi_cpufreq_exit); 542 module_exit(acpi_cpufreq_exit);
536 543
537 MODULE_ALIAS("acpi"); 544 MODULE_ALIAS("acpi");
538 545