[2.5. PATCH] cpufreq: cleanups

From: Dominik Brodowski (linux@brodo.de)
Date: Fri Nov 22 2002 - 13:14:01 EST


Hi,

This patch changes the return type of the verify and setpolicy
functions from void to int. While doing this, I've changed the values for
minimum and maximum supported frequency to be per CPU, as UltraSPARC
needs this. Additionally, small cleanups in various drivers.

Please apply,

       Dominik

diff -ruN linux-original/Documentation/cpufreq linux/Documentation/cpufreq
--- linux-original/Documentation/cpufreq 2002-11-17 19:04:11.000000000 +0100
+++ linux/Documentation/cpufreq 2002-11-18 16:34:44.000000000 +0100
@@ -87,7 +87,8 @@
 Transmeta Crusoe Longrun:
     Transmeta Crusoe processors:
 --------------------------------
- Does not work with the 2.4. /proc/sys/cpu/ interface.
+ It is recommended to use the 2.6. /proc/cpufreq interface when
+ using this driver
 
 
 
@@ -283,15 +284,17 @@
 
 cpufreq_verify_t verify: This is a pointer to a function with the
         following definition:
- void verify_function (struct cpufreq_policy *policy).
+ int verify_function (struct cpufreq_policy *policy).
         This function must verify the new policy is within the limits
         supported by the CPU, and at least one supported CPU is within
         this range. It may be useful to use cpufreq.h /
- cpufreq_verify_within_limits for this.
+ cpufreq_verify_within_limits for this. If this is called with
+ CPUFREQ_ALL_CPUS, and there is no common subset of frequencies
+ for all CPUs, exit with an error.
 
 cpufreq_setpolicy_t setpolicy: This is a pointer to a function with
         the following definition:
- void setpolicy_function (struct cpufreq_policy *policy).
+ int setpolicy_function (struct cpufreq_policy *policy).
         This function must set the CPU to the new policy. If it is a
         "dumb" CPU which only allows fixed frequencies to be set, it
         shall set it to the lowest within the limit for
@@ -302,30 +305,30 @@
 
 struct cpufreq_policy *policy: This is an array of NR_CPUS struct
         cpufreq_policies, containing the current policies set for these
- CPUs. Note that policy[0].max_cpu_freq must contain the
- absolute maximum CPU frequency supported by _all_ CPUs.
+ CPUs. Note that policy[cpu].max_cpu_freq must contain the
+ absolute maximum CPU frequency supported by the specified cpu.
 
 In case the driver is expected to run with the 2.4.-style API
 (/proc/sys/cpu/.../), two more values must be passed
 #ifdef CONFIG_CPU_FREQ_24_API
- unsigned int cpu_min_freq;
+ unsigned int cpu_min_freq[NR_CPUS];
         unsigned int cpu_cur_freq[NR_CPUS];
 #endif
- with cpu_min_freq being the minimum CPU frequency supported by
- the CPUs; and the entries in cpu_cur_freq reflecting the
- current speed of the appropriate CPU.
+ with cpu_min_freq[cpu] being the minimum CPU frequency
+ supported by the CPU; and the entries in cpu_cur_freq
+ reflecting the current speed of the appropriate CPU.
 
 Some Requirements to CPUFreq architecture drivers
 -------------------------------------------------
 * Only call cpufreq_register() when the ability to switch CPU
- frequencies is _verified_ or can't be missing
+ frequencies is _verified_ or can't be missing. Also, all
+ other initialization must be done beofre this call, as
+ cpfureq_register calls the driver's verify and setpolicy code for
+ each CPU.
 * cpufreq_unregister() may only be called if cpufreq_register() has
   been successfully(!) called before.
 * kfree() the struct cpufreq_driver only after the call to
   cpufreq_unregister(), unless cpufreq_register() failed.
-* Be aware that there is currently no error management in the
- setpolicy() code in the CPUFreq core. So only call yourself a
- cpufreq_driver if you are really a working cpufreq_driver!
 
 
 
diff -ruN linux-original/arch/arm/mach-integrator/cpu.c linux/arch/arm/mach-integrator/cpu.c
--- linux-original/arch/arm/mach-integrator/cpu.c 2002-11-17 19:04:12.000000000 +0100
+++ linux/arch/arm/mach-integrator/cpu.c 2002-11-18 16:34:44.000000000 +0100
@@ -73,7 +73,7 @@
  * Validate the speed in khz. If it is outside our
  * range, then return the lowest.
  */
-static void integrator_verify_speed(struct cpufreq_policy *policy)
+static int integrator_verify_speed(struct cpufreq_policy *policy)
 {
         struct vco vco;
 
@@ -93,6 +93,8 @@
                 vco.vdw = 152;
 
         policy->min = policy->max = vco_to_freq(vco, 1);
+
+ return 0;
 }
 
 static void do_set_policy(int cpu, struct cpufreq_policy *policy)
@@ -116,7 +118,7 @@
         __raw_writel(0, CM_LOCK);
 }
 
-static void integrator_set_policy(struct cpufreq_policy *policy)
+static int integrator_set_policy(struct cpufreq_policy *policy)
 {
         unsigned long cpus_allowed;
         int cpu;
@@ -139,6 +141,8 @@
          * Restore the CPUs allowed mask.
          */
         set_cpus_allowed(current, cpus_allowed);
+
+ return 0;
 }
 
 static struct cpufreq_policy integrator_policy = {
@@ -151,7 +155,6 @@
         .verify = integrator_verify_speed,
         .setpolicy = integrator_set_policy,
         .policy = &integrator_policy,
- .cpu_min_freq = 12000,
 };
 #endif
 
@@ -202,6 +205,8 @@
         set_cpus_allowed(current, cpus_allowed);
 
 #ifdef CONFIG_CPU_FREQ
+ for (cpu=0; cpu<NR_CPUS; cpu++)
+ integrator_driver.cpu_min_freq[cpu] = 12000;
         integrator_driver.policy = policies;
         cpufreq_register(&integrator_driver);
 #else
diff -ruN linux-original/arch/arm/mach-sa1100/cpu-sa1100.c linux/arch/arm/mach-sa1100/cpu-sa1100.c
--- linux-original/arch/arm/mach-sa1100/cpu-sa1100.c 2002-11-17 19:04:12.000000000 +0100
+++ linux/arch/arm/mach-sa1100/cpu-sa1100.c 2002-11-18 16:34:44.000000000 +0100
@@ -176,7 +176,7 @@
         }
 }
 
-static void sa1100_setspeed(struct cpufreq_policy *policy)
+static int sa1100_setspeed(struct cpufreq_policy *policy)
 {
         unsigned int cur = sa11x0_getspeed();
         struct cpufreq_freqs freqs;
@@ -196,6 +196,8 @@
                 sa1100_update_dram_timings(cur, policy->max);
 
         cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
 }
 
 static struct cpufreq_policy sa1100_policy = {
@@ -208,7 +210,7 @@
         .verify = sa11x0_verify_speed,
         .setpolicy = sa1100_setspeed,
         .policy = &sa1100_policy,
- .cpu_min_freq = 59000,
+ .cpu_min_freq[0]= 59000,
 };
 
 static int __init sa1100_dram_init(void)
@@ -216,7 +218,7 @@
         int ret = -ENODEV;
 
         if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
- sa1100_driver.cpu_curr_freq[0] =
+ sa1100_driver.cpu_cur_freq[0] =
                 sa1100_policy.min =
                 sa1100_policy.max = sa11x0_getspeed();
 
diff -ruN linux-original/arch/arm/mach-sa1100/cpu-sa1110.c linux/arch/arm/mach-sa1100/cpu-sa1110.c
--- linux-original/arch/arm/mach-sa1100/cpu-sa1110.c 2002-11-17 19:04:12.000000000 +0100
+++ linux/arch/arm/mach-sa1100/cpu-sa1110.c 2002-11-18 16:34:44.000000000 +0100
@@ -212,7 +212,7 @@
  * above, we can match for an exact frequency. If we don't find
  * an exact match, we will to set the lowest frequency to be safe.
  */
-static void sa1110_setspeed(struct cpufreq_policy *policy)
+static int sa1110_setspeed(struct cpufreq_policy *policy)
 {
         struct sdram_params *sdram = &sdram_params;
         struct cpufreq_freqs freqs;
@@ -291,6 +291,8 @@
         sdram_update_refresh(policy->max, sdram);
 
         cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
 }
 
 static struct cpufreq_policy sa1110_policy = {
@@ -300,10 +302,10 @@
 };
 
 static struct cpufreq_driver sa1110_driver = {
- .verify = sa11x0_verify_speed,
- .setpolicy = sa1110_setspeed,
- .policy = &sa1110_policy,
- .cpu_min_freq = 59000,
+ .verify = sa11x0_verify_speed,
+ .setpolicy = sa1110_setspeed,
+ .policy = &sa1110_policy,
+ .cpu_min_freq[0] = 59000,
 };
 
 static int __init sa1110_clk_init(void)
diff -ruN linux-original/arch/arm/mach-sa1100/generic.c linux/arch/arm/mach-sa1100/generic.c
--- linux-original/arch/arm/mach-sa1100/generic.c 2002-11-17 19:04:12.000000000 +0100
+++ linux/arch/arm/mach-sa1100/generic.c 2002-11-18 16:34:35.000000000 +0100
@@ -67,7 +67,7 @@
  * scaling, so we force min=max, and set the policy to "performance".
  * If we can't generate the precise frequency requested, round it up.
  */
-void sa11x0_verify_speed(struct cpufreq_policy *policy)
+int sa11x0_verify_speed(struct cpufreq_policy *policy)
 {
         if (policy->max > policy->max_cpu_freq)
                 policy->max = policy->max_cpu_freq;
@@ -75,6 +75,7 @@
         policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
         policy->min = policy->max;
         policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ return 0;
 }
 
 unsigned int sa11x0_getspeed(void)
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/elanfreq.c linux/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/elanfreq.c 2002-11-17 19:04:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/elanfreq.c 2002-11-18 16:34:44.000000000 +0100
@@ -172,13 +172,13 @@
  * for the hardware supported by the driver.
  */
 
-static void elanfreq_verify (struct cpufreq_policy *policy)
+static int elanfreq_verify (struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i;
 
         if (!policy || !max_freq)
- return;
+ return -EINVAL;
 
         policy->cpu = 0;
 
@@ -190,7 +190,7 @@
                         number_states++;
 
         if (number_states)
- return;
+ return 0;
 
         for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--)
                 if (elan_multiplier[i].clock < policy->max)
@@ -198,16 +198,16 @@
 
         policy->max = elan_multiplier[i+1].clock;
 
- return;
+ return 0;
 }
 
-static void elanfreq_setpolicy (struct cpufreq_policy *policy)
+static int elanfreq_setpolicy (struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i, j=4;
 
         if (!elanfreq_driver)
- return;
+ return -EINVAL;
 
         for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--)
                 if ((elan_multiplier[i].clock >= policy->min) &&
@@ -219,7 +219,7 @@
 
         if (number_states == 1) {
                 elanfreq_set_cpu_state(j);
- return;
+ return 0;
         }
 
         switch (policy->policy) {
@@ -236,14 +236,14 @@
                                 j = i;
                 break;
         default:
- return;
+ return -EINVAL;
         }
 
         if (elan_multiplier[j].clock > max_freq)
- BUG();
+ return -EINVAL;
 
         elanfreq_set_cpu_state(j);
- return;
+ return 0;
 }
 
 
@@ -296,7 +296,7 @@
                 max_freq = elanfreq_get_cpu_frequency();
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = 1000;
+ driver->cpu_min_freq[0] = 1000;
         driver->cpu_cur_freq[0] = elanfreq_get_cpu_frequency();
 #endif
 
@@ -309,15 +309,15 @@
         driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
         driver->policy[0].max_cpu_freq = max_freq;
 
+ elanfreq_driver = driver;
+
         ret = cpufreq_register(driver);
         if (ret) {
+ elanfreq_driver = NULL;
                 kfree(driver);
- return ret;
         }
 
- elanfreq_driver = driver;
-
- return 0;
+ return ret;
 }
 
 
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/longhaul.c linux/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/longhaul.c 2002-11-17 19:04:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/longhaul.c 2002-11-18 16:46:41.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: longhaul.c,v 1.72 2002/09/29 23:43:10 db Exp $
+ * $Id: longhaul.c,v 1.77 2002/10/31 21:17:40 db Exp $
  *
  * (C) 2001 Dave Jones. <davej@suse.de>
  * (C) 2002 Padraig Brady. <padraig@antefacto.com>
@@ -436,8 +436,10 @@
         switch (longhaul) {
         case 1:
                 /* Ugh, Longhaul v1 didn't have the min/max MSRs.
- Assume max = whatever we booted at. */
+ Assume min=3.0x & max = whatever we booted at. */
+ minmult = 30;
                 maxmult = longhaul_get_cpu_mult();
+ minfsb = maxfsb = current_fsb;
                 break;
 
         case 2 ... 3:
@@ -531,7 +533,7 @@
 }
 
 
-static void longhaul_verify(struct cpufreq_policy *policy)
+static int longhaul_verify(struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i;
@@ -540,7 +542,7 @@
         unsigned int newmax = -1;
 
         if (!policy || !longhaul_driver)
- return;
+ return -EINVAL;
 
         policy->cpu = 0;
         cpufreq_verify_within_limits(policy, lowest_speed, highest_speed);
@@ -552,7 +554,7 @@
                 number_states = longhaul_statecount_fsb(policy, current_fsb);
 
         if (number_states)
- return;
+ return 0;
 
         /* get frequency closest above current policy->max */
         if (can_scale_fsb==1) {
@@ -579,10 +581,12 @@
         }
 
         policy->max = newmax;
+
+ return 0;
 }
 
 
-static void longhaul_setpolicy (struct cpufreq_policy *policy)
+static int longhaul_setpolicy (struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i;
@@ -592,7 +596,7 @@
         unsigned int best_freq = -1;
 
         if (!longhaul_driver)
- return;
+ return -EINVAL;
 
         if (policy->policy==CPUFREQ_POLICY_PERFORMANCE)
                 fsb_search_table = perf_fsb_table;
@@ -613,7 +617,7 @@
         }
 
         if (!number_states)
- return;
+ return -EINVAL;
         else if (number_states == 1) {
                 for(i=0; i<numscales; i++) {
                         if ((clock_ratio[i] != -1) &&
@@ -692,11 +696,11 @@
                 }
                 break;
         default:
- return;
+ return -EINVAL;
         }
 
         longhaul_setstate(new_clock_ratio, new_fsb);
- return;
+ return 0;
 }
 
 
@@ -775,7 +779,7 @@
         driver->policy = (struct cpufreq_policy *) (driver + 1);
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = (unsigned int) lowest_speed;
+ driver->cpu_min_freq[0] = (unsigned int) lowest_speed;
         driver->cpu_cur_freq[0] = currentspeed;
 #endif
 
@@ -788,15 +792,15 @@
         driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
         driver->policy[0].max_cpu_freq = (unsigned int) highest_speed;
 
- ret = cpufreq_register(driver);
+ longhaul_driver = driver;
 
+ ret = cpufreq_register(driver);
         if (ret) {
+ longhaul_driver = NULL;
                 kfree(driver);
- return ret;
         }
 
- longhaul_driver = driver;
- return 0;
+ return ret;
 }
 
 
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/longrun.c linux/arch/i386/kernel/cpu/cpufreq/longrun.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/longrun.c 2002-11-17 19:09:07.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/longrun.c 2002-11-18 16:34:44.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: longrun.c,v 1.12 2002/09/29 23:43:10 db Exp $
+ * $Id: longrun.c,v 1.14 2002/10/31 21:17:40 db Exp $
  *
  * (C) 2002 Dominik Brodowski <linux@brodo.de>
  *
@@ -67,13 +67,13 @@
  * Sets a new CPUFreq policy on LongRun-capable processors. This function
  * has to be called with cpufreq_driver locked.
  */
-static void longrun_set_policy(struct cpufreq_policy *policy)
+static int longrun_set_policy(struct cpufreq_policy *policy)
 {
         u32 msr_lo, msr_hi;
         u32 pctg_lo, pctg_hi;
 
         if (!longrun_driver || !policy)
- return;
+ return -EINVAL;
 
         pctg_lo = (policy->min - longrun_low_freq) /
                 ((longrun_high_freq - longrun_low_freq) / 100);
@@ -105,7 +105,7 @@
         msr_hi |= pctg_hi;
         wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
 
- return;
+ return 0;
 }
 
 
@@ -115,16 +115,16 @@
  * Validates a new CPUFreq policy. This function has to be called with
  * cpufreq_driver locked.
  */
-static void longrun_verify_policy(struct cpufreq_policy *policy)
+static int longrun_verify_policy(struct cpufreq_policy *policy)
 {
         if (!policy || !longrun_driver)
- return;
+ return -EINVAL;
 
         policy->cpu = 0;
         cpufreq_verify_within_limits(policy, 0,
                 longrun_driver->policy[0].max_cpu_freq);
 
- return;
+ return 0;
 }
 
 
@@ -252,20 +252,22 @@
         longrun_get_policy(&driver->policy[0]);
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = longrun_low_freq;
+ driver->cpu_min_freq[0] = longrun_low_freq;
         driver->cpu_cur_freq[0] = longrun_high_freq; /* dummy value */
 #endif
 
         driver->verify = &longrun_verify_policy;
         driver->setpolicy = &longrun_set_policy;
+
+ longrun_driver = driver;
+
         result = cpufreq_register(driver);
         if (result) {
+ longrun_driver = NULL;
                 kfree(driver);
- return result;
         }
- longrun_driver = driver;
 
- return 0;
+ return result;
 }
 
 
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2002-11-17 20:42:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2002-11-18 16:54:30.000000000 +0100
@@ -78,7 +78,7 @@
         }
 #endif
         set_cpus_allowed(current, affected_cpu_map);
- BUG_ON(!(smp_processor_id() & affected_cpu_map));
+ BUG_ON(!(affected_cpu_map & (1 << smp_processor_id())));
 
         /* get current state */
         rdmsr(MSR_IA32_THERM_CONTROL, l, h);
@@ -136,14 +136,14 @@
 }
 
 
-static void cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
+static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
 {
         unsigned int i;
         unsigned int newstate = 0;
         unsigned int number_states = 0;
 
         if (!cpufreq_p4_driver || !stock_freq || !policy)
- return;
+ return -EINVAL;
 
         if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
         {
@@ -183,16 +183,17 @@
                         min_state = newstate - (number_states - 1);
                 }
         } */
+ return 0;
 }
 
 
-static void cpufreq_p4_verify(struct cpufreq_policy *policy)
+static int cpufreq_p4_verify(struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i;
 
         if (!cpufreq_p4_driver || !stock_freq || !policy)
- return;
+ return -EINVAL;
 
         if (!cpu_online(policy->cpu))
                 policy->cpu = CPUFREQ_ALL_CPUS;
@@ -205,10 +206,10 @@
                         number_states++;
 
         if (number_states)
- return;
+ return 0;
 
         policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1);
- return;
+ return 0;
 }
 
 
@@ -255,9 +256,10 @@
                 stock_freq = cpu_khz;
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = stock_freq / 8;
- for (i=0;i<NR_CPUS;i++)
+ for (i=0;i<NR_CPUS;i++) {
+ driver->cpu_min_freq[i] = stock_freq / 8;
                 driver->cpu_cur_freq[i] = stock_freq;
+ }
 #endif
 
         driver->verify = &cpufreq_p4_verify;
@@ -274,15 +276,15 @@
                 driver->policy[i].cpu = i;
         }
 
+ cpufreq_p4_driver = driver;
+
         ret = cpufreq_register(driver);
         if (ret) {
+ cpufreq_p4_driver = NULL;
                 kfree(driver);
- return ret;
         }
 
- cpufreq_p4_driver = driver;
-
- return 0;
+ return ret;
 }
 
 
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/powernow-k6.c linux/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/powernow-k6.c 2002-11-17 19:04:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k6.c 2002-11-18 16:34:44.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: powernow-k6.c,v 1.33 2002/09/29 23:43:11 db Exp $
+ * $Id: powernow-k6.c,v 1.36 2002/10/31 21:17:40 db Exp $
  * This file was part of Powertweak Linux (http://powertweak.sf.net)
  * and is shared with the Linux Kernel module.
  *
@@ -113,13 +113,13 @@
  * Policy must be within lowest and highest possible CPU Frequency,
  * and at least one possible state must be within min and max.
  */
-static void powernow_k6_verify(struct cpufreq_policy *policy)
+static int powernow_k6_verify(struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i, j;
 
         if (!policy || !busfreq)
- return;
+ return -EINVAL;
 
         policy->cpu = 0;
         cpufreq_verify_within_limits(policy, (20 * busfreq),
@@ -131,7 +131,7 @@
                         number_states++;
 
         if (number_states)
- return;
+ return 0;
 
         /* no state is available within range -- find next larger state */
 
@@ -144,7 +144,7 @@
 
         policy->max = clock_ratio[j] * busfreq;
 
- return;
+ return 0;
 }
 
 
@@ -154,13 +154,13 @@
  *
  * sets a new CPUFreq policy
  */
-static void powernow_k6_setpolicy (struct cpufreq_policy *policy)
+static int powernow_k6_setpolicy (struct cpufreq_policy *policy)
 {
         unsigned int number_states = 0;
         unsigned int i, j=4;
 
         if (!powernow_driver)
- return;
+ return -EINVAL;
 
         for (i=0; i<8; i++)
                 if ((policy->min <= (busfreq * clock_ratio[i])) &&
@@ -174,7 +174,7 @@
                 /* if only one state is within the limit borders, it
                    is easily detected and set */
                 powernow_k6_set_state(j);
- return;
+ return 0;
         }
 
         /* more than one state within limit */
@@ -196,14 +196,14 @@
                                 j = i;
                 break;
         default:
- return;
+ return -EINVAL;
         }
 
         if (clock_ratio[i] > max_multiplier)
- BUG();
+ return -EINVAL;
 
         powernow_k6_set_state(j);
- return;
+ return 0;
 }
 
 
@@ -242,7 +242,7 @@
         driver->policy = (struct cpufreq_policy *) (driver + 1);
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = busfreq * 20;
+ driver->cpu_min_freq[0] = busfreq * 20;
         driver->cpu_cur_freq[0] = busfreq * max_multiplier;
 #endif
 
@@ -255,16 +255,16 @@
         driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
         driver->policy[0].max_cpu_freq = busfreq * max_multiplier;
 
+ powernow_driver = driver;
 
         result = cpufreq_register(driver);
         if (result) {
                 release_region (POWERNOW_IOPORT, 16);
+ powernow_driver = NULL;
                 kfree(driver);
- return result;
         }
- powernow_driver = driver;
 
- return 0;
+ return result;
 }
 
 
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/speedstep.c linux/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/speedstep.c 2002-11-17 19:09:17.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/speedstep.c 2002-11-18 16:36:36.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * $Id: speedstep.c,v 1.57 2002/11/05 12:01:12 db Exp $
+ * $Id: speedstep.c,v 1.58 2002/11/11 15:35:46 db Exp $
  *
  * (C) 2001 Dave Jones, Arjan van de ven.
  * (C) 2002 Dominik Brodowski <linux@brodo.de>
@@ -567,10 +567,10 @@
  *
  * Sets a new CPUFreq policy.
  */
-static void speedstep_setpolicy (struct cpufreq_policy *policy)
+static int speedstep_setpolicy (struct cpufreq_policy *policy)
 {
         if (!speedstep_driver || !policy)
- return;
+ return -EINVAL;
 
         if (policy->min > speedstep_low_freq)
                 speedstep_set_state(SPEEDSTEP_HIGH, 1);
@@ -585,6 +585,7 @@
                                 speedstep_set_state(SPEEDSTEP_HIGH, 1);
                 }
         }
+ return 0;
 }
 
 
@@ -595,11 +596,11 @@
  * Limit must be within speedstep_low_freq and speedstep_high_freq, with
  * at least one border included.
  */
-static void speedstep_verify (struct cpufreq_policy *policy)
+static int speedstep_verify (struct cpufreq_policy *policy)
 {
         if (!policy || !speedstep_driver ||
             !speedstep_low_freq || !speedstep_high_freq)
- return;
+ return -EINVAL;
 
         policy->cpu = 0; /* UP only */
 
@@ -609,7 +610,7 @@
             (policy->max < speedstep_high_freq))
                 policy->max = speedstep_high_freq;
         
- return;
+ return 0;
 }
 
 
@@ -654,12 +655,11 @@
                 speedstep_processor = speedstep_detect_processor();
 
         if ((!speedstep_chipset) || (!speedstep_processor)) {
- printk(KERN_INFO "a 0x%x b 0x%x\n", speedstep_processor, speedstep_chipset);
                 printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset");
                 return -ENODEV;
         }
 
- dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.57 $\n");
+ dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.58 $\n");
         dprintk(KERN_DEBUG "cpufreq: chipset 0x%x - processor 0x%x\n",
                speedstep_chipset, speedstep_processor);
 
@@ -693,7 +693,7 @@
         driver->policy = (struct cpufreq_policy *) (driver + 1);
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = speedstep_low_freq;
+ driver->cpu_min_freq[0] = speedstep_low_freq;
         driver->cpu_cur_freq[0] = speed;
 #endif
 
@@ -707,14 +707,15 @@
         driver->policy[0].policy = (speed == speedstep_low_freq) ?
             CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
 
+ speedstep_driver = driver;
+
         result = cpufreq_register(driver);
         if (result) {
+ speedstep_driver = NULL;
                 kfree(driver);
- return result;
         }
- speedstep_driver = driver;
 
- return 0;
+ return result;
 }
 
 
diff -ruN linux-original/drivers/acpi/processor.c linux/drivers/acpi/processor.c
--- linux-original/drivers/acpi/processor.c 2002-11-18 16:30:03.000000000 +0100
+++ linux/drivers/acpi/processor.c 2002-11-18 16:34:44.000000000 +0100
@@ -1613,7 +1613,7 @@
                                cpufreq interface
    -------------------------------------------------------------------------- */
 #ifdef CONFIG_ACPI_PROCESSOR_PERF
-static void
+static int
 acpi_cpufreq_setpolicy (
         struct cpufreq_policy *policy)
 {
@@ -1626,7 +1626,7 @@
         ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy");
 
         if (!policy)
- return_VOID;
+ return_VALUE(-EINVAL);
 
         /* get a present, initialized CPU */
         if (policy->cpu == CPUFREQ_ALL_CPUS)
@@ -1644,7 +1644,7 @@
                 cpu = policy->cpu;
                 pr = processors[cpu];
                 if (!pr)
- return_VOID;
+ return_VALUE(-EINVAL);
         }
 
         /* select appropriate P-State */
@@ -1686,11 +1686,11 @@
                 result = acpi_processor_set_performance (pr, next_state);
         }
 
- return_VOID;
+ return_VALUE(0);
 }
 
 
-static void
+static int
 acpi_cpufreq_verify (
         struct cpufreq_policy *policy)
 {
@@ -1703,7 +1703,7 @@
         ACPI_FUNCTION_TRACE("acpi_cpufreq_verify");
 
         if (!policy)
- return_VOID;
+ return_VALUE(-EINVAL);
 
         /* get a present, initialized CPU */
         if (policy->cpu == CPUFREQ_ALL_CPUS)
@@ -1721,7 +1721,7 @@
                 cpu = policy->cpu;
                 pr = processors[cpu];
                 if (!pr)
- return_VOID;
+ return_VALUE(-EINVAL);
         }
 
         /* first check if min and max are within valid limits */
@@ -1741,13 +1741,12 @@
                         next_larger_state = i;
         }
 
- if (number_states)
- return_VOID;
-
- /* round up now */
- policy->max = pr->performance.states[next_larger_state].core_frequency * 1000;
+ if (!number_states) {
+ /* round up now */
+ policy->max = pr->performance.states[next_larger_state].core_frequency * 1000;
+ }
 
- return_VOID;
+ return_VALUE(0);
 }
 
 static int
@@ -1807,9 +1806,10 @@
         driver->policy = (struct cpufreq_policy *) (driver + 1);
 
 #ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_min_freq = pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000;
- for (i=0;i<NR_CPUS;i++)
+ for (i=0;i<NR_CPUS;i++) {
                 driver->cpu_cur_freq[0] = pr->performance.states[current_state].core_frequency * 1000;
+ driver->cpu_min_freq[0] = pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000;
+ }
 #endif
 
         driver->verify = &acpi_cpufreq_verify;
diff -ruN linux-original/include/linux/cpufreq.h linux/include/linux/cpufreq.h
--- linux-original/include/linux/cpufreq.h 2002-11-17 19:09:26.000000000 +0100
+++ linux/include/linux/cpufreq.h 2002-11-18 16:35:13.000000000 +0100
@@ -5,7 +5,7 @@
  * (C) 2002 Dominik Brodowski <linux@brodo.de>
  *
  *
- * $Id: cpufreq.h,v 1.27 2002/10/08 14:54:23 db Exp $
+ * $Id: cpufreq.h,v 1.29 2002/11/11 15:35:47 db Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -104,7 +104,7 @@
  * CPUFREQ DRIVER INTERFACE *
  *********************************************************************/
 
-typedef void (*cpufreq_policy_t) (struct cpufreq_policy *policy);
+typedef int (*cpufreq_policy_t) (struct cpufreq_policy *policy);
 
 struct cpufreq_driver {
         /* needed by all drivers */
@@ -116,7 +116,7 @@
 #endif
         /* 2.4. compatible API */
 #ifdef CONFIG_CPU_FREQ_24_API
- unsigned int cpu_min_freq;
+ unsigned int cpu_min_freq[NR_CPUS];
         unsigned int cpu_cur_freq[NR_CPUS];
 #endif
 };
@@ -205,19 +205,19 @@
         CPU_NR_FREQ = 3,
 };
 
-#define CTL_CPU_VARS_SPEED_MAX { \
+#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
                 .ctl_name = CPU_NR_FREQ_MAX, \
- .data = &cpu_max_freq, \
+ .data = &cpu_max_freq[cpunr], \
                 .procname = "speed-max", \
- .maxlen = sizeof(cpu_max_freq),\
+ .maxlen = sizeof(cpu_max_freq[cpunr]),\
                 .mode = 0444, \
                 .proc_handler = proc_dointvec, }
 
-#define CTL_CPU_VARS_SPEED_MIN { \
+#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
                 .ctl_name = CPU_NR_FREQ_MIN, \
- .data = &cpu_min_freq, \
+ .data = &cpu_min_freq[cpunr], \
                 .procname = "speed-min", \
- .maxlen = sizeof(cpu_min_freq),\
+ .maxlen = sizeof(cpu_min_freq[cpunr]),\
                 .mode = 0444, \
                 .proc_handler = proc_dointvec, }
 
@@ -230,8 +230,8 @@
                 .extra1 = (void*) (cpunr), }
 
 #define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
- CTL_CPU_VARS_SPEED_MAX, \
- CTL_CPU_VARS_SPEED_MIN, \
+ CTL_CPU_VARS_SPEED_MAX(cpunr), \
+ CTL_CPU_VARS_SPEED_MIN(cpunr), \
                 CTL_CPU_VARS_SPEED(cpunr), \
                 { .ctl_name = 0, }, }
 
diff -ruN linux-original/kernel/cpufreq.c linux/kernel/cpufreq.c
--- linux-original/kernel/cpufreq.c 2002-11-17 19:09:26.000000000 +0100
+++ linux/kernel/cpufreq.c 2002-11-18 16:35:44.000000000 +0100
@@ -4,7 +4,7 @@
  * Copyright (C) 2001 Russell King
  * (C) 2002 Dominik Brodowski <linux@brodo.de>
  *
- * $Id: cpufreq.c,v 1.45 2002/10/08 14:54:23 db Exp $
+ * $Id: cpufreq.c,v 1.50 2002/11/11 15:35:48 db Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -69,8 +69,8 @@
 /**
  * A few values needed by the 2.4.-compatible API
  */
-static unsigned int cpu_max_freq;
-static unsigned int cpu_min_freq;
+static unsigned int cpu_max_freq[NR_CPUS];
+static unsigned int cpu_min_freq[NR_CPUS];
 static unsigned int cpu_cur_freq[NR_CPUS];
 #endif
 
@@ -228,6 +228,10 @@
                         continue;
 
                 cpufreq_get_policy(&policy, i);
+
+ if (!policy.max_cpu_freq)
+ continue;
+
                 min_pctg = (policy.min * 100) / policy.max_cpu_freq;
                 max_pctg = (policy.max * 100) / policy.max_cpu_freq;
 
@@ -378,7 +382,7 @@
 {
         if (!cpu_online(cpu) && (cpu != CPUFREQ_ALL_CPUS))
                 return -EINVAL;
- return cpufreq_set(cpu_max_freq, cpu);
+ return cpufreq_set(cpu_max_freq[cpu], cpu);
 }
 EXPORT_SYMBOL_GPL(cpufreq_setmax);
 
@@ -807,13 +811,14 @@
         policy->min = cpufreq_driver->policy[cpu].min;
         policy->max = cpufreq_driver->policy[cpu].max;
         policy->policy = cpufreq_driver->policy[cpu].policy;
- policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq;
+ policy->max_cpu_freq = cpufreq_driver->policy[cpu].max_cpu_freq;
         policy->cpu = cpu;
 
         up(&cpufreq_driver_sem);
 
         return 0;
 }
+EXPORT_SYMBOL(cpufreq_get_policy);
 
 
 /**
@@ -825,6 +830,7 @@
 int cpufreq_set_policy(struct cpufreq_policy *policy)
 {
         unsigned int i;
+ int ret;
 
         down(&cpufreq_driver_sem);
         if (!cpufreq_driver || !cpufreq_driver->verify ||
@@ -834,12 +840,20 @@
                 return -EINVAL;
         }
 
- down(&cpufreq_notifier_sem);
+ if (policy->cpu == CPUFREQ_ALL_CPUS)
+ policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq;
+ else
+ policy->max_cpu_freq = cpufreq_driver->policy[policy->cpu].max_cpu_freq;
 
- policy->max_cpu_freq = cpufreq_driver->policy[0].max_cpu_freq;
 
         /* verify the cpu speed can be set within this limit */
- cpufreq_driver->verify(policy);
+ ret = cpufreq_driver->verify(policy);
+ if (ret) {
+ up(&cpufreq_driver_sem);
+ return ret;
+ }
+
+ down(&cpufreq_notifier_sem);
 
         /* adjust if neccessary - all reasons */
         notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
@@ -851,7 +865,12 @@
 
         /* verify the cpu speed can be set within this limit,
            which might be different to the first one */
- cpufreq_driver->verify(policy);
+ ret = cpufreq_driver->verify(policy);
+ if (ret) {
+ up(&cpufreq_notifier_sem);
+ up(&cpufreq_driver_sem);
+ return ret;
+ }
 
         /* notification of the new policy */
         notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
@@ -879,11 +898,11 @@
                 cpu_cur_freq[policy->cpu] = policy->max;
 #endif
 
- cpufreq_driver->setpolicy(policy);
+ ret = cpufreq_driver->setpolicy(policy);
         
         up(&cpufreq_driver_sem);
 
- return 0;
+ return ret;
 }
 EXPORT_SYMBOL(cpufreq_set_policy);
 
@@ -968,6 +987,8 @@
 int cpufreq_register(struct cpufreq_driver *driver_data)
 {
         unsigned int ret;
+ unsigned int i;
+ struct cpufreq_policy policy;
 
         if (cpufreq_driver)
                 return -EBUSY;
@@ -979,41 +1000,55 @@
         down(&cpufreq_driver_sem);
         cpufreq_driver = driver_data;
         
- if (!default_policy.policy)
- default_policy.policy = driver_data->policy[0].policy;
- if (!default_policy.min)
- default_policy.min = driver_data->policy[0].min;
- if (!default_policy.max)
- default_policy.max = driver_data->policy[0].max;
- default_policy.cpu = CPUFREQ_ALL_CPUS;
+ /* check for a default policy - if it exists, use it on _all_ CPUs*/
+ for (i=0; i<NR_CPUS; i++)
+ {
+ if (default_policy.policy)
+ cpufreq_driver->policy[i].policy = default_policy.policy;
+ if (default_policy.min)
+ cpufreq_driver->policy[i].min = default_policy.min;
+ if (default_policy.max)
+ cpufreq_driver->policy[i].max = default_policy.max;
+ }
 
- up(&cpufreq_driver_sem);
+ /* set default policy on all CPUs. Must be called per-CPU and not
+ * with CPUFREQ_ALL_CPUs as there might be no common policy for all
+ * CPUs (UltraSPARC etc.)
+ */
+ for (i=0; i<NR_CPUS; i++)
+ {
+ policy.policy = cpufreq_driver->policy[i].policy;
+ policy.min = cpufreq_driver->policy[i].min;
+ policy.max = cpufreq_driver->policy[i].max;
+ policy.cpu = i;
+ up(&cpufreq_driver_sem);
+ ret = cpufreq_set_policy(&policy);
+ down(&cpufreq_driver_sem);
+ if (ret) {
+ cpufreq_driver = NULL;
+ up(&cpufreq_driver_sem);
+ return ret;
+ }
+ }
 
- ret = cpufreq_set_policy(&default_policy);
+ up(&cpufreq_driver_sem);
 
         cpufreq_proc_init();
 
 #ifdef CONFIG_CPU_FREQ_24_API
- down(&cpufreq_driver_sem);
- cpu_min_freq = driver_data->cpu_min_freq;
- cpu_max_freq = driver_data->policy[0].max_cpu_freq;
+ down(&cpufreq_driver_sem);
+ for (i=0; i<NR_CPUS; i++)
         {
- unsigned int i;
- for (i=0; i<NR_CPUS; i++) {
- cpu_cur_freq[i] = driver_data->cpu_cur_freq[i];
- }
+ cpu_min_freq[i] = driver_data->cpu_min_freq[i];
+ cpu_max_freq[i] = driver_data->policy[i].max_cpu_freq;
+ cpu_cur_freq[i] = driver_data->cpu_cur_freq[i];
         }
         up(&cpufreq_driver_sem);
 
         cpufreq_sysctl_init();
 #endif
- if (ret) {
- down(&cpufreq_driver_sem);
- cpufreq_driver = NULL;
- up(&cpufreq_driver_sem);
- }
 
- return ret;
+ return 0;
 }
 EXPORT_SYMBOL_GPL(cpufreq_register);
 
@@ -1061,6 +1096,7 @@
 {
         struct cpufreq_policy policy;
         unsigned int i;
+ unsigned int ret = 0;
 
         if (in_interrupt())
                 panic("cpufreq_restore() called from interrupt context!");
@@ -1081,10 +1117,10 @@
                 policy.cpu = i;
                 up(&cpufreq_driver_sem);
 
- cpufreq_set_policy(&policy);
+ ret += cpufreq_set_policy(&policy);
         }
 
- return 0;
+ return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_restore);
 #else



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Nov 23 2002 - 22:00:40 EST