Commit 0c7eef6a authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[PATCH] cpufreq: cleanups

This 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.
parent 645e448c
......@@ -87,7 +87,8 @@ PowerNow! K6:
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 @@ entries:
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 @@ cpufreq_setpolicy_t setpolicy: This is a pointer to a function with
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!
......
......@@ -73,7 +73,7 @@ static struct vco freq_to_vco(unsigned int freq_khz, int factor)
* 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 @@ static void integrator_verify_speed(struct cpufreq_policy *policy)
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 @@ static void do_set_policy(int cpu, struct cpufreq_policy *policy)
__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 @@ static void integrator_set_policy(struct cpufreq_policy *policy)
* Restore the CPUs allowed mask.
*/
set_cpus_allowed(current, cpus_allowed);
return 0;
}
static struct cpufreq_policy integrator_policy = {
......@@ -151,7 +155,6 @@ static struct cpufreq_driver integrator_driver = {
.verify = integrator_verify_speed,
.setpolicy = integrator_set_policy,
.policy = &integrator_policy,
.cpu_min_freq = 12000,
};
#endif
......@@ -202,6 +205,8 @@ static int __init integrator_cpu_init(void)
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
......
......@@ -176,7 +176,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
}
}
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 @@ static void sa1100_setspeed(struct cpufreq_policy *policy)
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 @@ static struct cpufreq_driver sa1100_driver = {
.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 @@ static int __init sa1100_dram_init(void)
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();
......
......@@ -212,7 +212,7 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
* 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 @@ static void sa1110_setspeed(struct cpufreq_policy *policy)
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_policy sa1110_policy = {
};
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)
......
......@@ -67,7 +67,7 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
* 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 @@ void sa11x0_verify_speed(struct cpufreq_policy *policy)
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)
......
......@@ -172,13 +172,13 @@ static void elanfreq_set_cpu_state (unsigned int state) {
* 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 @@ static void elanfreq_verify (struct cpufreq_policy *policy)
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 @@ static void elanfreq_verify (struct cpufreq_policy *policy)
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 @@ static void elanfreq_setpolicy (struct cpufreq_policy *policy)
if (number_states == 1) {
elanfreq_set_cpu_state(j);
return;
return 0;
}
switch (policy->policy) {
......@@ -236,14 +236,14 @@ static void elanfreq_setpolicy (struct cpufreq_policy *policy)
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 @@ static int __init elanfreq_init(void)
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 @@ static int __init elanfreq_init(void)
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;
}
......
/*
* $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 @@ static void __init longhaul_get_ranges (void)
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 inline unsigned int longhaul_statecount_fsb(struct cpufreq_policy *policy
}
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 @@ static void longhaul_verify(struct cpufreq_policy *policy)
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 @@ static void longhaul_verify(struct cpufreq_policy *policy)
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 @@ static void longhaul_verify(struct cpufreq_policy *policy)
}
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 @@ static void longhaul_setpolicy (struct cpufreq_policy *policy)
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 @@ static void longhaul_setpolicy (struct cpufreq_policy *policy)
}
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 @@ static void longhaul_setpolicy (struct cpufreq_policy *policy)
}
break;
default:
return;
return -EINVAL;
}
longhaul_setstate(new_clock_ratio, new_fsb);
return;
return 0;
}
......@@ -775,7 +779,7 @@ static int __init longhaul_init (void)
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 @@ static int __init longhaul_init (void)
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;
}
......
/*
* $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 @@ static void longrun_get_policy(struct cpufreq_policy *policy)
* 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 @@ static void longrun_set_policy(struct cpufreq_policy *policy)
msr_hi |= pctg_hi;
wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
return;
return 0;
}
......@@ -115,16 +115,16 @@ static void longrun_set_policy(struct cpufreq_policy *policy)
* 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 @@ static int __init longrun_init(void)
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;
}
......
......@@ -78,7 +78,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
}
#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 int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
}
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 @@ static void cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
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 @@ static void cpufreq_p4_verify(struct cpufreq_policy *policy)
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 @@ int __init cpufreq_p4_init(void)
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 @@ int __init cpufreq_p4_init(void)
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;
}
......
/*
* $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 @@ static void powernow_k6_set_state (unsigned int best_i)
* 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 @@ static void powernow_k6_verify(struct cpufreq_policy *policy)
number_states++;
if (number_states)
return;
return 0;
/* no state is available within range -- find next larger state */
......@@ -144,7 +144,7 @@ static void powernow_k6_verify(struct cpufreq_policy *policy)
policy->max = clock_ratio[j] * busfreq;
return;
return 0;
}
......@@ -154,13 +154,13 @@ static void powernow_k6_verify(struct cpufreq_policy *policy)
*
* 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 @@ static void powernow_k6_setpolicy (struct cpufreq_policy *policy)
/* 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 @@ static void powernow_k6_setpolicy (struct cpufreq_policy *policy)
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 @@ static int __init powernow_k6_init(void)
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 @@ static int __init powernow_k6_init(void)
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;
}
......
/*
* $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 @@ static int speedstep_detect_speeds (void)
*
* 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 @@ static void speedstep_setpolicy (struct cpufreq_policy *policy)
speedstep_set_state(SPEEDSTEP_HIGH, 1);
}
}
return 0;
}
......@@ -595,11 +596,11 @@ static void speedstep_setpolicy (struct cpufreq_policy *policy)
* 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 @@ static void speedstep_verify (struct cpufreq_policy *policy)
(policy->max < speedstep_high_freq))
policy->max = speedstep_high_freq;
return;
return 0;
}
......@@ -654,12 +655,11 @@ static int __init speedstep_init(void)
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 @@ static int __init speedstep_init(void)
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 @@ static int __init speedstep_init(void)
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;
}
......
......@@ -1613,7 +1613,7 @@ acpi_processor_get_limit_info (
cpufreq interface
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCESSOR_PERF
static void
static int
acpi_cpufreq_setpolicy (
struct cpufreq_policy *policy)
{
......@@ -1626,7 +1626,7 @@ acpi_cpufreq_setpolicy (
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 @@ acpi_cpufreq_setpolicy (
cpu = policy->cpu;
pr = processors[cpu];
if (!pr)
return_VOID;
return_VALUE(-EINVAL);
}
/* select appropriate P-State */
......@@ -1686,11 +1686,11 @@ acpi_cpufreq_setpolicy (
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_cpufreq_verify (
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 @@ acpi_cpufreq_verify (
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 @@ acpi_cpufreq_verify (
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 @@ acpi_cpufreq_init (
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;
......
......@@ -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 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu
* 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 @@ struct cpufreq_driver {
#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 @@ enum {
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 @@ enum {
.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, }, }
......
......@@ -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 @@ static struct cpufreq_policy default_policy = {
/**
* 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 @@ static int cpufreq_proc_read (
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 @@ int cpufreq_setmax(unsigned int cpu)
{
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 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
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_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
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 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
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 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
/* 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 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
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 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
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 @@ int cpufreq_register(struct cpufreq_driver *driver_data)
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 @@ int cpufreq_restore(void)
{
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 @@ int cpufreq_restore(void)
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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment