Magellan Linux

Contents of /trunk/kernel26-magellan/patches-2.6.30-r1/0156-2.6.30-linux-phc-0.3.2.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1114 - (show annotations) (download)
Sun Aug 22 17:59:15 2010 UTC (13 years, 8 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