Magellan Linux

Contents of /trunk/kernel26-magellan/patches-2.6.25-r2/0156-2.6.25-linux-phc-0.3.1-teknohog.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 653 - (show annotations) (download)
Sun Jun 22 15:02:54 2008 UTC (15 years, 10 months ago) by niro
File size: 15454 byte(s)
-2.6.25-magellan-r2; updated to linux-2.6.25.6

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