Contents of /trunk/kernel26-alx/patches-2.6.29-r1/0156-2.6.29-linux-phc-0.3.2.patch
Parent Directory | Revision Log
Revision 875 -
(show annotations)
(download)
Tue Aug 4 20:59:11 2009 UTC (15 years, 1 month ago) by niro
File size: 16865 byte(s)
Tue Aug 4 20:59:11 2009 UTC (15 years, 1 month ago) by niro
File size: 16865 byte(s)
-2.6.29-alx-r1
1 | diff --new-file -a --unified=5 --recursive linux-source-2.6.26-rc9_orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-source-2.6.26-rc9-custom8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c |
2 | --- linux-source-2.6.26-rc9_orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2008-07-09 16:59:37.000000000 +0200 |
3 | +++ linux-source-2.6.26-rc9-custom8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2008-07-09 12:41:37.000000000 +0200 |
4 | @@ -23,10 +23,14 @@ |
5 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
6 | * |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
8 | */ |
9 | |
10 | +/* This file has been patched with Linux PHC: http://phc.athousandnights.de |
11 | + * Patch version: linux-phc-0.3.1-kernel-vanilla-2.6.26.patch |
12 | + */ |
13 | + |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/init.h> |
17 | #include <linux/smp.h> |
18 | #include <linux/sched.h> |
19 | @@ -56,17 +60,22 @@ |
20 | SYSTEM_IO_CAPABLE, |
21 | }; |
22 | |
23 | #define INTEL_MSR_RANGE (0xffff) |
24 | #define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1) |
25 | +#define INTEL_MSR_VID_MASK (0x00ff) |
26 | +#define INTEL_MSR_FID_MASK (0xff00) |
27 | +#define INTEL_MSR_FID_SHIFT (0x8) |
28 | +#define PHC_VERSION_STRING "0.3.2:1" |
29 | |
30 | struct acpi_cpufreq_data { |
31 | struct acpi_processor_performance *acpi_data; |
32 | struct cpufreq_frequency_table *freq_table; |
33 | unsigned int max_freq; |
34 | unsigned int resume; |
35 | unsigned int cpu_feature; |
36 | + acpi_integer *original_controls; |
37 | }; |
38 | |
39 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data); |
40 | |
41 | /* acpi_perf_data is a pointer to percpu data. */ |
42 | @@ -102,17 +111,18 @@ |
43 | } |
44 | |
45 | static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data) |
46 | { |
47 | int i; |
48 | + u32 fid; |
49 | struct acpi_processor_performance *perf; |
50 | |
51 | - msr &= INTEL_MSR_RANGE; |
52 | + fid = msr & INTEL_MSR_FID_MASK; |
53 | perf = data->acpi_data; |
54 | |
55 | for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
56 | - if (msr == perf->states[data->freq_table[i].index].status) |
57 | + if (fid == (perf->states[data->freq_table[i].index].status & INTEL_MSR_FID_MASK)) |
58 | return data->freq_table[i].frequency; |
59 | } |
60 | return data->freq_table[0].frequency; |
61 | } |
62 | |
63 | @@ -740,10 +750,12 @@ |
64 | if (data) { |
65 | cpufreq_frequency_table_put_attr(policy->cpu); |
66 | per_cpu(drv_data, policy->cpu) = NULL; |
67 | acpi_processor_unregister_performance(data->acpi_data, |
68 | policy->cpu); |
69 | + if (data->original_controls) |
70 | + kfree(data->original_controls); |
71 | kfree(data); |
72 | } |
73 | |
74 | return 0; |
75 | } |
76 | @@ -757,12 +769,477 @@ |
77 | data->resume = 1; |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | + |
83 | + |
84 | + |
85 | +/* sysfs interface to change operating points voltages */ |
86 | + |
87 | +static unsigned int extract_fid_from_control(unsigned int control) |
88 | +{ |
89 | + return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT); |
90 | +} |
91 | + |
92 | +static unsigned int extract_vid_from_control(unsigned int control) |
93 | +{ |
94 | + return (control & INTEL_MSR_VID_MASK); |
95 | +} |
96 | + |
97 | + |
98 | +static bool check_cpu_control_capability(struct acpi_cpufreq_data *data) { |
99 | + /* check if the cpu we are running on is capable of setting new control data |
100 | + * |
101 | + */ |
102 | + if (unlikely(data == NULL || |
103 | + data->acpi_data == NULL || |
104 | + data->freq_table == NULL || |
105 | + data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) { |
106 | + return false; |
107 | + } else { |
108 | + return true; |
109 | + }; |
110 | +} |
111 | + |
112 | + |
113 | +static ssize_t check_origial_table (struct acpi_cpufreq_data *data) |
114 | +{ |
115 | + |
116 | + struct acpi_processor_performance *acpi_data; |
117 | + struct cpufreq_frequency_table *freq_table; |
118 | + unsigned int state_index; |
119 | + |
120 | + acpi_data = data->acpi_data; |
121 | + freq_table = data->freq_table; |
122 | + |
123 | + if (data->original_controls == NULL) { |
124 | + // Backup original control values |
125 | + data->original_controls = kcalloc(acpi_data->state_count, |
126 | + sizeof(acpi_integer), GFP_KERNEL); |
127 | + if (data->original_controls == NULL) { |
128 | + printk("failed to allocate memory for original control values\n"); |
129 | + return -ENOMEM; |
130 | + } |
131 | + for (state_index = 0; state_index < acpi_data->state_count; state_index++) { |
132 | + data->original_controls[state_index] = acpi_data->states[state_index].control; |
133 | + } |
134 | + } |
135 | + return 0; |
136 | +} |
137 | + |
138 | +static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf) |
139 | + /* display phc's voltage id's |
140 | + * |
141 | + */ |
142 | +{ |
143 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
144 | + struct acpi_processor_performance *acpi_data; |
145 | + struct cpufreq_frequency_table *freq_table; |
146 | + unsigned int i; |
147 | + unsigned int vid; |
148 | + ssize_t count = 0; |
149 | + |
150 | + if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls |
151 | + |
152 | + acpi_data = data->acpi_data; |
153 | + freq_table = data->freq_table; |
154 | + |
155 | + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
156 | + vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control); |
157 | + count += sprintf(&buf[count], "%u ", vid); |
158 | + } |
159 | + count += sprintf(&buf[count], "\n"); |
160 | + |
161 | + return count; |
162 | +} |
163 | + |
164 | +static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf) |
165 | + /* display acpi's default voltage id's |
166 | + * |
167 | + */ |
168 | +{ |
169 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
170 | + struct cpufreq_frequency_table *freq_table; |
171 | + unsigned int i; |
172 | + unsigned int vid; |
173 | + ssize_t count = 0; |
174 | + ssize_t retval; |
175 | + |
176 | + if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls |
177 | + |
178 | + retval = check_origial_table(data); |
179 | + if (0 != retval) |
180 | + return retval; |
181 | + |
182 | + freq_table = data->freq_table; |
183 | + |
184 | + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
185 | + vid = extract_vid_from_control(data->original_controls[freq_table[i].index]); |
186 | + count += sprintf(&buf[count], "%u ", vid); |
187 | + } |
188 | + count += sprintf(&buf[count], "\n"); |
189 | + |
190 | + return count; |
191 | +} |
192 | + |
193 | +static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf) |
194 | + /* display phc's frequeny id's |
195 | + * |
196 | + */ |
197 | +{ |
198 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
199 | + struct acpi_processor_performance *acpi_data; |
200 | + struct cpufreq_frequency_table *freq_table; |
201 | + unsigned int i; |
202 | + unsigned int fid; |
203 | + ssize_t count = 0; |
204 | + |
205 | + if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls |
206 | + |
207 | + acpi_data = data->acpi_data; |
208 | + freq_table = data->freq_table; |
209 | + |
210 | + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
211 | + fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control); |
212 | + count += sprintf(&buf[count], "%u ", fid); |
213 | + } |
214 | + count += sprintf(&buf[count], "\n"); |
215 | + |
216 | + return count; |
217 | +} |
218 | + |
219 | +static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf) |
220 | + /* display phc's controls for the cpu (frequency id's and related voltage id's) |
221 | + * |
222 | + */ |
223 | +{ |
224 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
225 | + struct acpi_processor_performance *acpi_data; |
226 | + struct cpufreq_frequency_table *freq_table; |
227 | + unsigned int i; |
228 | + unsigned int fid; |
229 | + unsigned int vid; |
230 | + ssize_t count = 0; |
231 | + |
232 | + if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls |
233 | + |
234 | + acpi_data = data->acpi_data; |
235 | + freq_table = data->freq_table; |
236 | + |
237 | + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
238 | + fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control); |
239 | + vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control); |
240 | + count += sprintf(&buf[count], "%u:%u ", fid, vid); |
241 | + } |
242 | + count += sprintf(&buf[count], "\n"); |
243 | + |
244 | + return count; |
245 | +} |
246 | + |
247 | +static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf) |
248 | + /* display acpi's default controls for the cpu (frequency id's and related voltage id's) |
249 | + * |
250 | + */ |
251 | +{ |
252 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
253 | + struct cpufreq_frequency_table *freq_table; |
254 | + unsigned int i; |
255 | + unsigned int fid; |
256 | + unsigned int vid; |
257 | + ssize_t count = 0; |
258 | + ssize_t retval; |
259 | + |
260 | + if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls |
261 | + |
262 | + retval = check_origial_table(data); |
263 | + if (0 != retval) |
264 | + return retval; |
265 | + |
266 | + freq_table = data->freq_table; |
267 | + |
268 | + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { |
269 | + fid = extract_fid_from_control(data->original_controls[freq_table[i].index]); |
270 | + vid = extract_vid_from_control(data->original_controls[freq_table[i].index]); |
271 | + count += sprintf(&buf[count], "%u:%u ", fid, vid); |
272 | + } |
273 | + count += sprintf(&buf[count], "\n"); |
274 | + |
275 | + return count; |
276 | +} |
277 | + |
278 | + |
279 | +static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count) |
280 | + /* store the voltage id's for the related frequency |
281 | + * We are going to do some sanity checks here to prevent users |
282 | + * from setting higher voltages than the default one. |
283 | + */ |
284 | +{ |
285 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
286 | + struct acpi_processor_performance *acpi_data; |
287 | + struct cpufreq_frequency_table *freq_table; |
288 | + unsigned int freq_index; |
289 | + unsigned int state_index; |
290 | + unsigned int new_vid; |
291 | + unsigned int original_vid; |
292 | + unsigned int new_control; |
293 | + unsigned int original_control; |
294 | + const char *curr_buf = buf; |
295 | + char *next_buf; |
296 | + ssize_t retval; |
297 | + |
298 | + if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls |
299 | + |
300 | + retval = check_origial_table(data); |
301 | + if (0 != retval) |
302 | + return retval; |
303 | + |
304 | + acpi_data = data->acpi_data; |
305 | + freq_table = data->freq_table; |
306 | + |
307 | + /* for each value taken from the sysfs interfalce (phc_vids) get entrys and convert them to unsigned long integers*/ |
308 | + for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) { |
309 | + new_vid = simple_strtoul(curr_buf, &next_buf, 10); |
310 | + if (next_buf == curr_buf) { |
311 | + if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) { //end of line? |
312 | + curr_buf++; |
313 | + break; |
314 | + } |
315 | + //if we didn't got end of line but there is nothing more to read something went wrong... |
316 | + printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf); |
317 | + return -EINVAL; |
318 | + } |
319 | + |
320 | + state_index = freq_table[freq_index].index; |
321 | + original_control = data->original_controls[state_index]; |
322 | + original_vid = original_control & INTEL_MSR_VID_MASK; |
323 | + |
324 | + /* before we store the values we do some checks to prevent |
325 | + * users to set up values higher than the default one |
326 | + */ |
327 | + if (new_vid <= original_vid) { |
328 | + new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid; |
329 | + dprintk("setting control at %i to %x (default is %x)\n", |
330 | + freq_index, new_control, original_control); |
331 | + acpi_data->states[state_index].control = new_control; |
332 | + |
333 | + } else { |
334 | + printk("skipping vid at %i, %u is greater than default %u\n", |
335 | + freq_index, new_vid, original_vid); |
336 | + } |
337 | + |
338 | + curr_buf = next_buf; |
339 | + /* jump over value seperators (space or comma). |
340 | + * There could be more than one space or comma character |
341 | + * to separate two values so we better do it using a loop. |
342 | + */ |
343 | + while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) { |
344 | + curr_buf++; |
345 | + } |
346 | + } |
347 | + |
348 | + /* set new voltage for current frequency */ |
349 | + data->resume = 1; |
350 | + acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L); |
351 | + |
352 | + return curr_buf - buf; |
353 | +} |
354 | + |
355 | +static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count) |
356 | + /* store the controls (frequency id's and related voltage id's) |
357 | + * We are going to do some sanity checks here to prevent users |
358 | + * from setting higher voltages than the default one. |
359 | + */ |
360 | +{ |
361 | + struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu); |
362 | + struct acpi_processor_performance *acpi_data; |
363 | + struct cpufreq_frequency_table *freq_table; |
364 | + const char *curr_buf; |
365 | + unsigned int op_count; |
366 | + unsigned int state_index; |
367 | + int isok; |
368 | + char *next_buf; |
369 | + ssize_t retval; |
370 | + unsigned int new_vid; |
371 | + unsigned int original_vid; |
372 | + unsigned int new_fid; |
373 | + unsigned int old_fid; |
374 | + unsigned int original_control; |
375 | + unsigned int old_control; |
376 | + unsigned int new_control; |
377 | + int found; |
378 | + |
379 | + if (!check_cpu_control_capability(data)) return -ENODEV; |
380 | + |
381 | + retval = check_origial_table(data); |
382 | + if (0 != retval) |
383 | + return retval; |
384 | + |
385 | + acpi_data = data->acpi_data; |
386 | + freq_table = data->freq_table; |
387 | + |
388 | + op_count = 0; |
389 | + curr_buf = buf; |
390 | + next_buf = NULL; |
391 | + isok = 1; |
392 | + |
393 | + while ( (isok) && (curr_buf != NULL) ) |
394 | + { |
395 | + op_count++; |
396 | + // Parse fid |
397 | + new_fid = simple_strtoul(curr_buf, &next_buf, 10); |
398 | + if ((next_buf != curr_buf) && (next_buf != NULL)) |
399 | + { |
400 | + // Parse separator between frequency and voltage |
401 | + curr_buf = next_buf; |
402 | + next_buf = NULL; |
403 | + if (*curr_buf==':') |
404 | + { |
405 | + curr_buf++; |
406 | + // Parse vid |
407 | + new_vid = simple_strtoul(curr_buf, &next_buf, 10); |
408 | + if ((next_buf != curr_buf) && (next_buf != NULL)) |
409 | + { |
410 | + found = 0; |
411 | + for (state_index = 0; state_index < acpi_data->state_count; state_index++) { |
412 | + old_control = acpi_data->states[state_index].control; |
413 | + old_fid = extract_fid_from_control(old_control); |
414 | + if (new_fid == old_fid) |
415 | + { |
416 | + found = 1; |
417 | + original_control = data->original_controls[state_index]; |
418 | + original_vid = extract_vid_from_control(original_control); |
419 | + if (new_vid <= original_vid) |
420 | + { |
421 | + new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid; |
422 | + dprintk("setting control at %i to %x (default is %x)\n", |
423 | + state_index, new_control, original_control); |
424 | + acpi_data->states[state_index].control = new_control; |
425 | + |
426 | + } else { |
427 | + printk("skipping vid at %i, %u is greater than default %u\n", |
428 | + state_index, new_vid, original_vid); |
429 | + } |
430 | + } |
431 | + } |
432 | + |
433 | + if (found == 0) |
434 | + { |
435 | + printk("operating point # %u not found (FID = %u)\n", op_count, new_fid); |
436 | + isok = 0; |
437 | + } |
438 | + |
439 | + // Parse seprator before next operating point, if any |
440 | + curr_buf = next_buf; |
441 | + next_buf = NULL; |
442 | + if ((*curr_buf == ',') || (*curr_buf == ' ')) |
443 | + curr_buf++; |
444 | + else |
445 | + curr_buf = NULL; |
446 | + } |
447 | + else |
448 | + { |
449 | + printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf); |
450 | + isok = 0; |
451 | + } |
452 | + } |
453 | + else |
454 | + { |
455 | + printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf); |
456 | + isok = 0; |
457 | + } |
458 | + } |
459 | + else |
460 | + { |
461 | + printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf); |
462 | + isok = 0; |
463 | + } |
464 | + } |
465 | + |
466 | + if (isok) |
467 | + { |
468 | + retval = count; |
469 | + /* set new voltage at current frequency */ |
470 | + data->resume = 1; |
471 | + acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L); |
472 | + } |
473 | + else |
474 | + { |
475 | + retval = -EINVAL; |
476 | + } |
477 | + |
478 | + return retval; |
479 | +} |
480 | + |
481 | +static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf) |
482 | + /* print out the phc version string set at the beginning of that file |
483 | + */ |
484 | +{ |
485 | + ssize_t count = 0; |
486 | + count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING); |
487 | + return count; |
488 | +} |
489 | + |
490 | + |
491 | + |
492 | +static struct freq_attr cpufreq_freq_attr_phc_version = |
493 | +{ |
494 | + /*display phc's version string*/ |
495 | + .attr = { .name = "phc_version", .mode = 0444, .owner = THIS_MODULE }, |
496 | + .show = show_freq_attr_phc_version, |
497 | + .store = NULL, |
498 | +}; |
499 | + |
500 | +static struct freq_attr cpufreq_freq_attr_vids = |
501 | +{ |
502 | + /*display phc's voltage id's for the cpu*/ |
503 | + .attr = { .name = "phc_vids", .mode = 0644, .owner = THIS_MODULE }, |
504 | + .show = show_freq_attr_vids, |
505 | + .store = store_freq_attr_vids, |
506 | +}; |
507 | + |
508 | +static struct freq_attr cpufreq_freq_attr_default_vids = |
509 | +{ |
510 | + /*display acpi's default frequency id's for the cpu*/ |
511 | + .attr = { .name = "phc_default_vids", .mode = 0444, .owner = THIS_MODULE }, |
512 | + .show = show_freq_attr_default_vids, |
513 | + .store = NULL, |
514 | +}; |
515 | + |
516 | +static struct freq_attr cpufreq_freq_attr_fids = |
517 | +{ |
518 | + /*display phc's default frequency id's for the cpu*/ |
519 | + .attr = { .name = "phc_fids", .mode = 0444, .owner = THIS_MODULE }, |
520 | + .show = show_freq_attr_fids, |
521 | + .store = NULL, |
522 | +}; |
523 | + |
524 | +static struct freq_attr cpufreq_freq_attr_controls = |
525 | +{ |
526 | + /*display phc's current voltage/frequency controls for the cpu*/ |
527 | + .attr = { .name = "phc_controls", .mode = 0644, .owner = THIS_MODULE }, |
528 | + .show = show_freq_attr_controls, |
529 | + .store = store_freq_attr_controls, |
530 | +}; |
531 | + |
532 | +static struct freq_attr cpufreq_freq_attr_default_controls = |
533 | +{ |
534 | + /*display acpi's default voltage/frequency controls for the cpu*/ |
535 | + .attr = { .name = "phc_default_controls", .mode = 0444, .owner = THIS_MODULE }, |
536 | + .show = show_freq_attr_default_controls, |
537 | + .store = NULL, |
538 | +}; |
539 | + |
540 | + |
541 | static struct freq_attr *acpi_cpufreq_attr[] = { |
542 | - &cpufreq_freq_attr_scaling_available_freqs, |
543 | + &cpufreq_freq_attr_phc_version, |
544 | + &cpufreq_freq_attr_scaling_available_freqs, |
545 | + &cpufreq_freq_attr_vids, |
546 | + &cpufreq_freq_attr_default_vids, |
547 | + &cpufreq_freq_attr_fids, |
548 | + &cpufreq_freq_attr_controls, |
549 | + &cpufreq_freq_attr_default_controls, |
550 | NULL, |
551 | }; |
552 | |
553 | static struct cpufreq_driver acpi_cpufreq_driver = { |
554 | .verify = acpi_cpufreq_verify, |