# CPU scaling; Mobile AthlonXP on desktop board ?

## AlterEgo

I like silence. Less power = less heat = less fans = more silence  :Cool: 

Therefore, I've modified a desktop AthlonXP2000+ (Palomino) into a mobile Athlon. It runs on a MSI KT3Ultra2, and it is recognised as a mobile processor by the BIOS. It is also properly recognised by diagnostic tools, in both Win (Sandra/AIDA) and linux (x86info).

In Windows, I can easily throttle the CPU using  CPUMSR  or other tools (  link in Dutch, for who's interested ). 

In  linux, after having applied the  proper  kernel 2.6.6 config, dmesg tells me:

```

 powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: FSB: 133.366 MHz

powernow: Trying ACPI perflib

powernow: ACPI perflib can not be used in this platform

powernow: ACPI and legacy methods failed

powernow: See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml

```

I guess this means that the BIOS does not contain the proper tables with CPU-modes.

Also, /sys/devices/system/cpu/cpu0/cpufreq/ is missing.

Is there anything I can do to make CPU throttling work in linux without ACPI perflib, like can be done in Windows?

No is not an answer   :Wink: 

I did try ACPI throttling, and this "works" i.e.,  I can make the computer slow like a snail, but the temps will not go down.

----------

## HardenCoonor

Hi there,

I am also looking for a solution. 

It is true, the powernow-k7 driver does not work, if you do not have a pst table in your bios that matches you cpuid and other prerequisites(fsb, voltage and stuff). 

I have a ECS K7S5A Pro, which works perfectly under the evil empire OS,  with that CPUMSR-software, though my MB does not support voltage adjustment, but 1.467 GHz(11x133) @1.5Volt is quit good, before it was 1.4GHz(10.5x133)@1.75Volt, which is quite hot(>55°C onDie).

Nevermind, i tried to modify the powernow-k7.c file, so it does not use PST-tables provided by the bios, instead makes up a cpufreq table itself, depending on maxfid, with no voltage adjustment. 

But since i am no programmer, my driver failed, the kernel gave an error message and my pc hang. 

One major error was that the fsb was miscalculated, something with the fid codes i got wrong.

I did not look into the governors' code, so i do not know if such a simple cpufreq table is enough(i mean only fid and speed). Kernel hacking is  something only for kernel-developers.

@AlterEgo: Maybe you are a bit into programming (I guess the powernow-k7 is written C), maybe i can post the code i have, well, not written, but adapted(taken out ACPI-related, added mobile-vid-table, dektop-vid-table etc.).

Before the summer is getting real hot(and the PC too),  i think there should be a result, or i will throttle it via fsb.

----------

## vyral_surfer

I'm in the same boat as you over here. I recently modded my Athlon XP 2400+ to be mobile, and am looking to scale the processor down when I'm not using it. I tried various methods. and always got this:

```

powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: FSB: 133.366 MHz

powernow: Trying ACPI perflib

powernow: ACPI perflib can not be used in this platform

powernow: ACPI and legacy methods failed

powernow: See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml

```

Today, i noticed this post.  I tried brodo's advice, and with powernow_k7.acpi_force=1 on the kernel command line, I get this:

```

powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: PSB/PST known to be broken.  Trying ACPI instead

powernow: ACPI perflib can not be used in this platform

```

I wonder what is meant by "this platform"...

----------

## brodo

For throttling check out 

```
/proc/acpi/processor/*/throttling
```

. powernow-k7 is for frequency (and voltage) scaling.

----------

## HardenCoonor

 *Quote:*   

> powernow-k7 is for frequency (and voltage) scaling.

 

I guess we mean the same thing here with throttling/scaling, that is to alter the frequency the cpu is working at, from 3 GHz to 400 MHz and back.  Voltage scaling is just a by-product, which is not that important for me since it does not work on my Mainboard.

I searched the Internet (or at least the googled part of it) for ACPI perflib, but to no avail. 

From my point of view, there should be written a new driver for those cpu-modders among us, especially for the mobile athlons/durons. This driver should  provide us with a working cpufreq-table the governors can use, with or without voltage. Maybe someone comes across this thread, who is capable of rewriting either powernow-k7.c or writing a new kernel module. 

Maybe anyone interested in this should take a look at powernow-k7.c and/or the governors, maybe you get an idea how it could be done.

----------

## brodo

 *HardenCoonor wrote:*   

>  *Quote:*   powernow-k7 is for frequency (and voltage) scaling. 
> 
> I guess we mean the same thing here with throttling/scaling, that is to alter the frequency the cpu is working at, from 3 GHz to 400 MHz and back.

 

Throttling is _very_ different to scaling: throttling means possibly large latency and less energy saving than frequency scaling alone.

 *HardenCoonor wrote:*   

> I searched the Internet (or at least the googled part of it) for ACPI perflib, but to no avail. 

 

This does not surprise me. The ACPI perflib can only provide frequency/voltage pairs to the powernow-k7 or any other cpufreq driver if the BIOS exports these pairs inside the ACPI tables. As it's a pre-k8 desktop BIOS it doesn't know about "ACPI P-States" as it's technically called, so it can't export such information in the ACPI tables. Neither will the "direct"/"legacy" BIOS method called PSB work -- again, the BIOS is a pre-k8 desktop BIOS and doesn't know anything about frequency scaling because of that.

 *HardenCoonor wrote:*   

> From my point of view, there should be written a new driver for those cpu-modders among us, especially for the mobile athlons/durons. This driver should  provide us with a working cpufreq-table the governors can use, with or without voltage. Maybe someone comes across this thread, who is capable of rewriting either powernow-k7.c or writing a new kernel module. 
> 
> Maybe anyone interested in this should take a look at powernow-k7.c and/or the governors, maybe you get an idea how it could be done.

 

There are different approaches on how to provide such functionality in the powernow-k7 driver, but as it requires hardwiring frequency/voltage pairs, or even only valid frequencies, incorrect settings might cause permanent hardware damage, it will[*] only be available to "expert users" who know how to patch their kernels, how to modify some lines of code etc. See, for example, this thread on the cpufreq mailing list for details: 

http://www.linux.org.uk/mailman/private/cpufreq/2004-June/003812.html

[note: subscription required, but you can disable message delivery]

[*] e.g. see Dave's opinion on this matter at http://www.linux.org.uk/mailman/private/cpufreq/2004-June/003815.html, which illustrates the current and former cpufreq maintainer are of the same opinion.

----------

## brodo

 *brodo wrote:*   

>  *HardenCoonor wrote:*    *Quote:*   powernow-k7 is for frequency (and voltage) scaling. 
> 
> I guess we mean the same thing here with throttling/scaling, that is to alter the frequency the cpu is working at, from 3 GHz to 400 MHz and back. 
> 
> Throttling is _very_ different to scaling: throttling means possibly large latency and less energy saving than frequency scaling alone.

 

Addendum: throttling is also easier to implement, and desktop chipsets and/or BIOSes usally are aware of this thermal management method.

----------

## brodo

 *AlterEgo wrote:*   

> I did try ACPI throttling, and this "works" i.e.,  I can make the computer slow like a snail, but the temps will not go down.

 

The "idling" of a CPU if there's no work to do is quite the same as is done when throttling is done. That means the temperature should not go as high on high loads if throttling is enabled, as the CPU is "forced" to sit idle for short periods of time. 

As a sidenote: because of the technical equivalence of "idling" and "throttling" there's no sense in doing dynamic throttling: if the CPU is idle, it doesn't matter what throttling state it is in.

----------

## HardenCoonor

 *Quote:*   

> There are different approaches on how to provide such functionality in the powernow-k7 driver, but as it requires hardwiring frequency/voltage pairs, or even only valid frequencies, incorrect settings might cause permanent hardware damage, it will[*] only be available to "expert users" who know how to patch their kernels, how to modify some lines of code etc.

 

On these forums here there are only expert users, or persons who want to become experts  :Wink:  . But i have to agree on that. The only way to find out which pairs of FID/VID work is to test it under Windows with cpumsr, and of course to think about what you do before you do it. 

For users of mobile processors on desktop mainboards it is probably good to know that i guess most of them cannot change voltage, but only frequency, at least my K7S5A Pro is one of them.

Finally, now the hot summer days are gone, i was able to successfully edit the powernow-k7.c. I have modified the file with a hardcoded pst table. I have a Duron with 11x max multiplier, with the multipliers from 3x to 11x all working, at least in Windows(using cpumsr).  Using powernowd, my pc scales from 1467 to 401 MHz, with the temperature being as low as 32°C.

##############################################

Before using the patch, please adjust NUM_GENERIC_PST, max multiplier, and/or VID to suit your configuration. For valid vid or fid codes please look at the powernow-k7.c, into the vid_tables and fid_tables.

Suggestions for improving the code are welcome.

Here is the patch:

```

--- /usr/src/linux-2.6.8.1-nitro6/arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2004-08-31 20:03:12.000000000 +0200

+++ powernow-k7.c   2004-08-31 20:18:07.998253336 +0200

@@ -36,6 +36,8 @@

 

 #include "powernow-k7.h"

 

+#define NUM_GENERIC_PSTS 30

+

 #define DEBUG

 

 #ifdef DEBUG

@@ -176,6 +178,36 @@

    unsigned int speed;

    u8 fid, vid;

 

+   /************************************************ 

+    * HardenCoonor: generic voltages / frequencies for 

+    * Mobile Athlons with buggy BIOS 

+    ************************************************/

+    

+   pst = kmalloc ( NUM_GENERIC_PSTS *sizeof(unsigned char), GFP_KERNEL);

+   if (!pst) return -ENOMEM;

+   

+                  /* FID  */                       /*  VID  */

+   *pst++ = 0x10; /*  3.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x12; /*  4.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x04; /*  5.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x05; /*  5.5x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x06; /*  6.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x07; /*  6.5x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x08; /*  7.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x09; /*  7.5x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x0A; /*  8.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x0B; /*  8.5x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x0C; /*  9.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x0D; /*  9.5x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x0E; /* 10.0x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x0F; /* 10.5x */       *pst++ = 0x0A; /* 1.50V */

+   *pst++ = 0x00; /* 11.0x */       *pst++ = 0x0A; /* 1.50V */

+   

+   /* Set PST ptr back to base addr of table */

+   pst -= NUM_GENERIC_PSTS;

+   /************************************************/

+

+   

    powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);

    if (!powernow_table)

       return -ENOMEM;

@@ -424,6 +456,11 @@

    unsigned int ret;

 

    etuple = cpuid_eax(0x80000001);

+   

+   /* HardenCoonor: fix for broken PSB in Compaq Presario 2100 series */

+   dprintk (KERN_INFO PFX "Our CPU maxfid    0x%x\n", maxfid);

+   dprintk (KERN_INFO PFX "Our CPU startvid  0x%x\n", startvid);

+   dprintk (KERN_INFO PFX "WARNING: This driver has been modified with a generic PST table\n");

 

    for (i=0xC0000; i < 0xffff0 ; i+=16) {

 

@@ -461,25 +498,30 @@

 

          for (i = 0 ; i <psb->numpst; i++) {

             pst = (struct pst_s *) p;

-            number_scales = pst->numpstates;

-

             if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&

                 (maxfid==pst->maxfid) && (startvid==pst->startvid))

             {

+               number_scales = pst->numpstates;

                dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst);

                dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid);

                dprintk ("fsb: %d\t", pst->fsbspeed);

                dprintk ("maxFID: 0x%x\t", pst->maxfid);

                dprintk ("startvid: 0x%x\n", pst->startvid);

-

                ret = get_ranges ((char *) pst + sizeof (struct pst_s));

                return ret;

-

             } else {

                p = (char *) pst + sizeof (struct pst_s);

-               for (j=0 ; j < number_scales; j++)

-                  p+=2;

+                for (j=0 ; j < number_scales; j++)

+               p+=2;

             }

+            /* HardenCoonor: modified for generic method */

+            number_scales = NUM_GENERIC_PSTS / 2;

+            dprintk (KERN_INFO PFX " cpuid: 0x%x  ", pst->cpuid);

+            dprintk ("fsb: %d\t", fsb);

+            dprintk ("maxFID: 0x%x\t", maxfid);

+            dprintk ("startvid: 0x%x\n", startvid);               

+            ret = get_ranges ((char *) pst + sizeof (struct pst_s));

+             return ret;

          }

          printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);

          printk (KERN_INFO PFX "This is indicative of a broken BIOS.\n");

```

#################

This work is based on the patch of a person named baitisj, which can be found on the Internet.

----------

## new_nOOb

hello. can you post the completely powernow k7.c file because  i can´t patch it

thank´s

----------

## doom4

i dont know if i am right here but how can you make from a normal athlon an ahtlon m  :Smile:  i was wondering about. perhaps you can help me to know how. thx  :Smile: 

----------

## new_nOOb

have nobody a working powernow-k7.c for a mobile cpu on a desktop board

----------

## new_nOOb

any news??

----------

## f1n4rf1n

I'd also be very interested..

MSI KT880 with Athlon XP-M

----------

## luisfeser

I have a barton mobile in a nforce2 (desktop computer), and cpu scaling worked in a 2.6.7 kernel (when i used it), but with 2.6.10 it hangs the computer, i don't know why (using cpufreq).

But i think this is not very usefull in a desktop computer, because (at least when i tried) only changed the fsb, and the temperature was the same and the noise too.

If the voltage really change, then it will be usefull, but if not.....

----------

## YANOUSHek

Sorry if I'm makeing something wrong, but I didn't read the whole topic carefully.

I own a Mobile Athlon XP notebook and I didn't have any problems with the CPU throtling. I just use the drivers (powernow) from the kernel (2.6.9-gentoo-r9) and the throttling is rather easy:

```
___ root # cd /sys/devices/system/cpu/cpu0/cpufreq/
```

and then you have all the needed options:

1. listing available frequencies:

```
___ cpufreq # cat scaling_available_frequencies 

1788736 1457489 1059992 794994 662495 529996
```

2. changing the frequency:

```
___ cpufreq # cat cpuinfo_min_freq >scaling_max_freq
```

It works without a problem. The temperature of my laptop goes down instantly and the vent goes off - great for watching movies ;)

----------

## weingbz

In case this still interests anyone I have found part of the solution. 

 *AlterEgo wrote:*   

> I like silence. Less power = less heat = less fans = more silence 
> 
> Therefore, I've modified a desktop AthlonXP2000+ (Palomino) into a mobile Athlon. It runs on a MSI KT3Ultra2, and it is recognised as a mobile processor by the BIOS. It is also properly recognised by diagnostic tools, in both Win (Sandra/AIDA) and linux (x86info).
> 
> 

 

I too have the KT3 Ultra 2

 *AlterEgo wrote:*   

> 
> 
> dmesg tells me:
> 
> ```
> ...

 

Oh here's what I got:

Apply these two patches against kernel 2.6.11-rc2 or rc3:

```

--- linux/arch/i386/kernel/cpu/cpufreq/Kconfig.orig   2005-01-25 19:54:17.000000000 +0100

+++ linux/arch/i386/kernel/cpu/cpufreq/Kconfig   2005-01-25 20:07:52.000000000 +0100

@@ -71,6 +71,17 @@

    depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y"))

    default y

 

+config X86_POWERNOW_K7_MANUAL

+        bool "Manual setting of PowerNow! table for AMD Mobile Athlon/Duron."

+        depends on X86_POWERNOW_K7

+        default n

+        help

+          This adds the possibility to manual change the PST table.

+

+          For details, take a look at <file:Documentation/cpu-freq/>.

+

+          If in doubt, say N.

+

 config X86_POWERNOW_K8

    tristate "AMD Opteron/Athlon64 PowerNow!"

    depends on CPU_FREQ_TABLE && EXPERIMENTAL

```

and

```

--- linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c.orig   2005-01-25 19:54:10.000000000 +0100

+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2005-01-25 20:06:12.000000000 +0100

@@ -66,7 +66,7 @@

 };

 #endif

 

-#ifdef CONFIG_CPU_FREQ_DEBUG

+#if defined CONFIG_CPU_FREQ_DEBUG || defined CONFIG_X86_POWERNOW_K7_MANUAL

 /* divide by 1000 to get VCore voltage in V. */

 static int mobile_vid_table[32] = {

     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,

@@ -76,7 +76,7 @@

 };

 #endif

 

-/* divide by 10 to get FID. */

+/* divide by 10 to get multiplier. */

 static int fid_codes[32] = {

     110, 115, 120, 125, 50, 55, 60, 65,

     70, 75, 80, 85, 90, 95, 100, 105,

@@ -84,6 +84,31 @@

     150, 225, 160, 165, 170, 180, -1, -1,

 };

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+/* translation table for even multiplier to fid */

+static int even_multiplier[20] = {

+       16, 18, 4, 6, 8, 10, 12, 14,    // 3, 4, 5, 6, 7 ,8 , 9, 10

+       0, 2, 20, 22, 24, 26, 28, 29,   // 11, 12, 13, 14, 15, 16, 17, 18

+       17, 19, 23, 25,         // 19, 20, 21, 22

+};

+

+/* translation table for odd multiplier to fid*/

+static int odd_multiplier[9] = {

+       5, 7, 9, 11, 13, 15, 1, 3,      // 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5

+       21,                     // 13.5

+};

+

+/* This parameters can be used to manually overwrite the tables */

+static int overwrite_table = 0;

+#define MAX_PST 10

+static int multiplier_arr_size = MAX_PST;

+static int voltage_arr_size = MAX_PST;

+static int multiplier[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int voltage[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int switch_latency = 0;

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 /* This parameter is used in order to force ACPI instead of legacy method for

  * configuration purpose.

  */

@@ -97,7 +122,7 @@

 static unsigned int minimum_speed=-1;

 static unsigned int maximum_speed;

 static unsigned int number_scales;

-static unsigned int fsb;

+static unsigned int fsb=0;

 static unsigned int latency;

 static char have_a0;

 

@@ -413,6 +438,143 @@

 }

 #endif

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+static int powernow_manual_settings(union msr_fidvidstatus *fidvidstatus)

+{

+       int i, k, validentry;

+       unsigned int max_multiplier, max_voltage;

+       unsigned int speed, cm;

+       u8 vid, fid;

+       static struct cpufreq_frequency_table *powernow_table_tmp;

+

+       if (switch_latency > 0) {

+               if (switch_latency < 100) {

+                       printk(KERN_INFO PFX

+                              "Settling time passed as %d microseconds."

+                              "Should be at least 100. Correcting.\n",

+                              switch_latency);

+                       switch_latency = 100;

+               }

+               latency = switch_latency;

+       } else {

+               latency = 200;

+       }

+       dprintk("Settling Time: %d microseconds.\n", latency);

+

+       /* get number of specified multipliers */

+       number_scales = multiplier_arr_size;

+       for (i = 0; i < multiplier_arr_size; i++) {

+               if (multiplier[i] == 0) {

+                       number_scales = i;

+                       break;

+               }

+       }

+

+       /* get maximum values */

+       max_multiplier = fid_codes[fidvidstatus->bits.MFID];

+       max_voltage = mobile_vid_table[fidvidstatus->bits.MVID];

+

+       /* allocate memory */

+       powernow_table =

+           kmalloc((sizeof(struct cpufreq_frequency_table) *

+                    (number_scales + 1)), GFP_KERNEL);

+       if (!powernow_table)

+               return -ENOMEM;

+       memset(powernow_table, 0,

+              (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));

+

+       k = 0;

+       for (i = 0; i < number_scales; i++) {

+               validentry = 0;

+               if (multiplier[i] != 0) {

+                       /* fix multiplier */

+                       if (multiplier[i] < 30)

+                               multiplier[i] = multiplier[i] * 10;

+                       if (multiplier[i] < max_multiplier) {

+                               cm = (multiplier[i] / 10);

+

+                               /* check if odd or even muliplier */

+                               if (multiplier[i] % 10) {

+                                       /* odd multiplier */

+                                       if (cm == 16) {

+                                               /* hardcoded because 14.5 and 15.5 fids not possible */

+                                               fid = 27;

+                                               validentry = 1;

+                                       } else if ((cm > 4) && (cm < 14)) {

+                                               fid = odd_multiplier[cm - 5];

+                                               validentry = 1;

+                                       }

+                               } else {

+                                       /* even_multiplier */

+                                       if ((cm < 23) && (cm > 2)) {

+                                               fid = even_multiplier[cm - 3];

+                                               validentry = 1;

+                                       }

+                               }

+                       }

+               }

+

+               if (validentry) {

+                       /* if no voltage specified use CPU default */

+                       if (voltage[i] == 0)

+                               voltage[i] = max_voltage;

+                       /* we do not allow higher voltages than the CPU's maximum 925 mV is the minimum */

+                       if ((voltage[i] <= max_voltage) && (voltage[i] >= 925)) {

+                               if (voltage[i] >= 1300) {

+                                       vid = 40 - (voltage[i] / 50);

+                               } else {

+                                       vid = 67 - (voltage[i] / 25);

+                               }

+                               /* calculate speed */

+                               speed = fsb * fid_codes[fid] / 10;

+                               powernow_table[k].frequency = speed;

+                               powernow_table[k].index = fid;  /*lower 8 bits */

+                               powernow_table[k].index |= (vid << 8);  /*upper 8 bits */

+

+                               if (speed < minimum_speed)

+                                       minimum_speed = speed;

+                               if (speed > maximum_speed)

+                                       maximum_speed = speed;

+

+                               dprintk("   FID: 0x%x (%d.%dx [%dMHz])\t", fid,

+                                       fid_codes[fid] / 10,

+                                       fid_codes[fid] % 10, speed / 1000);

+                               dprintk("VID: 0x%x (%d.%03dV)\n", vid,

+                                       mobile_vid_table[vid] / 1000,

+                                       mobile_vid_table[vid] % 1000);

+                               k++;

+                       }

+               } else {

+                       // invalid entry

+                       dprintk("Entry %d is invalid\n", i + 1);

+               }

+       }

+       if (k < number_scales) {

+               /* some entrys were invalid need to realloc table */

+               number_scales = k;

+               powernow_table_tmp =

+                   kmalloc((sizeof(struct cpufreq_frequency_table) *

+                            (number_scales + 1)), GFP_KERNEL);

+               if (!powernow_table_tmp) {

+                       kfree(powernow_table);

+                       return -ENOMEM;

+               }

+               memcpy(powernow_table_tmp, powernow_table,

+                      (sizeof(struct cpufreq_frequency_table) *

+                       (number_scales + 1)));

+               kfree(powernow_table);

+               powernow_table = powernow_table_tmp;

+       }

+

+       /* Terminate frequency list */

+       powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;

+       powernow_table[number_scales].index = 0;

+

+       return 0;

+}

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 static int powernow_decode_bios (int maxfid, int startvid)

 {

    struct psb_s *psb;

@@ -585,6 +747,18 @@

       return -ENODEV;

 

    rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+       if (fsb) {

+               if (fsb < 1000)

+                       fsb *= 1000;

+

+               if (fsb < 1000 || fsb > 1000000) {

+                       printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                              fsb);

+                       return -EINVAL;

+               }

+       } else

+#endif

 

    /* A K7 with powernow technology is set to max frequency by BIOS */

    fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];

@@ -597,6 +771,12 @@

    if (dmi_check_system(powernow_dmi_table) || acpi_force) {

       printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");

       result = powernow_acpi_init();

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+        } else if (overwrite_table) {

+                printk(KERN_INFO PFX

+                       "Overwriting PST table with manual settings\n");

+                result = powernow_manual_settings(&fidvidstatus);

+#endif

    } else {

       result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);

       if (result) {

@@ -681,6 +861,22 @@

 module_param(acpi_force,  int, 0444);

 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+module_param(overwrite_table, int, 0444);

+MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

+module_param(fsb, uint, 0444);

+MODULE_PARM_DESC(fsb, "(MHz) overrides the calculated FSB");

+module_param_array(multiplier, int, &multiplier_arr_size, 0444);

+MODULE_PARM_DESC(multiplier,

+                "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

+module_param_array(voltage, int, &voltage_arr_size, 0444);

+MODULE_PARM_DESC(voltage,

+                "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

+module_param(switch_latency, int, 0444);

+MODULE_PARM_DESC(switch_latency,

+                "Set state transition latency in microseconds (default 200us)");

+#endif

+

 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");

 MODULE_LICENSE ("GPL");

```

Check the linewraps on the patches, the forum software mangled them a bit.

Activate it as a module and activate the manual override (or do make oldconfig, that should present you with the new features)

```

CONFIG_X86_POWERNOW_K7=m

CONFIG_X86_POWERNOW_K7_ACPI=y

CONFIG_X86_POWERNOW_K7_MANUAL=y

```

Build your kernel and boot it.

Now start the module with something like this command

```

modprobe powernow-k7 overwrite_table=1 multiplier=6,7,8,9,10,11,12 fsb=167

```

If you want odd multipliers you have to multiply them by 10, so 6.5 becomes 65.

The module has the following options:

overwrite_table: 

   activates the manually settings, set it to >=1

multiplier: 

  specifies an array of multipliers

voltage:

  specifies an array of VCore voltages (default BIOS settings)

switch_latency:  

  sets the state transition latency in microseconds (default 200us)

fsb:

  sets the frontsidebus (default calculated from BIOS settings)

(I have all of this from http://lists.linux.org.uk/mailman/private/cpufreq/2005-January/004847.html

you need to register to be able to read the mailinglist) They talk about putting this into the vanilla 2.6.12 kernel.

Now you should have a choice of frequencies in

/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies.

Be careful, because my system freezes if I make too big a change at once, I have the following frequencies:

1169000 1336000 1503000 1670000 1837000 2004000

I don't know if this is a bug or a feature but if I ommit the fsb option I can go to very low frequencies (something like 470 Mhz)

I can't change from the last to the first or vice versa I have to first change to some values in between. This also means that my system hangs if I use the ondemand as governor (because it switches from max to min frequency), you should use userspace until that problem is solved. Also I can't change my voltage which is pretty annoying. The KT3Ultra2 always boots with a multiplier of 15 with my Athlon XP Mobile 2600+ processor. To get that working with a FSB of 166 I have to put in 1.675V (which is enough to boot but not stable for work). I know that I can work with 1.55V at 2Ghz but I can't reduce Vcore.If I try

```

modprobe powernow-k7 overwrite_table=1 multiplier=6,7,8,9,10,11,12 fsb=167 voltage=1550,1550,1550,1550,1550,1550,1550

```

I get

FATAL: Error inserting powernow_k7 (/lib/modules/2.6.11-rc3/kernel/arch/i386/kernel/cpu/cpufreq/powernow-k7.ko): No such device

Does anyone know why?

----------

## weingbz

 *f1n4rf1n wrote:*   

> I'd also be very interested..
> 
> MSI KT880 with Athlon XP-M

 

I don't know if you checked my last post but I would be interested if the patches I described work with your board because I'm considering buying a new motherboard but I haven't decided between nforce 2 and Kt880.

----------

## Alan Turing

Hi

First some facts:

Changing the multiplier of K7-mobile CPUs on desktop-boards works on most (maybe all, I don't know) VIA-chipset based mainboards, but not on nForce2 based Mainboards.

Changing the CPU-voltage does not work on most (I don't know any) VIA-based (desktop) mainbords.

nForce2 mainbords support voltage and FSB changing and so you can save power like explained here

_____

I have also a desktop mainbord (Asus A7V600 with VIA KT600 chipset) and a mobile K7. 

A few days after HardenCoonor posted his patch, I used it and it worked great.

After a few month (and maybe a few kernel updates) I recognized that it doesn't work alwas correct. Often throttling works correct, but sometimes the multiplier does not change. (I use powernowd). Until today I used the 2.6.9-ck3 kernel.

After 2.6.9 kernel the powernow-k7 module in the kernel had changed and so I needed new patches.

Today I tried development-sources-2.6.11 with the patches posted by weingbz.

First it seems to work correct. I could load the module without failures. powernowd throttled the CPU down, but when I start an application and powernowd should increase CPU speed my system hangs.  :Sad: 

Any ideas what I can do or how I can analyze what's gone wrong.

----------

## weingbz

 *DeBIGBOSS wrote:*   

> Hi
> 
> First some facts:
> 
> Changing the multiplier of K7-mobile CPUs on desktop-boards works on most (maybe all, I don't know) VIA-chipset based mainboards, but not on nForce2 based Mainboards.
> ...

 

That sucks, do you have any links for that?

 *DeBIGBOSS wrote:*   

> 
> 
> After 2.6.9 kernel the powernow-k7 module in the kernel had changed and so I needed new patches.
> 
> Today I tried development-sources-2.6.11 with the patches posted by weingbz.
> ...

 

As I said I have problems if I make too big a change at once. Try starting just the module without powernowd. Increase/decrease the frequency by one multiplier. 

That should work. Now go up/down from min frequency to max frequency. If that hangs your system then you have the same problem I have. You can still use powernowd but you have to use a different mode (mode 0 "sine" instead of mode 1 or 2). E.g. start it with

```

powernowd -vvv -m 0 -s 166000

```

If you have a frontside bus of 166 Mhz.

Hope that helps

----------

## Alan Turing

Thanks.

I can only increase/decrease by 400Mhz. Higher increases/decreases cause system hangs.

Now I have added to my /etc/modules.autoload.d/kernel-2.6

```

powernow-k7 overwrite_table=1 multiplier=3,5,7,9,11,115 fsb=200

```

and start powernowd with options 

-m 0 (sine)

-s 400000 (for increasing/decreasing in 400Mhz steps)

-p 100 (for 0,1s polling intervall)

600Mhz are enough for internet-surfing music or xvid movies and if more power is needed, cpu speed increases to 2300Mhz in less than 1 second.

----------

## skakz

hi all,

this is my situation:

I have an AMD Athlon(TM) XP (Barton mobile) on an Asus a7v600 MB

by bios i can scale cpu frequency with 10x max multiplier (3x to 10x all working!!!!)

this is my kernel (2.6.11-gentoo-r9) config:

```

#

# Power management options (ACPI, APM)

#

CONFIG_PM=y

# CONFIG_PM_DEBUG is not set

# CONFIG_SOFTWARE_SUSPEND is not set

#

# ACPI (Advanced Configuration and Power Interface) Support

#

CONFIG_ACPI=y

CONFIG_ACPI_BOOT=y

CONFIG_ACPI_INTERPRETER=y

# CONFIG_ACPI_SLEEP is not set

CONFIG_ACPI_AC=m

CONFIG_ACPI_BATTERY=m

CONFIG_ACPI_BUTTON=m

CONFIG_ACPI_VIDEO=m

CONFIG_ACPI_FAN=m

CONFIG_ACPI_PROCESSOR=m

CONFIG_ACPI_THERMAL=m

# CONFIG_ACPI_ASUS is not set

# CONFIG_ACPI_IBM is not set

# CONFIG_ACPI_TOSHIBA is not set

CONFIG_ACPI_BLACKLIST_YEAR=0

# CONFIG_ACPI_DEBUG is not set

CONFIG_ACPI_BUS=y

CONFIG_ACPI_EC=y

CONFIG_ACPI_POWER=y

CONFIG_ACPI_PCI=y

CONFIG_ACPI_SYSTEM=y

# CONFIG_X86_PM_TIMER is not set

CONFIG_ACPI_CONTAINER=m

#

# APM (Advanced Power Management) BIOS Support

#

CONFIG_APM=y

# CONFIG_APM_IGNORE_USER_SUSPEND is not set

# CONFIG_APM_DO_ENABLE is not set

# CONFIG_APM_CPU_IDLE is not set

# CONFIG_APM_DISPLAY_BLANK is not set

# CONFIG_APM_RTC_IS_GMT is not set

# CONFIG_APM_ALLOW_INTS is not set

CONFIG_APM_REAL_MODE_POWER_OFF=y

#

# CPU Frequency scaling

#

CONFIG_CPU_FREQ=y

# CONFIG_CPU_FREQ_DEBUG is not set

CONFIG_CPU_FREQ_STAT=y

# CONFIG_CPU_FREQ_STAT_DETAILS is not set

# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set

CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y

CONFIG_CPU_FREQ_GOV_PERFORMANCE=y

CONFIG_CPU_FREQ_GOV_POWERSAVE=m

CONFIG_CPU_FREQ_GOV_USERSPACE=y

CONFIG_CPU_FREQ_GOV_ONDEMAND=m

CONFIG_CPU_FREQ_TABLE=y

#

# CPUFreq processor drivers

#

CONFIG_X86_ACPI_CPUFREQ=m

CONFIG_X86_POWERNOW_K6=m

CONFIG_X86_POWERNOW_K7=m

CONFIG_X86_POWERNOW_K7_ACPI=y

CONFIG_X86_POWERNOW_K8=m

CONFIG_X86_POWERNOW_K8_ACPI=y

CONFIG_X86_GX_SUSPMOD=m

CONFIG_X86_SPEEDSTEP_CENTRINO=m

# CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI is not set

CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y

CONFIG_X86_SPEEDSTEP_ICH=m

CONFIG_X86_SPEEDSTEP_SMI=m

CONFIG_X86_P4_CLOCKMOD=m

CONFIG_X86_CPUFREQ_NFORCE2=m

CONFIG_X86_LONGRUN=m

CONFIG_X86_LONGHAUL=m

#

# shared options

#

CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y

CONFIG_X86_SPEEDSTEP_LIB=m

# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set 

```

when i try modprobe powernow-k7 it says

```

FATAL: Error inserting powernow_k7 (/lib/modules/2.6.11-gentoo-r9/kernel/arch/i386/kernel/cpu/cpufreq/powernow-k7.ko): No such device

```

```

dmesg

powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: No PST tables match this cpuid (0x7a0)

powernow: This is indicative of a broken BIOS.

powernow: Trying ACPI perflib

powernow: ACPI perflib can not be used in this platform

powernow: ACPI and legacy methods failed

powernow: See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml

```

also tryed to pass "acpi_force=1" when modprobe but still same output  :Mad: 

```

dmesg

powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: PSB/PST known to be broken.  Trying ACPI instead

powernow: ACPI perflib can not be used in this platform

```

patching with your patch fails saying: ( maybe because it is fow r2 or r3 version  :Rolling Eyes:  )

```

patching file linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c

Hunk #5 succeeded at 438 with fuzz 1.

Hunk #6 FAILED at 747.

Hunk #7 FAILED at 771.

Hunk #8 succeeded at 861 with fuzz 1.

2 out of 8 hunks FAILED -- saving rejects to file linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c.rej

```

Also, /sys/devices/system/cpu/cpu0/cpufreq/ is missing.

cat /proc/acpi/processor/CPU0/throttling says <not supported>

that's all folks

Someone please help me, or I'll be forced to call the Psychic Friends Network

EDIT: -------------------------------------------------------------------

a doubt is risen me

my /proc/cpuinfo says:

```

processor       : 0

vendor_id       : AuthenticAMD

cpu family      : 6

model           : 10

model name      : AMD Athlon(TM) XP

stepping        : 0

cpu MHz         : 1800.926

cache size      : 512 KB

fdiv_bug        : no

hlt_bug         : no

f00f_bug        : no

coma_bug        : no

fpu             : yes

fpu_exception   : yes

cpuid level     : 1

wp              : yes

flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr sse pni syscall mp mmxext 3dnowext 3dnow

bogomips        : 3547.13

```

but it would not have to be

```

model name   : mobile AMD Athlon(TM)

```

  :Question:   :Question:   :Question: 

perhaps bios doesn't recognize it as "mobile" ???

Please help me or I'll throw the pc through the window and I'll get outside to step on it to make sure it's broken

I'll get crazy.........  :Evil or Very Mad: 

----------

## tnt

BIOS does recognise it as Mobile, but your BIOS can't provide PST table to your kernel and so, kernel does not now wich multiplier-voltage combinations to use (although voltage can't be changed on desktop mobos). 

So, you'll need a patch wich enables you to manualy specify multiplier-voltage combinations and NOT to ask BIOS for PST.

Last time I've tried that, kernel was 2.6.8 and I don't know where to find patch for newer kernel.

Alternative is to try to patch powernow-k7.c manualy by looking at code and trying to realize where to insert those lines and what to comment out.

And, try to subscribe to the 

cpufreq@lists.linux.org.uk

 :Wink: 

----------

## skakz

 *tnt wrote:*   

> 
> 
> Alternative is to try to patch powernow-k7.c manualy by looking at code and trying to realize where to insert those lines and what to comment out.
> 
> 

 

thanks for the quickly answer

i manually patched powernow-k7.c but i cant pass any option to modprobe

```

omega linux # modprobe powernow-k7 overwrite_table=1 multiplier=6,7,8,9,10 fsb=200

FATAL: Error inserting powernow_k7 (/lib/modules/2.6.11-gentoo-r9/kernel/arch/i386/kernel/cpu/cpufreq/powernow-k7.ko): Unknown symbol in module, or unknown parameter (see dmesg)

omega linux # dmesg

...

powernow_k7: Unknown parameter `overwrite_table'

powernow_k7: Unknown parameter `multiplier'

powernow_k7: Unknown parameter `fsb'

```

and if i only do modprobe powernow-k7

```

omega linux # modprobe powernow-k7

omega linux # dmesg

....

kobject_register failed for powernow_k7 (-17)

 [<c026ce47>] kobject_register+0x57/0x60

 [<c012ed70>] mod_sysfs_setup+0x50/0xb0

 [<c012fe86>] load_module+0x796/0xa80

 [<c01301d0>] sys_init_module+0x60/0x250

 [<c0102785>] sysenter_past_esp+0x52/0x75

```

i dont know what to do... :Crying or Very sad:   :Crying or Very sad:   :Crying or Very sad:   :Crying or Very sad:   :Crying or Very sad: 

EDIT: -------------------

solved:

```

omega root # modprobe powernow-k7 overwrite_table=1 multiplier=6,7,8,9,10 fsb=200

omega root # dmesg

....

powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: Overwriting PST table with manual settings

powernow: Minimum speed 1200 MHz. Maximum speed 2000 MHz.

omega root # powernowd

powernowd: PowerNow Daemon v0.90hun6, (c) 2003-2004 John Clemens

powernowd: Found 1 physical cpu and 1 virtual cpu:

powernowd: cpu0: 1200000 kHz - 2000000 kHz

```

thanks tnt  :Wink: 

yeappyyyyyyyyyyyyyyyyyyyyy  :Very Happy:   :Very Happy:   :Very Happy:   :Very Happy: 

----------

## tnt

you're welcome!  :Wink: 

----------

## ecthalion

Can someone tell me if you can make all this stuff (or something similar)  with Intel PIII.    Intel PIII -> Intel PIII Mobile ????

Thanks.

----------

## hampelratte

hi,

i have just patched my kernel and now im playing around with powernowd and powernow-k7.

but first my environment:

amd athlon xp-m barton 2800+

asus a7v600-x

gentoo-sources 2.6.12-r4  (manually patched with the patch from weingbz)

powernowd 0.9

modprobe powernow-k7 overwrite_table=1 multiplier=3,6,9,12,15,16,17,18,19 fsb=133 voltage=1100,1100,1300,1300,1650,1650,1650,1750,1750

powernowd -m 0 -s 200000 -p 100

# cat scaling_available_frequencies 

400194 800388 1200582 1600776 2000970

(did i miss something ?)

ok,

the modprobe command applies without error and powernowd starts fine. as you can see the following frequencies should be available:

400, 800, 1200, 1600 and 2000 MHz

but if i watch /proc/cpuinfo powernowd seems to scale between 600, 1200, 1800, 2400 and 3000  :Shocked: 

ksensors displays the same frequencies. the temperature goes up to 52 ° C  (that's ok, isn't it ?) 

any clue for this weird behaviour  :Question: 

----------

## skakz

 *hampelratte wrote:*   

> 
> 
> [CUT]
> 
> modprobe powernow-k7 overwrite_table=1 multiplier=3,6,9,12,15,16,17,18,19 fsb=133
> ...

 

you can load the module with this options:

overwrite_table:

activates the manually settings, set it to >=1

multiplier:

specifies an array of multipliers

voltage:

specifies an array of VCore voltages (default BIOS settings)

switch_latency:

sets the state transition latency in microseconds (default 200us)

fsb:

sets the frontsidebus (default calculated from BIOS settings)

so you can simply do

```
modprobe powernow-k7 overwrite_table=1 multiplier=5,6,7,8,9,10 fsb=200
```

leaves the voltages as they are.

----------

## hampelratte

i cant use fsb 200 since the cpu only supports fsb 266. so i have to choose 133. that's ok for me.

the freq scaling up to 3000 is ok, too. everything is just fine. i'm just wondering why the values in the /sys directory differ from the modprobe values and why powernowd scales in 600MHz steps instead of the givven 200 or 400 MHz steps.

but that's no problem. im happy with the curremt setup  :Very Happy: 

----------

## tnt

 *hampelratte wrote:*   

> i cant use fsb 200 since the cpu only supports fsb 266. so i have to choose 133. that's ok for me.
> 
> the freq scaling up to 3000 is ok, too. everything is just fine. i'm just wondering why the values in the /sys directory differ from the modprobe values and why powernowd scales in 600MHz steps instead of the givven 200 or 400 MHz steps.
> 
> but that's no problem. im happy with the curremt setup 

 

You can and you should use 200MHz FSB instead of 133MHz (which is default) because your CPU will get great performance boost. Ofcorse, you should use multiplier no bigger than 10 (eventualy 11) with that FSB to keep CPU frequency at resonable level ( ~2GHz ). But, be careful when setting FSB - you have to lock AGP frequency at 66MHz!

 :Wink: 

----------

## hampelratte

 *tnt wrote:*   

>  *hampelratte wrote:*   i cant use fsb 200 since the cpu only supports fsb 266. so i have to choose 133. that's ok for me.
> 
> the freq scaling up to 3000 is ok, too. everything is just fine. i'm just wondering why the values in the /sys directory differ from the modprobe values and why powernowd scales in 600MHz steps instead of the givven 200 or 400 MHz steps.
> 
> but that's no problem. im happy with the curremt setup  
> ...

 

i cant use fsb 200. as i said before, the cpu only supports a fsb of 133MHz. with DDR that is FSB266. but for modprobe i have to choose 133.

----------

## tnt

If CPU default FSB is 133 it dosn't mean it can run only at that FSB.

Personaly, I had Barton 2500+ that is meant to run at 11 x 166MHz, but I have been running it at 9 x 200MHz, 10 x 200MHx, 10.5 x 200MHz and 11 x 200Mhz before I did mobile mod and make it change multiplier depending on CPU usage. Than, it has been running at 5 x 200MHz without a load, and at 10.5 x 200MHz with the full load. 

Ofcourse, because of the desktop board, I couldn't change voltages on the fly, so there was always 1.65V (default for 11x166).

You should read this about FSB:

http://fab51.com/cpu/barton/athlon-e21.html

and this about other bridges on the Athlon CPU:

http://fab51.com/cpu/barton/athlon-e23.html

Mulitplier on the fly:

http://fab51.com/cpu/barton/athlon-e24.html

(Very useful stuff for others, too  :Wink:   )

----------

## skenvoy

Sorry to drag this thread up, but I need a wee bit of help - 

I have manually patched the 2.6.12-gentoo-r9 kernel with the code provided in both patches for Kconfig and powernow-k7.c by just looking at the source and doing what "patch" does but more intelligently.

The module compiles OK except for the very last bit:

```

  CC [M]  arch/i386/kernel/cpu/cpufreq/powernow-k7.o

arch/i386/kernel/cpu/cpufreq/powernow-k7.c:844: error: initializer element is not constant

arch/i386/kernel/cpu/cpufreq/powernow-k7.c:844: error: (near initialization for `__param_arr_multiplier.num')

arch/i386/kernel/cpu/cpufreq/powernow-k7.c:846: error: initializer element is not constant

arch/i386/kernel/cpu/cpufreq/powernow-k7.c:846: error: (near initialization for `__param_arr_voltage.num')

```

any ideas how to fix this? Relevant section of powernow-k7.c:

```
module_param(acpi_force,  int, 0444);

MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

module_param(overwrite_table,int,0444);

MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

module_param_array(multiplier, int, maxPSTSize, 0444); ***<- here is where it dies***

MODULE_PARM_DESC(multiplier, "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

module_param_array(voltage, int, maxPSTSize, 0444); *** <- and here***

MODULE_PARM_DESC(voltage, "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

module_param(switch_latency,  int, 0444);

MODULE_PARM_DESC(switch_latency, "Set state transition latency in microseconds (default 200us)");

MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");

MODULE_LICENSE ("GPL");
```

----------

## hampelratte

may be you have overlooked a passage in the patch. in my file at line 844, there is a struct. i have patched the 2.6.12r4 kernel.

i could send you my file, if you want.

----------

## skenvoy

 *hampelratte wrote:*   

> may be you have overlooked a passage in the patch. in my file at line 844, there is a struct. i have patched the 2.6.12r4 kernel.
> 
> i could send you my file, if you want.

 

Please do. I thought I applied all the hunks that are in the patch but maybe not :shrug:

Please private-message me the code and I can see what bits need fixing

Edit: the code at http://www.yggdrasl.demon.co.uk/code/powernow-k7-manual-2.6.8.1.patch is incomplete/different to the patch on this forum. Applying the patch on page 1 resulted in it compiling OK. Now let's see what happens...

----------

## skenvoy

yay! After inserting the module with the manual frequency table we have liftoff:

```
powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

powernow: Overwriting PST table with manual settings

powernow: Minimum speed 996 MHz. Maximum speed 1992 MHz.

```

And adding 

```
modprobe cpufreq-conservative && echo conservative > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
```

 allows it to dynamically clock under load. Problem solved  :Cool:  - minus getting all this happening at boot  :Very Happy: 

----------

## Soul_rebel

any info or patch for newer kernels (.12 and .13)?

----------

## VPN-User

I made a patch for 2.6.12 (this is my first self-made patch btw *g*):

powernow-k7-Kconfig-2.6.12.patch

```

--- linux/arch/i386/kernel/cpu/cpufreq/Kconfig.orig   2005-09-10 13:41:55.000000000 +0200

+++ linux/arch/i386/kernel/cpu/cpufreq/Kconfig   2005-09-10 14:13:47.000000000 +0200

@@ -77,6 +77,17 @@

    depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)

    default y

 

+config X86_POWERNOW_K7_MANUAL

+    bool "Manual setting of PowerNow! table for AMD Mobile Athlon/Duron."

+    depends on X86_POWERNOW_K7

+    default n

+    help

+      This adds the possibility to manual change the PST table.

+

+      For details, take a look at <file:Documentation/cpu-freq/>.

+

+      If in doubt, say N.

+

 config X86_POWERNOW_K8

    tristate "AMD Opteron/Athlon64 PowerNow!"

    select CPU_FREQ_TABLE

```

powernow-k7-manual-2.6.12.patch

```

--- linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c.orig   2005-09-10 13:41:55.000000000 +0200

+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2005-09-10 13:30:39.000000000 +0200

@@ -67,7 +67,7 @@

 };

 #endif

 

-#ifdef CONFIG_CPU_FREQ_DEBUG

+#if defined CONFIG_CPU_FREQ_DEBUG || defined CONFIG_X86_POWERNOW_K7_MANUAL

 /* divide by 1000 to get VCore voltage in V. */

 static int mobile_vid_table[32] = {

     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,

@@ -77,7 +77,7 @@

 };

 #endif

 

-/* divide by 10 to get FID. */

+/* divide by 10 to get multiplier. */

 static int fid_codes[32] = {

     110, 115, 120, 125, 50, 55, 60, 65,

     70, 75, 80, 85, 90, 95, 100, 105,

@@ -85,6 +85,31 @@

     150, 225, 160, 165, 170, 180, -1, -1,

 };

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+/* translation table for even multiplier to fid */

+static int even_multiplier[20] = {

+       16, 18, 4, 6, 8, 10, 12, 14,    // 3, 4, 5, 6, 7 ,8 , 9, 10

+       0, 2, 20, 22, 24, 26, 28, 29,   // 11, 12, 13, 14, 15, 16, 17, 18

+       17, 19, 23, 25,         // 19, 20, 21, 22

+};

+

+/* translation table for odd multiplier to fid*/

+static int odd_multiplier[9] = {

+       5, 7, 9, 11, 13, 15, 1, 3,      // 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5

+       21,                     // 13.5

+};

+

+/* This parameters can be used to manually overwrite the tables */

+static int overwrite_table = 0;

+#define MAX_PST 10

+static int multiplier_arr_size = MAX_PST;

+static int voltage_arr_size = MAX_PST;

+static int multiplier[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int voltage[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int switch_latency = 0;

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 /* This parameter is used in order to force ACPI instead of legacy method for

  * configuration purpose.

  */

@@ -98,7 +123,7 @@

 static unsigned int minimum_speed=-1;

 static unsigned int maximum_speed;

 static unsigned int number_scales;

-static unsigned int fsb;

+static unsigned int fsb=0;

 static unsigned int latency;

 static char have_a0;

 

@@ -414,6 +439,143 @@

 }

 #endif

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+static int powernow_manual_settings(union msr_fidvidstatus *fidvidstatus)

+{

+       int i, k, validentry;

+       unsigned int max_multiplier, max_voltage;

+       unsigned int speed, cm;

+       u8 vid, fid;

+       static struct cpufreq_frequency_table *powernow_table_tmp;

+

+       if (switch_latency > 0) {

+               if (switch_latency < 100) {

+                       printk(KERN_INFO PFX

+                              "Settling time passed as %d microseconds."

+                              "Should be at least 100. Correcting.\n",

+                              switch_latency);

+                       switch_latency = 100;

+               }

+               latency = switch_latency;

+       } else {

+               latency = 200;

+       }

+       dprintk("Settling Time: %d microseconds.\n", latency);

+

+       /* get number of specified multipliers */

+       number_scales = multiplier_arr_size;

+       for (i = 0; i < multiplier_arr_size; i++) {

+               if (multiplier[i] == 0) {

+                       number_scales = i;

+                       break;

+               }

+       }

+

+       /* get maximum values */

+       max_multiplier = fid_codes[fidvidstatus->bits.MFID];

+       max_voltage = mobile_vid_table[fidvidstatus->bits.MVID];

+

+       /* allocate memory */

+       powernow_table =

+           kmalloc((sizeof(struct cpufreq_frequency_table) *

+                    (number_scales + 1)), GFP_KERNEL);

+       if (!powernow_table)

+               return -ENOMEM;

+       memset(powernow_table, 0,

+              (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));

+

+       k = 0;

+       for (i = 0; i < number_scales; i++) {

+               validentry = 0;

+               if (multiplier[i] != 0) {

+                       /* fix multiplier */

+                       if (multiplier[i] < 30)

+                               multiplier[i] = multiplier[i] * 10;

+                       if (multiplier[i] < max_multiplier) {

+                               cm = (multiplier[i] / 10);

+

+                               /* check if odd or even muliplier */

+                               if (multiplier[i] % 10) {

+                                       /* odd multiplier */

+                                       if (cm == 16) {

+                                               /* hardcoded because 14.5 and 15.5 fids not possible */

+                                               fid = 27;

+                                               validentry = 1;

+                                       } else if ((cm > 4) && (cm < 14)) {

+                                               fid = odd_multiplier[cm - 5];

+                                               validentry = 1;

+                                       }

+                               } else {

+                                       /* even_multiplier */

+                                       if ((cm < 23) && (cm > 2)) {

+                                               fid = even_multiplier[cm - 3];

+                                               validentry = 1;

+                                       }

+                               }

+                       }

+               }

+

+               if (validentry) {

+                       /* if no voltage specified use CPU default */

+                       if (voltage[i] == 0)

+                               voltage[i] = max_voltage;

+                       /* we do not allow higher voltages than the CPU's maximum 925 mV is the minimum */

+                       if ((voltage[i] <= max_voltage) && (voltage[i] >= 925)) {

+                               if (voltage[i] >= 1300) {

+                                       vid = 40 - (voltage[i] / 50);

+                               } else {

+                                       vid = 67 - (voltage[i] / 25);

+                               }

+                               /* calculate speed */

+                               speed = fsb * fid_codes[fid] / 10;

+                               powernow_table[k].frequency = speed;

+                               powernow_table[k].index = fid;  /*lower 8 bits */

+                               powernow_table[k].index |= (vid << 8);  /*upper 8 bits */

+

+                               if (speed < minimum_speed)

+                                       minimum_speed = speed;

+                               if (speed > maximum_speed)

+                                       maximum_speed = speed;

+

+                               dprintk("   FID: 0x%x (%d.%dx [%dMHz])\t", fid,

+                                       fid_codes[fid] / 10,

+                                       fid_codes[fid] % 10, speed / 1000);

+                               dprintk("VID: 0x%x (%d.%03dV)\n", vid,

+                                       mobile_vid_table[vid] / 1000,

+                                       mobile_vid_table[vid] % 1000);

+                               k++;

+                       }

+               } else {

+                       // invalid entry

+                       dprintk("Entry %d is invalid\n", i + 1);

+               }

+       }

+       if (k < number_scales) {

+               /* some entrys were invalid need to realloc table */

+               number_scales = k;

+               powernow_table_tmp =

+                   kmalloc((sizeof(struct cpufreq_frequency_table) *

+                            (number_scales + 1)), GFP_KERNEL);

+               if (!powernow_table_tmp) {

+                       kfree(powernow_table);

+                       return -ENOMEM;

+               }

+               memcpy(powernow_table_tmp, powernow_table,

+                      (sizeof(struct cpufreq_frequency_table) *

+                       (number_scales + 1)));

+               kfree(powernow_table);

+               powernow_table = powernow_table_tmp;

+       }

+

+       /* Terminate frequency list */

+       powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;

+       powernow_table[number_scales].index = 0;

+

+       return 0;

+}

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 static int powernow_decode_bios (int maxfid, int startvid)

 {

    struct psb_s *psb;

@@ -546,6 +708,18 @@

    if (cpu)

       return 0;

    rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+   #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+       if (fsb) {

+               if (fsb < 1000)

+                       fsb *= 1000;

+

+               if (fsb < 1000 || fsb > 1000000) {

+                       printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                              fsb);

+                       return -EINVAL;

+               }

+       } else

+   #endif

    cfid = fidvidstatus.bits.CFID;

 

    return (fsb * fid_codes[cfid] / 10);

@@ -602,6 +776,12 @@

    if (dmi_check_system(powernow_dmi_table) || acpi_force) {

       printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");

       result = powernow_acpi_init();

+      #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+        } else if (overwrite_table) {

+                printk(KERN_INFO PFX

+                       "Overwriting PST table with manual settings\n");

+                result = powernow_manual_settings(&fidvidstatus);

+      #endif

    } else {

       result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);

       if (result) {

@@ -685,6 +865,21 @@

 

 module_param(acpi_force,  int, 0444);

 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+module_param(overwrite_table, int, 0444);

+MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

+module_param(fsb, uint, 0444);

+MODULE_PARM_DESC(fsb, "(MHz) overrides the calculated FSB");

+module_param_array(multiplier, int, &multiplier_arr_size, 0444);

+MODULE_PARM_DESC(multiplier,

+                "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

+module_param_array(voltage, int, &voltage_arr_size, 0444);

+MODULE_PARM_DESC(voltage,

+                "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

+module_param(switch_latency, int, 0444);

+MODULE_PARM_DESC(switch_latency,

+                "Set state transition latency in microseconds (default 200us)");

+#endif

 

 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");

```

Tell if it works.

----------

## Alan Turing

@VPN-User

Thank you for the patch. It worked for 2.6.12.5 vanilla kernel, but only with adding some parts of the code with an editor.

----------

## Uwe

After a night full of headaches and countless lockups, I was finally successfully with the Patch from VPN-User (although I am now an "expert" in rewriting kernel patches  :Wink: )

The modified patch for my 2.6.13-gentoo-r3 kernel:

```
--- linux/arch/i386/kernel/cpu/cpufreq/Kconfig.orig   2005-09-10 13:41:55.000000000 +0200

+++ linux/arch/i386/kernel/cpu/cpufreq/Kconfig   2005-09-10 14:13:47.000000000 +0200

@@ -77,6 +77,17 @@

    depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)

    default y

 

+config X86_POWERNOW_K7_MANUAL

+    bool "Manual setting of PowerNow! table for AMD Mobile Athlon/Duron."

+    depends on X86_POWERNOW_K7

+    default n

+    help

+      This adds the possibility to manual change the PST table.

+

+      For details, take a look at <file:Documentation/cpu-freq/>.

+

+      If in doubt, say N.

+

 config X86_POWERNOW_K8

    tristate "AMD Opteron/Athlon64 PowerNow!"

    select CPU_FREQ_TABLE 

```

```
--- linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c.orig   2005-09-10 13:41:55.000000000 +0200

+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2005-09-10 13:30:39.000000000 +0200

@@ -67,7 +67,7 @@

 };

 #endif

 

-#ifdef CONFIG_CPU_FREQ_DEBUG

+#if defined CONFIG_CPU_FREQ_DEBUG || defined CONFIG_X86_POWERNOW_K7_MANUAL

 /* divide by 1000 to get VCore voltage in V. */

 static int mobile_vid_table[32] = {

     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,

@@ -77,7 +77,7 @@

 };

 #endif

 

-/* divide by 10 to get FID. */

+/* divide by 10 to get multiplier. */

 static int fid_codes[32] = {

     110, 115, 120, 125, 50, 55, 60, 65,

     70, 75, 80, 85, 90, 95, 100, 105,

@@ -85,6 +85,31 @@

     150, 225, 160, 165, 170, 180, -1, -1,

 };

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+/* translation table for even multiplier to fid */

+static int even_multiplier[20] = {

+       16, 18, 4, 6, 8, 10, 12, 14,    // 3, 4, 5, 6, 7 ,8 , 9, 10

+       0, 2, 20, 22, 24, 26, 28, 29,   // 11, 12, 13, 14, 15, 16, 17, 18

+       17, 19, 23, 25,         // 19, 20, 21, 22

+};

+

+/* translation table for odd multiplier to fid*/

+static int odd_multiplier[9] = {

+       5, 7, 9, 11, 13, 15, 1, 3,      // 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5

+       21,                     // 13.5

+};

+

+/* This parameters can be used to manually overwrite the tables */

+static int overwrite_table = 0;

+#define MAX_PST 10

+static int multiplier_arr_size = MAX_PST;

+static int voltage_arr_size = MAX_PST;

+static int multiplier[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int voltage[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int switch_latency = 0;

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 /* This parameter is used in order to force ACPI instead of legacy method for

  * configuration purpose.

  */

@@ -98,7 +123,7 @@

 static unsigned int minimum_speed=-1;

 static unsigned int maximum_speed;

 static unsigned int number_scales;

-static unsigned int fsb;

+static unsigned int fsb=0;

 static unsigned int latency;

 static char have_a0;

 

@@ -414,6 +439,143 @@

 }

 #endif

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+static int powernow_manual_settings(union msr_fidvidstatus *fidvidstatus)

+{

+       int i, k, validentry;

+       unsigned int max_multiplier, max_voltage;

+       unsigned int speed, cm;

+       u8 vid, fid;

+       static struct cpufreq_frequency_table *powernow_table_tmp;

+

+       if (switch_latency > 0) {

+               if (switch_latency < 100) {

+                       printk(KERN_INFO PFX

+                              "Settling time passed as %d microseconds."

+                              "Should be at least 100. Correcting.\n",

+                              switch_latency);

+                       switch_latency = 100;

+               }

+               latency = switch_latency;

+       } else {

+               latency = 200;

+       }

+       dprintk("Settling Time: %d microseconds.\n", latency);

+

+       /* get number of specified multipliers */

+       number_scales = multiplier_arr_size;

+       for (i = 0; i < multiplier_arr_size; i++) {

+               if (multiplier[i] == 0) {

+                       number_scales = i;

+                       break;

+               }

+       }

+

+       /* get maximum values */

+       max_multiplier = fid_codes[fidvidstatus->bits.MFID];

+       max_voltage = mobile_vid_table[fidvidstatus->bits.MVID];

+

+       /* allocate memory */

+       powernow_table =

+           kmalloc((sizeof(struct cpufreq_frequency_table) *

+                    (number_scales + 1)), GFP_KERNEL);

+       if (!powernow_table)

+               return -ENOMEM;

+       memset(powernow_table, 0,

+              (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));

+

+       k = 0;

+       for (i = 0; i < number_scales; i++) {

+               validentry = 0;

+               if (multiplier[i] != 0) {

+                       /* fix multiplier */

+                       if (multiplier[i] < 30)

+                               multiplier[i] = multiplier[i] * 10;

+                       if (multiplier[i] < max_multiplier) {

+                               cm = (multiplier[i] / 10);

+

+                               /* check if odd or even muliplier */

+                               if (multiplier[i] % 10) {

+                                       /* odd multiplier */

+                                       if (cm == 16) {

+                                               /* hardcoded because 14.5 and 15.5 fids not possible */

+                                               fid = 27;

+                                               validentry = 1;

+                                       } else if ((cm > 4) && (cm < 14)) {

+                                               fid = odd_multiplier[cm - 5];

+                                               validentry = 1;

+                                       }

+                               } else {

+                                       /* even_multiplier */

+                                       if ((cm < 23) && (cm > 2)) {

+                                               fid = even_multiplier[cm - 3];

+                                               validentry = 1;

+                                       }

+                               }

+                       }

+               }

+

+               if (validentry) {

+                       /* if no voltage specified use CPU default */

+                       if (voltage[i] == 0)

+                               voltage[i] = max_voltage;

+                       /* we do not allow higher voltages than the CPU's maximum 925 mV is the minimum */

+                       if ((voltage[i] <= max_voltage) && (voltage[i] >= 925)) {

+                               if (voltage[i] >= 1300) {

+                                       vid = 40 - (voltage[i] / 50);

+                               } else {

+                                       vid = 67 - (voltage[i] / 25);

+                               }

+                               /* calculate speed */

+                               speed = fsb * fid_codes[fid] / 10;

+                               powernow_table[k].frequency = speed;

+                               powernow_table[k].index = fid;  /*lower 8 bits */

+                               powernow_table[k].index |= (vid << 8);  /*upper 8 bits */

+

+                               if (speed < minimum_speed)

+                                       minimum_speed = speed;

+                               if (speed > maximum_speed)

+                                       maximum_speed = speed;

+

+                               dprintk("   FID: 0x%x (%d.%dx [%dMHz])\t", fid,

+                                       fid_codes[fid] / 10,

+                                       fid_codes[fid] % 10, speed / 1000);

+                               dprintk("VID: 0x%x (%d.%03dV)\n", vid,

+                                       mobile_vid_table[vid] / 1000,

+                                       mobile_vid_table[vid] % 1000);

+                               k++;

+                       }

+               } else {

+                       // invalid entry

+                       dprintk("Entry %d is invalid\n", i + 1);

+               }

+       }

+       if (k < number_scales) {

+               /* some entrys were invalid need to realloc table */

+               number_scales = k;

+               powernow_table_tmp =

+                   kmalloc((sizeof(struct cpufreq_frequency_table) *

+                            (number_scales + 1)), GFP_KERNEL);

+               if (!powernow_table_tmp) {

+                       kfree(powernow_table);

+                       return -ENOMEM;

+               }

+               memcpy(powernow_table_tmp, powernow_table,

+                      (sizeof(struct cpufreq_frequency_table) *

+                       (number_scales + 1)));

+               kfree(powernow_table);

+               powernow_table = powernow_table_tmp;

+       }

+

+       /* Terminate frequency list */

+       powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;

+       powernow_table[number_scales].index = 0;

+

+       return 0;

+}

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 static int powernow_decode_bios (int maxfid, int startvid)

 {

    struct psb_s *psb;

@@ -546,6 +708,18 @@

   if (cpu)

      return 0;

   rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+   #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+       if (fsb) {

+               if (fsb < 1000)

+                       fsb *= 1000;

+

+               if (fsb < 1000 || fsb > 1000000) {

+                       printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                              fsb);

+                       return -EINVAL;

+               }

+       } else

+   #endif

   cfid = fidvidstatus.bits.CFID;

   return (fsb * fid_codes[cfid] / 10);

@@ -602,6 +776,12 @@

   if (dmi_check_system(powernow_dmi_table) || acpi_force) {

      printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");

      result = powernow_acpi_init();

+      #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+        } else if (overwrite_table) {

+                printk(KERN_INFO PFX

+                       "Overwriting PST table with manual settings\n");

+                result = powernow_manual_settings(&fidvidstatus);

+      #endif

   } else {

      result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);

      if (result) {

@@ -685,6 +865,21 @@

 

 module_param(acpi_force,  int, 0444);

 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+module_param(overwrite_table, int, 0444);

+MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

+module_param(fsb, uint, 0444);

+MODULE_PARM_DESC(fsb, "(MHz) overrides the calculated FSB");

+module_param_array(multiplier, int, &multiplier_arr_size, 0444);

+MODULE_PARM_DESC(multiplier,

+                "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

+module_param_array(voltage, int, &voltage_arr_size, 0444);

+MODULE_PARM_DESC(voltage,

+                "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

+module_param(switch_latency, int, 0444);

+MODULE_PARM_DESC(switch_latency,

+                "Set state transition latency in microseconds (default 200us)");

+#endif

 

 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors."); 

```

Although I must report some issues I encountered. My system contains an ASUS A7V880 with a mobile Athlon XP 2600+ (2000 Mhz with 133x15).

First I was not able to set any multiplier higher than 14x (higher multipliers are ignored when setting them as parameters for the powernow-k7 module. I must admit that I never tried so set a higher multiplier via software before (I can via BIOS) because when I used the feature beforce under Window$, it was overclocked with 200x12 as maximum). So thus i am wanting to save energy with my HTPC and get a good compromise between the lowest an highest clock, my final setting is a minimum of 666 MHz, increasing in 133 MHz steps up to 1866 Mhz.

Second, the Powernowd Daemon must be set to increase the clock frequency step-by-step, otherwise the system will lock up (dont set the daemon into autostart with default settings, otherwise you have a lot of fun to removing it before the system hangs up immediately after boot (I did  :Wink: ).

Third, cat /proc/cpuinfo now gives me false values (the Gnome CPU Frequency applet shows the correct values): for example, it shows ca. 990 Mhz when at the lowest point (666 Mhz), and incredible 2600 Mhz when at the highest (1866) clock. Cannot be, the CPU would die at 2600 Mhz (believe me, I have tried  :Wink: ).

But now, the system ran stable over night, downloading and emerging some packages, thus having a various load level. Yay!!!

----------

## arnelj

Hi,

I had also problem with false frequency values, my may to solve this was make a small change in the patch file.

I removed the else statement (in red) in part below. 

@@ -546,6 +708,18 @@

	if (cpu)

		return 0;

	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+   #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+       if (fsb) {

+               if (fsb < 1000)

+                       fsb *= 1000;

+

+               if (fsb < 1000 || fsb > 1000000) {

+                       printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                              fsb);

+                       return -EINVAL;

+               }

+       } else

+   #endif

	cfid = fidvidstatus.bits.CFID;

	return (fsb * fid_codes[cfid] / 10);

My other problem is that this patch dosn't work as good with the 2.6.14-gentoo-r3 kernel as it did with previous kernels. The max frequency is now 2.18 Ghz instead of 2.32 Ghz.

Shuttle AK32A 266FSB

AthlonXP 2500+ mobile @2.32GHz /190Mhz fsb

2.6.13-gentoo-r5 kernel 

Shuttle AK32A 266FSB

AthlonXP 2500+ mobile @2.18GHz / 190 Mhz fsb

2.6.14-gentoo-r2 kernel

----------

## jarno

Hi,

I'm running Athlon XP mobile 2600+ with Gigabyte GA-7ZXE (KT133A chipset). I patched my 2.6.14.3 vanilla kernel, and when loadin the powernow-k7 -module with options 'overwrite_table=1 multiplier=8,10,12,14,15,16,17' I get this:

```
powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

Detected 800.570 MHz processor.

powernow: Overwriting PST table with manual settings

powernow: Minimum speed 1067 MHz. Maximum speed 1867 MHz.

------------[ cut here ]------------

kernel BUG at drivers/cpufreq/cpufreq_userspace.c:136!

invalid operand: 0000 [#1]

Modules linked in: powernow_k7 freq_table processor unix

CPU:    0

EIP:    0060:[<c037d5b4>]    Not tainted VLI

EFLAGS: 00010246   (2.6.14.3)

EIP is at cpufreq_governor_userspace+0x224/0x231

eax: ffffffea   ebx: dfc64360   ecx: 00000000   edx: 00000000

esi: 00000000   edi: df1e7ebc   ebp: dfc64360   esp: df1e7e20

ds: 007b   es: 007b   ss: 0068

Process modprobe (pid: 2685, threadinfo=df1e6000 task=dfa22ab0)

Stack: dfc64360 e083a8e1 00000000 00000001 dfc64360 df1e7ebc dfc64360 c037ca1e

       dfc64360 00000001 df1e7ea8 00000000 df1e7ebc c037cdfb dfc64360 00000001

       df1e7ea8 df1e7ea8 dfc64360 00000000 df1e7ea8 c037ce91 dfc64360 df1e7ea8

Call Trace:

 [<e083a8e1>] acpi_processor_ppc_notifier+0xd/0x86 [processor]

 [<c037ca1e>] __cpufreq_governor+0x3e/0xc0

 [<c037cdfb>] __cpufreq_set_policy+0x16b/0x1b0

 [<c037ce91>] cpufreq_set_policy+0x51/0x80

 [<c037c283>] cpufreq_add_dev+0x213/0x2b0

 [<c037c410>] handle_update+0x0/0x10

 [<c02fefb9>] sysdev_driver_register+0x69/0xb0

 [<e087ac80>] powernow_target+0x0/0x50 [powernow_k7]

 [<c037cfc9>] cpufreq_register_driver+0x59/0xc0

 [<e086334d>] powernow_init+0x1d/0x25 [powernow_k7]

 [<c01358f3>] sys_init_module+0xd3/0x1d0

 [<c010307b>] sysenter_past_esp+0x54/0x75

Code: f0 89 4c 24 04 c1 e2 04 c1 e0 06 c7 44 24 08 00 00 00 00 29 d0 29 f0 8d 3c 85 c0 60 56 c0 89 3c 24 e8 91 f3 ff ff e9 7c ff ff ff <0f> 0b 88 00 20 1e 46 c0 e9 17 ff ff ff 8d 05 c0 a7 4a c0 e8 dc
```

Does anyone know what's wrong with cpufreq_userspace.c? Or is the problem somewhere else?

Here are related options from my .config:

```
#

# ACPI (Advanced Configuration and Power Interface) Support

#

CONFIG_ACPI=y

CONFIG_ACPI_SLEEP=y

CONFIG_ACPI_SLEEP_PROC_FS=y

CONFIG_ACPI_SLEEP_PROC_SLEEP=y

CONFIG_ACPI_AC=y

# CONFIG_ACPI_BATTERY is not set

CONFIG_ACPI_BUTTON=y

CONFIG_ACPI_VIDEO=y

CONFIG_ACPI_HOTKEY=y

CONFIG_ACPI_FAN=y

CONFIG_ACPI_PROCESSOR=m

CONFIG_ACPI_THERMAL=m

# CONFIG_ACPI_ASUS is not set

# CONFIG_ACPI_IBM is not set

# CONFIG_ACPI_TOSHIBA is not set

CONFIG_ACPI_CUSTOM_DSDT_INITRD=y

CONFIG_ACPI_BLACKLIST_YEAR=0

# CONFIG_ACPI_DEBUG is not set

CONFIG_ACPI_EC=y

CONFIG_ACPI_POWER=y

CONFIG_ACPI_SYSTEM=y

CONFIG_X86_PM_TIMER=y

# CONFIG_ACPI_CONTAINER is not set

#

# APM (Advanced Power Management) BIOS Support

#

# CONFIG_APM is not set

#

# CPU Frequency scaling

#

CONFIG_CPU_FREQ=y

CONFIG_CPU_FREQ_TABLE=m

# CONFIG_CPU_FREQ_DEBUG is not set

CONFIG_CPU_FREQ_STAT=m

CONFIG_CPU_FREQ_STAT_DETAILS=y

# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set

CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y

CONFIG_CPU_FREQ_GOV_PERFORMANCE=m

CONFIG_CPU_FREQ_GOV_POWERSAVE=m

CONFIG_CPU_FREQ_GOV_USERSPACE=y

CONFIG_CPU_FREQ_GOV_ONDEMAND=m

CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m

#

# CPUFreq processor drivers

#

CONFIG_X86_ACPI_CPUFREQ=m

# CONFIG_X86_POWERNOW_K6 is not set

CONFIG_X86_POWERNOW_K7=m

CONFIG_X86_POWERNOW_K7_ACPI=y

CONFIG_X86_POWERNOW_K7_MANUAL=y

# CONFIG_X86_POWERNOW_K8 is not set

# CONFIG_X86_GX_SUSPMOD is not set

# CONFIG_X86_SPEEDSTEP_CENTRINO is not set

# CONFIG_X86_SPEEDSTEP_ICH is not set

# CONFIG_X86_SPEEDSTEP_SMI is not set

# CONFIG_X86_P4_CLOCKMOD is not set

# CONFIG_X86_CPUFREQ_NFORCE2 is not set

# CONFIG_X86_LONGRUN is not set

# CONFIG_X86_LONGHAUL is not set
```

I've also tried with 2.6.13.4 and 2.6.12.6 with same results...

--

    /jarno

----------

## kilroy12

Hi,

I'm running a Duron 1800 with mobile hack on  Asrock board. I patched my  2.6.13-gentoo-r3 kernel.

This ist functional, but in 2.6.14 powernow-k7.c is different. The patch doesn't work, has anyone modified the patch that can i use it with >=2.6.14?

thanks 

Kilroy1205

----------

## jarno

 *kilroy12 wrote:*   

> Hi,
> 
> has anyone modified the patch that can i use it with >=2.6.14?
> 
> 

 

This is for 2.6.14.3 Vanilla-source from kernel.org, I'm not sure if it works for gentoo-source. The patch older patch for Kconfig works for me.

```

--- /usr/src/linux-2.6.14.3/arch/i386/kernel/cpu/cpufreq/powernow-k7.c.org      2005-11-27 14:33:12.000000000 +0200

+++ /usr/src/linux-2.6.14.3/arch/i386/kernel/cpu/cpufreq/powernow-k7.c         2005-11-27 15:40:05.000000000 +0200

@@ -67,7 +67,7 @@

 };

 #endif

-#ifdef CONFIG_CPU_FREQ_DEBUG

+#if defined CONFIG_CPU_FREQ_DEBUG || defined CONFIG_X86_POWERNOW_K7_MANUAL

 /* divide by 1000 to get VCore voltage in V. */

 static int mobile_vid_table[32] = {

     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,

@@ -77,7 +77,7 @@

 };

 #endif

-/* divide by 10 to get FID. */

+/* divide by 10 to get multiplier. */

 static int fid_codes[32] = {

     110, 115, 120, 125, 50, 55, 60, 65,

     70, 75, 80, 85, 90, 95, 100, 105,

@@ -85,6 +85,31 @@

     150, 225, 160, 165, 170, 180, -1, -1,

 };

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+/* translation table for even multiplier to fid */

+static int even_multiplier[20] = {

+       16, 18, 4, 6, 8, 10, 12, 14,    // 3, 4, 5, 6, 7 ,8 , 9, 10

+       0, 2, 20, 22, 24, 26, 28, 29,   // 11, 12, 13, 14, 15, 16, 17, 18

+       17, 19, 23, 25,         // 19, 20, 21, 22

+};

+

+/* translation table for odd multiplier to fid*/

+static int odd_multiplier[9] = {

+       5, 7, 9, 11, 13, 15, 1, 3,      // 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5

+       21,                     // 13.5

+};

+

+/* This parameters can be used to manually overwrite the tables */

+static int overwrite_table = 0;

+#define MAX_PST 10

+static int multiplier_arr_size = MAX_PST;

+static int voltage_arr_size = MAX_PST;

+static int multiplier[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int voltage[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int switch_latency = 0;

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 /* This parameter is used in order to force ACPI instead of legacy method for

  * configuration purpose.

  */

@@ -98,7 +123,7 @@

 static unsigned int minimum_speed=-1;

 static unsigned int maximum_speed;

 static unsigned int number_scales;

-static unsigned int fsb;

+static unsigned int fsb=0;

 static unsigned int latency;

 static char have_a0;

@@ -414,6 +439,143 @@

 }

 #endif

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+static int powernow_manual_settings(union msr_fidvidstatus *fidvidstatus)

+{

+       int i, k, validentry;

+       unsigned int max_multiplier, max_voltage;

+       unsigned int speed, cm;

+       u8 vid, fid;

+       static struct cpufreq_frequency_table *powernow_table_tmp;

+

+       if (switch_latency > 0) {

+               if (switch_latency < 100) {

+                       printk(KERN_INFO PFX

+                              "Settling time passed as %d microseconds."

+                              "Should be at least 100. Correcting.\n",

+                              switch_latency);

+                       switch_latency = 100;

+               }

+               latency = switch_latency;

+       } else {

+               latency = 200;

+       }

+       dprintk("Settling Time: %d microseconds.\n", latency);

+

+       /* get number of specified multipliers */

+       number_scales = multiplier_arr_size;

+       for (i = 0; i < multiplier_arr_size; i++) {

+               if (multiplier[i] == 0) {

+                       number_scales = i;

+                       break;

+               }

+       }

+

+       /* get maximum values */

+       max_multiplier = fid_codes[fidvidstatus->bits.MFID];

+       max_voltage = mobile_vid_table[fidvidstatus->bits.MVID];

+

+       /* allocate memory */

+       powernow_table =

+           kmalloc((sizeof(struct cpufreq_frequency_table) *

+                    (number_scales + 1)), GFP_KERNEL);

+       if (!powernow_table)

+               return -ENOMEM;

+       memset(powernow_table, 0,

+              (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));

+

+       k = 0;

+       for (i = 0; i < number_scales; i++) {

+               validentry = 0;

+               if (multiplier[i] != 0) {

+                       /* fix multiplier */

+                       if (multiplier[i] < 30)

+                               multiplier[i] = multiplier[i] * 10;

+                       if (multiplier[i] < max_multiplier) {

+                               cm = (multiplier[i] / 10);

+

+                               /* check if odd or even muliplier */

+                               if (multiplier[i] % 10) {

+                                       /* odd multiplier */

+                                       if (cm == 16) {

+                                               /* hardcoded because 14.5 and 15.5 fids not possible */

+                                               fid = 27;

+                                               validentry = 1;

+                                       } else if ((cm > 4) && (cm < 14)) {

+                                               fid = odd_multiplier[cm - 5];

+                                               validentry = 1;

+                                       }

+                               } else {

+                                       /* even_multiplier */

+                                       if ((cm < 23) && (cm > 2)) {

+                                               fid = even_multiplier[cm - 3];

+                                               validentry = 1;

+                                       }

+                               }

+                       }

+               }

+

+               if (validentry) {

+                       /* if no voltage specified use CPU default */

+                       if (voltage[i] == 0)

+                               voltage[i] = max_voltage;

+                       /* we do not allow higher voltages than the CPU's maximum 925 mV is the minimum */

+                       if ((voltage[i] <= max_voltage) && (voltage[i] >= 925)) {

+                               if (voltage[i] >= 1300) {

+                                       vid = 40 - (voltage[i] / 50);

+                               } else {

+                                       vid = 67 - (voltage[i] / 25);

+                               }

+                               /* calculate speed */

+                               speed = fsb * fid_codes[fid] / 10;

+                               powernow_table[k].frequency = speed;

+                               powernow_table[k].index = fid;  /*lower 8 bits */

+                               powernow_table[k].index |= (vid << 8);  /*upper 8 bits */

+

+                               if (speed < minimum_speed)

+                                       minimum_speed = speed;

+                               if (speed > maximum_speed)

+                                       maximum_speed = speed;

+

+                               dprintk("   FID: 0x%x (%d.%dx [%dMHz])\t", fid,

+                                       fid_codes[fid] / 10,

+                                       fid_codes[fid] % 10, speed / 1000);

+                               dprintk("VID: 0x%x (%d.%03dV)\n", vid,

+                                       mobile_vid_table[vid] / 1000,

+                                       mobile_vid_table[vid] % 1000);

+                               k++;

+                       }

+               } else {

+                       // invalid entry

+                       dprintk("Entry %d is invalid\n", i + 1);

+               }

+       }

+       if (k < number_scales) {

+               /* some entrys were invalid need to realloc table */

+               number_scales = k;

+               powernow_table_tmp =

+                   kmalloc((sizeof(struct cpufreq_frequency_table) *

+                            (number_scales + 1)), GFP_KERNEL);

+               if (!powernow_table_tmp) {

+                       kfree(powernow_table);

+                       return -ENOMEM;

+               }

+               memcpy(powernow_table_tmp, powernow_table,

+                      (sizeof(struct cpufreq_frequency_table) *

+                       (number_scales + 1)));

+               kfree(powernow_table);

+               powernow_table = powernow_table_tmp;

+       }

+

+       /* Terminate frequency list */

+       powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;

+       powernow_table[number_scales].index = 0;

+

+       return 0;

+}

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 static int powernow_decode_bios (int maxfid, int startvid)

 {

        struct psb_s *psb;

@@ -546,6 +708,18 @@

        if (cpu)

                return 0;

        rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+    #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+        if (fsb) {

+                if (fsb < 1000)

+                        fsb *= 1000;

+

+                if (fsb < 1000 || fsb > 1000000) {

+                        printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                               fsb);

+                        return -EINVAL;

+                }

+        } else

+    #endif

        cfid = fidvidstatus.bits.CFID;

        return (fsb * fid_codes[cfid] / 10);

@@ -602,6 +776,12 @@

        if (dmi_check_system(powernow_dmi_table) || acpi_force) {

                printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");

                result = powernow_acpi_init();

+       #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+         } else if (overwrite_table) {

+                 printk(KERN_INFO PFX

+                        "Overwriting PST table with manual settings\n");

+                 result = powernow_manual_settings(&fidvidstatus);

+       #endif

        } else {

                result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);

                if (result) {

@@ -683,6 +863,21 @@

 module_param(acpi_force,  int, 0444);

 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+module_param(overwrite_table, int, 0444);

+MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

+module_param(fsb, uint, 0444);

+MODULE_PARM_DESC(fsb, "(MHz) overrides the calculated FSB");

+module_param_array(multiplier, int, &multiplier_arr_size, 0444);

+MODULE_PARM_DESC(multiplier,

+                "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

+module_param_array(voltage, int, &voltage_arr_size, 0444);

+MODULE_PARM_DESC(voltage,

+                "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

+module_param(switch_latency, int, 0444);

+MODULE_PARM_DESC(switch_latency,

+                "Set state transition latency in microseconds (default 200us)");

+#endif

 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");

```

----------

## kilroy12

 *jarno wrote:*   

> 
> 
> This is for 2.6.14.3 Vanilla-source from kernel.org, I'm not sure if it works for gentoo-source.
> 
> 

 

Thanks this patch works with gentoo-sources-2.6.14-r3, but there are 2 rej.

But small, I have edited by hand.

Regards

Kilroy12

----------

## kilroy12

Hi,

another Kernel another Problem......

does anyone have make the patch funktional for kernel 2.6.15?

I´m using gentoo-sources-2.6.15-r4 with the patch from jarno.

 The modile compiles fine, but when  modprobe powernow-k7 overwrite_table=1 multiplier=3,5,10,11,12,21

 then i see this in dmesg.

```
powernow: PowerNOW! Technology present. Can scale: frequency and voltage.

Detected 1462.826 MHz processor.

powernow: Overwriting PST table with manual settings

powernow: Minimum speed 398 MHz. Maximum speed 1329 MHz.

Unable to handle kernel paging request at virtual address 144acfd0

 printing eip:

d0dbbaa4

*pde = 00000000

Oops: 0000 [#1]

PREEMPT

Modules linked in: powernow_k7 w83627hf w83781d hwmon_vid hwmon eeprom i2c_isa i 2c_viapro b2c2_flexcop_pci b2c2_flexcop_usb b2c2_flexcop nxt200x stv0297_cs2 lgd t330x budget_av budget_ci budget budget_core dvb_ttpci ttpci_eeprom saa7146_vv s aa7146 nxt6000 s5h1420 ttusbdecfe bcm3510 nxt2002 stv0297 mt352 mt312 cx22702 cx 24110 tda8083 l64781 dib3000mc dib3000mb dib3000_common tda10021 tda1004x ves182 0 stv0299 cx22700 sp8870 ves1x93 dvb_pll dvb_core video_buf v4l2_common v4l1_com pat videodev evdev firmware_class i2c_core usb_storage

CPU:    0

EIP:    0060:[<d0dbbaa4>]    Not tainted VLI

EFLAGS: 00010293   (2.6.15-gentoo-r4)

EIP is at powernow_get+0x63/0x81 [powernow_k7]

eax: 00020390   ebx: 00020778   ecx: 00000000   edx: 00020778

esi: 00001500   edi: 17d78400   ebp: d0dbbf7c   esp: c998de60

ds: 007b   es: 007b   ss: 0068

Process modprobe (pid: 5494, threadinfo=c998c000 task=c994d110)

Stack: 00020778 ca09b880 17d78400 d0dbbf7c d0daa23e 00000000 00001500 00000000

       ca09b880 00000000 fffffff4 c04f6268 c0379823 ca09b880 c045beac c998dee0

       c01251aa cfa19580 00000001 00000000 00000000 00000001 00000000 c994d110

Call Trace:

 [<d0daa23e>] powernow_cpu_init+0x1ae/0x1d5 [powernow_k7]

 [<c0379823>] cpufreq_add_dev+0xe9/0x2ab

 [<c01251aa>] autoremove_wake_function+0x18/0x3a

 [<c01224a2>] rcu_check_quiescent_state+0x55/0x6c

 [<c0122552>] __rcu_process_callbacks+0x98/0xb3

 [<c0122595>] rcu_process_callbacks+0x28/0x2c

 [<c0118961>] tasklet_action+0x3a/0x59

 [<c0118738>] __do_softirq+0x34/0x7d

 [<c011883d>] irq_exit+0x29/0x34

 [<c0104247>] do_IRQ+0x1e/0x24

 [<c0102dc6>] common_interrupt+0x1a/0x20

 [<c0318e16>] sysdev_driver_register+0x67/0xa8

 [<c037a418>] cpufreq_register_driver+0x87/0xe7

 [<d0daa27d>] powernow_init+0x18/0x1e [powernow_k7]

 [<c012a95e>] sys_init_module+0xb9/0x1b1

 [<c0102bf9>] syscall_call+0x7/0xb

Code: 15 8c d6 db d0 8d 82 18 fc ff ff 3d 58 3e 0f 00 76 19 52 68 fc bd db d0 e8  37 8f 35 ef b8 ea ff ff ff 5f 5d eb 1e 89 f5 83 e5 1f <8b> 04 ad e0 d1 db d0 ba  0a 00 00 00 0f af 05 8c d6 db d0 89 d1

```

What does it mean?

Regards 

Sven

----------

## kilroy12

Hi,

ok I think i´ve found the mistake in funktion powernow_get 

Its the same thing like arnelj have had.

```
static unsigned int powernow_get(unsigned int cpu)

{

   union msr_fidvidstatus fidvidstatus;

   unsigned int cfid;

   if (cpu)

      return 0;

   rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

     #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

         if (fsb) {

                 if (fsb < 1000)

                         fsb *= 1000;

                 if (fsb < 1000 || fsb > 1000000) {

                         printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

                                fsb);

                         return -EINVAL;

                 }

         }  else  <-- this else is without  any if, so delete it !!!

     #endif

   cfid = fidvidstatus.bits.CFID;

   return (fsb * fid_codes[cfid] / 10);

}
```

I think it´s a else without an  if.

This is olny a Idea, because i can´t taste it at the moment.

Regards

Sven

----------

## kilroy12

ok thats it, 

only the "else" was it.

Regards

Sven

----------

## VPN-User

Here are the (fixed) patches for 2.6.15-gentoo-r1

powernow-k7-Kconfig-2.6.15-gentoo-r1.patch

```
--- arch/i386/kernel/cpu/cpufreq/Kconfig   2006-02-11 01:23:38.000000000 +0100

+++ arch/i386/kernel/cpu/cpufreq/Kconfig.new   2006-02-11 01:22:55.000000000 +0100

@@ -76,6 +76,17 @@

    depends on X86_POWERNOW_K7 && ACPI_PROCESSOR

    depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)

    default y

+   

+config X86_POWERNOW_K7_MANUAL

+   bool "Manual setting of PowerNow! table for AMD Mobile Athlon/Duron."

+   depends on X86_POWERNOW_K7

+   default n

+   help

+     This adds the possibility to manual change the PST table.

+

+     For details, take a look at <file:Documentation/cpu-freq/>.

+

+     If in doubt, say N.

 

 config X86_POWERNOW_K8

    tristate "AMD Opteron/Athlon64 PowerNow!"

```

powernow-k7-manual-2.6.15-gentoo-r1.patch

```
--- arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2006-02-11 01:23:57.000000000 +0100

+++ arch/i386/kernel/cpu/cpufreq/powernow-k7.c.new   2006-02-11 01:23:29.000000000 +0100

@@ -67,7 +67,7 @@

 };

 #endif

 

-#ifdef CONFIG_CPU_FREQ_DEBUG

+#if defined CONFIG_CPU_FREQ_DEBUG || defined CONFIG_X86_POWERNOW_K7_MANUAL

 /* divide by 1000 to get VCore voltage in V. */

 static int mobile_vid_table[32] = {

     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,

@@ -77,7 +77,7 @@

 };

 #endif

 

-/* divide by 10 to get FID. */

+/* divide by 10 to get multiplier. */

 static int fid_codes[32] = {

     110, 115, 120, 125, 50, 55, 60, 65,

     70, 75, 80, 85, 90, 95, 100, 105,

@@ -85,6 +85,31 @@

     150, 225, 160, 165, 170, 180, -1, -1,

 };

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+/* translation table for even multiplier to fid */

+static int even_multiplier[20] = {

+       16, 18, 4, 6, 8, 10, 12, 14,    // 3, 4, 5, 6, 7 ,8 , 9, 10

+       0, 2, 20, 22, 24, 26, 28, 29,   // 11, 12, 13, 14, 15, 16, 17, 18

+       17, 19, 23, 25,         // 19, 20, 21, 22

+};

+

+/* translation table for odd multiplier to fid*/

+static int odd_multiplier[9] = {

+       5, 7, 9, 11, 13, 15, 1, 3,      // 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5

+       21,                     // 13.5

+};

+

+/* This parameters can be used to manually overwrite the tables */

+static int overwrite_table = 0;

+#define MAX_PST 10

+static int multiplier_arr_size = MAX_PST;

+static int voltage_arr_size = MAX_PST;

+static int multiplier[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int voltage[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int switch_latency = 0;

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 /* This parameter is used in order to force ACPI instead of legacy method for

  * configuration purpose.

  */

@@ -98,7 +123,7 @@

 static unsigned int minimum_speed=-1;

 static unsigned int maximum_speed;

 static unsigned int number_scales;

-static unsigned int fsb;

+static unsigned int fsb=0;

 static unsigned int latency;

 static char have_a0;

 

@@ -408,6 +433,144 @@

 }

 #endif

 

+

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+static int powernow_manual_settings(union msr_fidvidstatus *fidvidstatus)

+{

+       int i, k, validentry;

+       unsigned int max_multiplier, max_voltage;

+       unsigned int speed, cm;

+       u8 vid, fid;

+       static struct cpufreq_frequency_table *powernow_table_tmp;

+

+       if (switch_latency > 0) {

+               if (switch_latency < 100) {

+                       printk(KERN_INFO PFX

+                              "Settling time passed as %d microseconds."

+                              "Should be at least 100. Correcting.\n",

+                              switch_latency);

+                       switch_latency = 100;

+               }

+               latency = switch_latency;

+       } else {

+               latency = 200;

+       }

+       dprintk("Settling Time: %d microseconds.\n", latency);

+

+       /* get number of specified multipliers */

+       number_scales = multiplier_arr_size;

+       for (i = 0; i < multiplier_arr_size; i++) {

+               if (multiplier[i] == 0) {

+                       number_scales = i;

+                       break;

+               }

+       }

+

+       /* get maximum values */

+       max_multiplier = fid_codes[fidvidstatus->bits.MFID];

+       max_voltage = mobile_vid_table[fidvidstatus->bits.MVID];

+

+       /* allocate memory */

+       powernow_table =

+           kmalloc((sizeof(struct cpufreq_frequency_table) *

+                    (number_scales + 1)), GFP_KERNEL);

+       if (!powernow_table)

+               return -ENOMEM;

+       memset(powernow_table, 0,

+              (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));

+

+       k = 0;

+       for (i = 0; i < number_scales; i++) {

+               validentry = 0;

+               if (multiplier[i] != 0) {

+                       /* fix multiplier */

+                       if (multiplier[i] < 30)

+                               multiplier[i] = multiplier[i] * 10;

+                       if (multiplier[i] < max_multiplier) {

+                               cm = (multiplier[i] / 10);

+

+                               /* check if odd or even muliplier */

+                               if (multiplier[i] % 10) {

+                                       /* odd multiplier */

+                                       if (cm == 16) {

+                                               /* hardcoded because 14.5 and 15.5 fids not possible */

+                                               fid = 27;

+                                               validentry = 1;

+                                       } else if ((cm > 4) && (cm < 14)) {

+                                               fid = odd_multiplier[cm - 5];

+                                               validentry = 1;

+                                       }

+                               } else {

+                                       /* even_multiplier */

+                                       if ((cm < 23) && (cm > 2)) {

+                                               fid = even_multiplier[cm - 3];

+                                               validentry = 1;

+                                       }

+                               }

+                       }

+               }

+

+               if (validentry) {

+                       /* if no voltage specified use CPU default */

+                       if (voltage[i] == 0)

+                               voltage[i] = max_voltage;

+                       /* we do not allow higher voltages than the CPU's maximum 925 mV is the minimum */

+                       if ((voltage[i] <= max_voltage) && (voltage[i] >= 925)) {

+                               if (voltage[i] >= 1300) {

+                                       vid = 40 - (voltage[i] / 50);

+                               } else {

+                                       vid = 67 - (voltage[i] / 25);

+                               }

+                               /* calculate speed */

+                               speed = fsb * fid_codes[fid] / 10;

+                               powernow_table[k].frequency = speed;

+                               powernow_table[k].index = fid;  /*lower 8 bits */

+                               powernow_table[k].index |= (vid << 8);  /*upper 8 bits */

+

+                               if (speed < minimum_speed)

+                                       minimum_speed = speed;

+                               if (speed > maximum_speed)

+                                       maximum_speed = speed;

+

+                               dprintk("   FID: 0x%x (%d.%dx [%dMHz])\t", fid,

+                                       fid_codes[fid] / 10,

+                                       fid_codes[fid] % 10, speed / 1000);

+                               dprintk("VID: 0x%x (%d.%03dV)\n", vid,

+                                       mobile_vid_table[vid] / 1000,

+                                       mobile_vid_table[vid] % 1000);

+                               k++;

+                       }

+               } else {

+                       // invalid entry

+                       dprintk("Entry %d is invalid\n", i + 1);

+               }

+       }

+       if (k < number_scales) {

+               /* some entrys were invalid need to realloc table */

+               number_scales = k;

+               powernow_table_tmp =

+                   kmalloc((sizeof(struct cpufreq_frequency_table) *

+                            (number_scales + 1)), GFP_KERNEL);

+               if (!powernow_table_tmp) {

+                       kfree(powernow_table);

+                       return -ENOMEM;

+               }

+               memcpy(powernow_table_tmp, powernow_table,

+                      (sizeof(struct cpufreq_frequency_table) *

+                       (number_scales + 1)));

+               kfree(powernow_table);

+               powernow_table = powernow_table_tmp;

+       }

+

+       /* Terminate frequency list */

+       powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;

+       powernow_table[number_scales].index = 0;

+

+       return 0;

+}

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 static int powernow_decode_bios (int maxfid, int startvid)

 {

    struct psb_s *psb;

@@ -540,6 +703,18 @@

    if (cpu)

       return 0;

    rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+    #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+        if (fsb) {

+                if (fsb < 1000)

+                        fsb *= 1000;

+

+                if (fsb < 1000 || fsb > 1000000) {

+                        printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                               fsb);

+                        return -EINVAL;

+                }

+        }

+    #endif

    cfid = fidvidstatus.bits.CFID;

 

    return (fsb * fid_codes[cfid] / 10);

@@ -596,6 +771,12 @@

    if (dmi_check_system(powernow_dmi_table) || acpi_force) {

       printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");

       result = powernow_acpi_init();

+        #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+          } else if (overwrite_table) {

+                 printk(KERN_INFO PFX

+                        "Overwriting PST table with manual settings\n");

+                 result = powernow_manual_settings(&fidvidstatus);

+        #endif

    } else {

       result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);

       if (result) {

@@ -677,6 +858,21 @@

 

 module_param(acpi_force,  int, 0444);

 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+module_param(overwrite_table, int, 0444);

+MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

+module_param(fsb, uint, 0444);

+MODULE_PARM_DESC(fsb, "(MHz) overrides the calculated FSB");

+module_param_array(multiplier, int, &multiplier_arr_size, 0444);

+MODULE_PARM_DESC(multiplier,

+                "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

+module_param_array(voltage, int, &voltage_arr_size, 0444);

+MODULE_PARM_DESC(voltage,

+                "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

+module_param(switch_latency, int, 0444);

+MODULE_PARM_DESC(switch_latency,

+                "Set state transition latency in microseconds (default 200us)");

+#endif

 

 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");

```

----------

## woZa

```
cd /usr/src/linux && patch -p1 --dry-run < ~/k7-powernow.patch
```

gives

```
can't find file to patch at input line 3

Perhaps you used the wrong -p or --strip option?

The text leading up to this was:

--------------------------

|--- arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2006-02-11 01:23:57.000000000 +0100 

|+++ arch/i386/kernel/cpu/cpufreq/powernow-k7.c.new   2006-02-11 01:23:29.000000000 +0100 

--------------------------

File to patch:
```

I type in 

```
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
```

 and get the response

```
patching file powernow-k7.c

Hunk #1 FAILED at 67.

Hunk #2 FAILED at 77.

Hunk #3 FAILED at 85.

Hunk #4 FAILED at 123.

Hunk #5 FAILED at 433.

Hunk #6 FAILED at 703.

Hunk #7 FAILED at 771.

Hunk #8 FAILED at 858.

8 out of 8 hunks FAILED -- saving rejects to file powernow-k7.c.rej
```

Am I using the correct patch command or is something else up?

Running kernel 2.6.15-gentoo-r1 and patching with above patch...

----------

## VPN-User

I just copy the patchfiles in the /usr/src/linux dir and do a "patch -p1 < file.patch" and it works.

BTW you can easily manually edit the 2 files using vi or something like that.

----------

## woZa

I went through the patch and edited out the white spaces at the end of each line and now I get

```
can't find file to patch at input line 3

Perhaps you used the wrong -p or --strip option?

The text leading up to this was:

--------------------------

|--- arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2006-02-11 01:23:57.000000000 +0100

|+++ arch/i386/kernel/cpu/cpufreq/powernow-k7.c.new   2006-02-11 01:23:29.000000000 +0100

--------------------------

File to patch: arch/i386/kernel/cpu/cpufreq/powernow-k7.c

patching file arch/i386/kernel/cpu/cpufreq/powernow-k7.c

Hunk #5 succeeded at 433 with fuzz 1.

Hunk #6 FAILED at 703.

Hunk #7 FAILED at 771.

2 out of 8 hunks FAILED -- saving rejects to file arch/i386/kernel/cpu/cpufreq/powernow-k7.c.rej
```

----------

## VPN-User

You can' t just reapply a patch which already did something (at least partially). You have to copy over the original file first bevor retrying.

----------

## VPN-User

Sorry I was wrong I use "patch -p0 < patchfile" when in /usr/src/linux and patchfile in this dir.

I just retried my patch with linux-2.6.15-gentoo-r1 and it works flawlessly.

----------

## woZa

Have been using 

```
--dry-run
```

 which only gives the output of what would happen if the patch was applied. p0 patches the file straight away but still gives error 

```
patching file arch/i386/kernel/cpu/cpufreq/powernow-k7.c

Hunk #5 succeeded at 433 with fuzz 1.

Hunk #6 FAILED at 703.

Hunk #7 FAILED at 771.

2 out of 8 hunks FAILED -- saving rejects to file arch/i386/kernel/cpu/cpufreq/powernow-k7.c.rej
```

Guess I'll have to do those 2 failed hunks by hand. Thanks anyways...

----------

## VPN-User

 *woZa wrote:*   

> Have been using 
> 
> ```
> --dry-run
> ```
> ...

 

I don' t get any errors. Perhaps something went wrong while copying code from the forum.

----------

## rufflove

Does FID changing work on VIA boards with older multiplier 'unlocked' Thoroughbred Bs? For example, I can change the FID upwards of its stock value via BIOS using my MSI KT400/Tbred B combination - would Powernow work OK with this setup, or would I still need to do some 'bridging'?

----------

## VPN-User

You still have to mod it to an "mobile Athlon". At least I think.

----------

## ebat

Has somebody working patch for gentoo-sources-2.6.16-r7  :Question: 

----------

## VPN-User

Latest posted patch works fine.

----------

## ebat

 *VPN-User wrote:*   

> Latest posted patch works fine.

 

Not for me:

```
patching file arch/i386/kernel/cpu/cpufreq/powernow-k7.c 

Hunk #5 succeeded at 433 with fuzz 1. 

Hunk #6 FAILED at 703. 

Hunk #7 FAILED at 771. 

2 out of 8 hunks FAILED -- saving rejects to file arch/i386/kernel/cpu/cpufreq/powernow-k7.c.rej
```

For 2.6.15-gentoo-r1 same error   :Confused: 

----------

## VPN-User

I will repost the patch for you (also runs with gentoo-sources-2.6.16-r7):

powernow-k7-Kconfig-2.6.16-gentoo-r3.patch

```
--- arch/i386/kernel/cpu/cpufreq/Kconfig   2006-02-11 01:23:38.000000000 +0100

+++ arch/i386/kernel/cpu/cpufreq/Kconfig.new   2006-02-11 01:22:55.000000000 +0100

@@ -76,6 +76,17 @@

    depends on X86_POWERNOW_K7 && ACPI_PROCESSOR

    depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)

    default y

+   

+config X86_POWERNOW_K7_MANUAL

+   bool "Manual setting of PowerNow! table for AMD Mobile Athlon/Duron."

+   depends on X86_POWERNOW_K7

+   default n

+   help

+     This adds the possibility to manual change the PST table.

+

+     For details, take a look at <file:Documentation/cpu-freq/>.

+

+     If in doubt, say N.

 

 config X86_POWERNOW_K8

    tristate "AMD Opteron/Athlon64 PowerNow!"
```

powernow-k7-manual-2.6.16-gentoo-r3.patch

```
--- arch/i386/kernel/cpu/cpufreq/powernow-k7.c   2006-02-11 01:23:57.000000000 +0100

+++ arch/i386/kernel/cpu/cpufreq/powernow-k7.c.new   2006-02-11 01:23:29.000000000 +0100

@@ -67,7 +67,7 @@

 };

 #endif

 

-#ifdef CONFIG_CPU_FREQ_DEBUG

+#if defined CONFIG_CPU_FREQ_DEBUG || defined CONFIG_X86_POWERNOW_K7_MANUAL

 /* divide by 1000 to get VCore voltage in V. */

 static int mobile_vid_table[32] = {

     2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,

@@ -77,7 +77,7 @@

 };

 #endif

 

-/* divide by 10 to get FID. */

+/* divide by 10 to get multiplier. */

 static int fid_codes[32] = {

     110, 115, 120, 125, 50, 55, 60, 65,

     70, 75, 80, 85, 90, 95, 100, 105,

@@ -85,6 +85,31 @@

     150, 225, 160, 165, 170, 180, -1, -1,

 };

 

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+/* translation table for even multiplier to fid */

+static int even_multiplier[20] = {

+       16, 18, 4, 6, 8, 10, 12, 14,    // 3, 4, 5, 6, 7 ,8 , 9, 10

+       0, 2, 20, 22, 24, 26, 28, 29,   // 11, 12, 13, 14, 15, 16, 17, 18

+       17, 19, 23, 25,         // 19, 20, 21, 22

+};

+

+/* translation table for odd multiplier to fid*/

+static int odd_multiplier[9] = {

+       5, 7, 9, 11, 13, 15, 1, 3,      // 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5

+       21,                     // 13.5

+};

+

+/* This parameters can be used to manually overwrite the tables */

+static int overwrite_table = 0;

+#define MAX_PST 10

+static int multiplier_arr_size = MAX_PST;

+static int voltage_arr_size = MAX_PST;

+static int multiplier[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int voltage[MAX_PST] = {[0 ... (MAX_PST - 1)] = 0 };

+static int switch_latency = 0;

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 /* This parameter is used in order to force ACPI instead of legacy method for

  * configuration purpose.

  */

@@ -98,7 +123,7 @@

 static unsigned int minimum_speed=-1;

 static unsigned int maximum_speed;

 static unsigned int number_scales;

-static unsigned int fsb;

+static unsigned int fsb=0;

 static unsigned int latency;

 static char have_a0;

 

@@ -408,6 +433,144 @@

 }

 #endif

 

+

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+static int powernow_manual_settings(union msr_fidvidstatus *fidvidstatus)

+{

+       int i, k, validentry;

+       unsigned int max_multiplier, max_voltage;

+       unsigned int speed, cm;

+       u8 vid, fid;

+       static struct cpufreq_frequency_table *powernow_table_tmp;

+

+       if (switch_latency > 0) {

+               if (switch_latency < 100) {

+                       printk(KERN_INFO PFX

+                              "Settling time passed as %d microseconds."

+                              "Should be at least 100. Correcting.\n",

+                              switch_latency);

+                       switch_latency = 100;

+               }

+               latency = switch_latency;

+       } else {

+               latency = 200;

+       }

+       dprintk("Settling Time: %d microseconds.\n", latency);

+

+       /* get number of specified multipliers */

+       number_scales = multiplier_arr_size;

+       for (i = 0; i < multiplier_arr_size; i++) {

+               if (multiplier[i] == 0) {

+                       number_scales = i;

+                       break;

+               }

+       }

+

+       /* get maximum values */

+       max_multiplier = fid_codes[fidvidstatus->bits.MFID];

+       max_voltage = mobile_vid_table[fidvidstatus->bits.MVID];

+

+       /* allocate memory */

+       powernow_table =

+           kmalloc((sizeof(struct cpufreq_frequency_table) *

+                    (number_scales + 1)), GFP_KERNEL);

+       if (!powernow_table)

+               return -ENOMEM;

+       memset(powernow_table, 0,

+              (sizeof(struct cpufreq_frequency_table) * (number_scales + 1)));

+

+       k = 0;

+       for (i = 0; i < number_scales; i++) {

+               validentry = 0;

+               if (multiplier[i] != 0) {

+                       /* fix multiplier */

+                       if (multiplier[i] < 30)

+                               multiplier[i] = multiplier[i] * 10;

+                       if (multiplier[i] < max_multiplier) {

+                               cm = (multiplier[i] / 10);

+

+                               /* check if odd or even muliplier */

+                               if (multiplier[i] % 10) {

+                                       /* odd multiplier */

+                                       if (cm == 16) {

+                                               /* hardcoded because 14.5 and 15.5 fids not possible */

+                                               fid = 27;

+                                               validentry = 1;

+                                       } else if ((cm > 4) && (cm < 14)) {

+                                               fid = odd_multiplier[cm - 5];

+                                               validentry = 1;

+                                       }

+                               } else {

+                                       /* even_multiplier */

+                                       if ((cm < 23) && (cm > 2)) {

+                                               fid = even_multiplier[cm - 3];

+                                               validentry = 1;

+                                       }

+                               }

+                       }

+               }

+

+               if (validentry) {

+                       /* if no voltage specified use CPU default */

+                       if (voltage[i] == 0)

+                               voltage[i] = max_voltage;

+                       /* we do not allow higher voltages than the CPU's maximum 925 mV is the minimum */

+                       if ((voltage[i] <= max_voltage) && (voltage[i] >= 925)) {

+                               if (voltage[i] >= 1300) {

+                                       vid = 40 - (voltage[i] / 50);

+                               } else {

+                                       vid = 67 - (voltage[i] / 25);

+                               }

+                               /* calculate speed */

+                               speed = fsb * fid_codes[fid] / 10;

+                               powernow_table[k].frequency = speed;

+                               powernow_table[k].index = fid;  /*lower 8 bits */

+                               powernow_table[k].index |= (vid << 8);  /*upper 8 bits */

+

+                               if (speed < minimum_speed)

+                                       minimum_speed = speed;

+                               if (speed > maximum_speed)

+                                       maximum_speed = speed;

+

+                               dprintk("   FID: 0x%x (%d.%dx [%dMHz])\t", fid,

+                                       fid_codes[fid] / 10,

+                                       fid_codes[fid] % 10, speed / 1000);

+                               dprintk("VID: 0x%x (%d.%03dV)\n", vid,

+                                       mobile_vid_table[vid] / 1000,

+                                       mobile_vid_table[vid] % 1000);

+                               k++;

+                       }

+               } else {

+                       // invalid entry

+                       dprintk("Entry %d is invalid\n", i + 1);

+               }

+       }

+       if (k < number_scales) {

+               /* some entrys were invalid need to realloc table */

+               number_scales = k;

+               powernow_table_tmp =

+                   kmalloc((sizeof(struct cpufreq_frequency_table) *

+                            (number_scales + 1)), GFP_KERNEL);

+               if (!powernow_table_tmp) {

+                       kfree(powernow_table);

+                       return -ENOMEM;

+               }

+               memcpy(powernow_table_tmp, powernow_table,

+                      (sizeof(struct cpufreq_frequency_table) *

+                       (number_scales + 1)));

+               kfree(powernow_table);

+               powernow_table = powernow_table_tmp;

+       }

+

+       /* Terminate frequency list */

+       powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;

+       powernow_table[number_scales].index = 0;

+

+       return 0;

+}

+#endif /* CONFIG_X86_POWERNOW_K7_MANUAL */

+

+

 static int powernow_decode_bios (int maxfid, int startvid)

 {

    struct psb_s *psb;

@@ -540,6 +703,18 @@

    if (cpu)

       return 0;

    rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);

+    #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+        if (fsb) {

+                if (fsb < 1000)

+                        fsb *= 1000;

+

+                if (fsb < 1000 || fsb > 1000000) {

+                        printk(KERN_WARNING PFX "FSB %ukhz out of range\n",

+                               fsb);

+                        return -EINVAL;

+                }

+        }

+    #endif

    cfid = fidvidstatus.bits.CFID;

 

    return (fsb * fid_codes[cfid] / 10);

@@ -596,6 +771,12 @@

    if (dmi_check_system(powernow_dmi_table) || acpi_force) {

       printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");

       result = powernow_acpi_init();

+        #ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+          } else if (overwrite_table) {

+                 printk(KERN_INFO PFX

+                        "Overwriting PST table with manual settings\n");

+                 result = powernow_manual_settings(&fidvidstatus);

+        #endif

    } else {

       result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);

       if (result) {

@@ -677,6 +858,21 @@

 

 module_param(acpi_force,  int, 0444);

 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");

+#ifdef CONFIG_X86_POWERNOW_K7_MANUAL

+module_param(overwrite_table, int, 0444);

+MODULE_PARM_DESC(overwrite_table, "overwrite table with manually settings");

+module_param(fsb, uint, 0444);

+MODULE_PARM_DESC(fsb, "(MHz) overrides the calculated FSB");

+module_param_array(multiplier, int, &multiplier_arr_size, 0444);

+MODULE_PARM_DESC(multiplier,

+                "Specifiy up to 10 multipliers, multiply them by 10: 5->50, 5.5->55");

+module_param_array(voltage, int, &voltage_arr_size, 0444);

+MODULE_PARM_DESC(voltage,

+                "Specify voltages in respect to the given multipliers, specify them in mV: 1.275V -> 1275");

+module_param(switch_latency, int, 0444);

+MODULE_PARM_DESC(switch_latency,

+                "Set state transition latency in microseconds (default 200us)");

+#endif

 

 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");

 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");

```

----------

## ebat

I make:

```
# patch -p0 --dry-run < powernow-k7-Kconfig-2.6.16-gentoo-r7.patch
```

on clean, remerged sources and I have:

```
patching file arch/i386/kernel/cpu/cpufreq/Kconfig

Hunk #1 FAILED at 76.

1 out of 1 hunk FAILED -- saving rejects to file arch/i386/kernel/cpu/cpufreq/Kconfig.rej

```

 :Confused: 

----------

## VPN-User

Copy both patchfiles to /usr/src/linux and do "patch -p1 < patchfile"

----------

## VPN-User

Maybe something got wrong by pasting the files contents. Give me your email address and I will send you my (really working!!!) files.

----------

## ebat

 *VPN-User wrote:*   

> Copy both patchfiles to /usr/src/linux and do "patch -p1 < patchfile"

 

Yeah Yeah Yeah, no effect   :Sad: 

I copy from Opera / Firefox and still is a problem!

-> PW   :Wink: 

----------

