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