aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2007-05-02 18:19:05 -0400
committerDave Jones <davej@redhat.com>2007-05-13 17:25:13 -0400
commitdc2585eb478cfeb45b3d6e235ac7b5918fb859f7 (patch)
tree7243e8b4b9d059762f70eb5b1c94598606f0df06
parent30046e5885848fe5c2c66177dca6b277323e31ab (diff)
[CPUFREQ] powernow-k7: fix MHz rounding issue with perflib
When the PST tables are broken, powernow-k7 uses ACPI's processor_perflib to deduce the available frequency multipliers from the _PSS tables. Upon frequency change, processor_perflib performs some verification on the frequency (checks that it's within allowable bounds). powernow-k7 deals with absolute frequencies in KHz, whereas perflib only deals with MHz values. When performing the above verification, perflib multiplies the MHz values by 1000 to obtain the KHz value. We then end up with situations like the following: - powernow-k7 multiplies the multiplier by the FSB, and obtains a value such as 1266768 KHz - perflib belives the same state has frequency of 1266 MHz - acpi_processor_ppc_notifier calls cpufreq_verify_within_limits to verify that 1266768 is in the allowable range of 0 to 1266000 (i.e. 1266 * 1000) - it's not, so that frequency is rejected - the maximum CPU frequency is not reachable This patch solves the problem by rounding up the MHz values stored in perflib's tables. Additionally it corrects a broken URL. It also fixes http://bugzilla.kernel.org/show_bug.cgi?id=8255 although this case is a bit different: the frequencies in the _PSS tables are wildly wrong, but we get better results if we force ACPI to respect the fsb * multiplier calculations (even though it seems that the multiplier values aren't entirely correct either). Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 837b04166a47..ca3e1d341889 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -341,15 +341,17 @@ static int powernow_acpi_init(void)
341 pc.val = (unsigned long) acpi_processor_perf->states[0].control; 341 pc.val = (unsigned long) acpi_processor_perf->states[0].control;
342 for (i = 0; i < number_scales; i++) { 342 for (i = 0; i < number_scales; i++) {
343 u8 fid, vid; 343 u8 fid, vid;
344 unsigned int speed; 344 struct acpi_processor_px *state =
345 &acpi_processor_perf->states[i];
346 unsigned int speed, speed_mhz;
345 347
346 pc.val = (unsigned long) acpi_processor_perf->states[i].control; 348 pc.val = (unsigned long) state->control;
347 dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n", 349 dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
348 i, 350 i,
349 (u32) acpi_processor_perf->states[i].core_frequency, 351 (u32) state->core_frequency,
350 (u32) acpi_processor_perf->states[i].power, 352 (u32) state->power,
351 (u32) acpi_processor_perf->states[i].transition_latency, 353 (u32) state->transition_latency,
352 (u32) acpi_processor_perf->states[i].control, 354 (u32) state->control,
353 pc.bits.sgtc); 355 pc.bits.sgtc);
354 356
355 vid = pc.bits.vid; 357 vid = pc.bits.vid;
@@ -360,6 +362,18 @@ static int powernow_acpi_init(void)
360 powernow_table[i].index |= (vid << 8); /* upper 8 bits */ 362 powernow_table[i].index |= (vid << 8); /* upper 8 bits */
361 363
362 speed = powernow_table[i].frequency; 364 speed = powernow_table[i].frequency;
365 speed_mhz = speed / 1000;
366
367 /* processor_perflib will multiply the MHz value by 1000 to
368 * get a KHz value (e.g. 1266000). However, powernow-k7 works
369 * with true KHz values (e.g. 1266768). To ensure that all
370 * powernow frequencies are available, we must ensure that
371 * ACPI doesn't restrict them, so we round up the MHz value
372 * to ensure that perflib's computed KHz value is greater than
373 * or equal to powernow's KHz value.
374 */
375 if (speed % 1000 > 0)
376 speed_mhz++;
363 377
364 if ((fid_codes[fid] % 10)==5) { 378 if ((fid_codes[fid] % 10)==5) {
365 if (have_a0 == 1) 379 if (have_a0 == 1)
@@ -368,10 +382,16 @@ static int powernow_acpi_init(void)
368 382
369 dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " 383 dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
370 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, 384 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
371 fid_codes[fid] % 10, speed/1000, vid, 385 fid_codes[fid] % 10, speed_mhz, vid,
372 mobile_vid_table[vid]/1000, 386 mobile_vid_table[vid]/1000,
373 mobile_vid_table[vid]%1000); 387 mobile_vid_table[vid]%1000);
374 388
389 if (state->core_frequency != speed_mhz) {
390 state->core_frequency = speed_mhz;
391 dprintk(" Corrected ACPI frequency to %d\n",
392 speed_mhz);
393 }
394
375 if (latency < pc.bits.sgtc) 395 if (latency < pc.bits.sgtc)
376 latency = pc.bits.sgtc; 396 latency = pc.bits.sgtc;
377 397
@@ -602,7 +622,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
602 result = powernow_acpi_init(); 622 result = powernow_acpi_init();
603 if (result) { 623 if (result) {
604 printk (KERN_INFO PFX "ACPI and legacy methods failed\n"); 624 printk (KERN_INFO PFX "ACPI and legacy methods failed\n");
605 printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n"); 625 printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.html\n");
606 } 626 }
607 } else { 627 } else {
608 /* SGTC use the bus clock as timer */ 628 /* SGTC use the bus clock as timer */