Commit bcf41bfd authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-dj.bkbits.net/cpufreq

into home.osdl.org:/home/torvalds/v2.5/linux
parents 3377ea43 fa1d2434
......@@ -64,6 +64,12 @@ And optionally
cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
cpufreq_driver.resume - A pointer to a per-CPU resume function
which is called with interrupts disabled
and _before_ the pre-suspend frequency
and/or policy is restored by a call to
->target or ->setpolicy.
cpufreq_driver.attr - A pointer to a NULL-terminated list of
"struct freq_attr" which allow to
export values to sysfs.
......@@ -119,7 +125,7 @@ section 2 for details on frequency table helpers.
You need to make sure that at least one valid frequency (or operating
range) is within policy->min and policy->max. If necessary, increase
policy->max fist, and only if this is no solution, decreas policy->min.
policy->max first, and only if this is no solution, decrease policy->min.
1.4 target or setpolicy?
......
......@@ -542,39 +542,15 @@ config CPU_FREQ_SA1100
bool
depends on CPU_FREQ && SA1100_LART
default y
select CPU_FREQ_DEFAULT_GOV_USERSPACE
select CPU_FREQ_24_API if SYSCTL
config CPU_FREQ_SA1110
bool
depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
default y
if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110)
config CPU_FREQ_GOV_USERSPACE
tristate
depends on CPU_FREQ
default y
config CPU_FREQ_24_API
bool
depends on CPU_FREQ_GOV_USERSPACE && SYSCTL
default y
config CPU_FREQ_PROC_INTF
tristate "/proc/cpufreq interface (deprecated)"
depends on CPU_FREQ && PROC_FS
help
This enables the /proc/cpufreq interface for controlling
CPUFreq. Please note that it is recommended to use the sysfs
interface instead (which is built automatically).
For details, take a look at linux/Documentation/cpufreq.
If in doubt, say N.
endif
# CPUfreq on Integrator can use the generic cpufreq core
select CPU_FREQ_DEFAULT_GOV_USERSPACE
select CPU_FREQ_24_API if SYSCTL
config CPU_FREQ_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs"
......@@ -587,7 +563,7 @@ config CPU_FREQ_INTEGRATOR
If in doubt, say Y.
if (CPU_FREQ_INTEGRATOR)
if (CPU_FREQ_INTEGRATOR) || (CPU_FREQ_SA1110) || (CPU_FREQ_SA1100)
source "drivers/cpufreq/Kconfig"
......
......@@ -170,7 +170,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
vco.r = 22;
/* set default policy and cpuinfo */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.max_freq = 160000;
policy->cpuinfo.min_freq = 12000;
policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */
......
......@@ -222,7 +222,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0)
return -EINVAL;
policy->cur = policy->min = policy->max = sa11x0_getspeed();
policy->policy = CPUFREQ_POLICY_POWERSAVE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.min_freq = 59000;
policy->cpuinfo.max_freq = 287000;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
......
......@@ -321,7 +321,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0)
return -EINVAL;
policy->cur = policy->min = policy->max = sa11x0_getspeed();
policy->policy = CPUFREQ_POLICY_POWERSAVE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.min_freq = 59000;
policy->cpuinfo.max_freq = 287000;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
......
......@@ -580,7 +580,7 @@ acpi_cpufreq_cpu_init (
if (perf->states[i].transition_latency > policy->cpuinfo.transition_latency)
policy->cpuinfo.transition_latency = perf->states[i].transition_latency;
}
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000;
/* table init */
......
......@@ -216,7 +216,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
}
/* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = elanfreq_get_cpu_frequency();
......
......@@ -434,7 +434,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
policy->min = maxfreq / POLICY_MIN_DIV;
policy->max = maxfreq;
policy->cur = curfreq;
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.min_freq = maxfreq / max_duration;
policy->cpuinfo.max_freq = maxfreq;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
......
This diff is collapsed.
......@@ -47,3 +47,204 @@ union msr_longhaul {
unsigned long long val;
};
/*
* Clock ratio tables. Div/Mod by 10 to get ratio.
* The eblcr ones specify the ratio read from the CPU.
* The clock_ratio ones specify what to write to the CPU.
*/
/*
* VIA C3 Samuel 1 & Samuel 2 (stepping 0)
*/
static int __initdata longhaul1_clock_ratio[16] = {
-1, /* 0000 -> RESERVED */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
-1, /* 0011 -> RESERVED */
-1, /* 0100 -> RESERVED */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
55, /* 0111 -> 5.5x */
60, /* 1000 -> 6.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
50, /* 1011 -> 5.0x */
65, /* 1100 -> 6.5x */
75, /* 1101 -> 7.5x */
-1, /* 1110 -> RESERVED */
-1, /* 1111 -> RESERVED */
};
static int __initdata samuel1_eblcr[16] = {
50, /* 0000 -> RESERVED */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
-1, /* 0011 -> RESERVED */
55, /* 0100 -> 5.5x */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
-1, /* 0111 -> RESERVED */
-1, /* 1000 -> RESERVED */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
60, /* 1011 -> 6.0x */
-1, /* 1100 -> RESERVED */
75, /* 1101 -> 7.5x */
-1, /* 1110 -> RESERVED */
65, /* 1111 -> 6.5x */
};
/*
* VIA C3 Samuel2 Stepping 1->15 & VIA C3 Ezra
*/
static int __initdata longhaul2_clock_ratio[16] = {
100, /* 0000 -> 10.0x */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
90, /* 0011 -> 9.0x */
95, /* 0100 -> 9.5x */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
55, /* 0111 -> 5.5x */
60, /* 1000 -> 6.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
50, /* 1011 -> 5.0x */
65, /* 1100 -> 6.5x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
120, /* 1111 -> 12.0x */
};
static int __initdata samuel2_eblcr[16] = {
50, /* 0000 -> 5.0x */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
100, /* 0011 -> 10.0x */
55, /* 0100 -> 5.5x */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
110, /* 0111 -> 11.0x */
90, /* 1000 -> 9.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
60, /* 1011 -> 6.0x */
120, /* 1100 -> 12.0x */
75, /* 1101 -> 7.5x */
130, /* 1110 -> 13.0x */
65, /* 1111 -> 6.5x */
};
static int __initdata ezra_eblcr[16] = {
50, /* 0000 -> 5.0x */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
100, /* 0011 -> 10.0x */
55, /* 0100 -> 5.5x */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
95, /* 0111 -> 9.5x */
90, /* 1000 -> 9.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
60, /* 1011 -> 6.0x */
120, /* 1100 -> 12.0x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
65, /* 1111 -> 6.5x */
};
/*
* VIA C3 (Ezra-T) [C5M].
*/
static int __initdata longhaul3_clock_ratio[32] = {
100, /* 0000 -> 10.0x */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
90, /* 0011 -> 9.0x */
95, /* 0100 -> 9.5x */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
55, /* 0111 -> 5.5x */
60, /* 1000 -> 6.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
50, /* 1011 -> 5.0x */
65, /* 1100 -> 6.5x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
120, /* 1111 -> 12.0x */
-1, /* 0000 -> RESERVED (10.0x) */
110, /* 0001 -> 11.0x */
120, /* 0010 -> 12.0x */
-1, /* 0011 -> RESERVED (9.0x)*/
105, /* 0100 -> 10.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
135, /* 0111 -> 13.5x */
140, /* 1000 -> 14.0x */
150, /* 1001 -> 15.0x */
160, /* 1010 -> 16.0x */
130, /* 1011 -> 13.0x */
145, /* 1100 -> 14.5x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
-1, /* 1111 -> RESERVED (12.0x) */
};
static int __initdata c5m_eblcr[32] = {
50, /* 0000 -> 5.0x */
30, /* 0001 -> 3.0x */
40, /* 0010 -> 4.0x */
100, /* 0011 -> 10.0x */
55, /* 0100 -> 5.5x */
35, /* 0101 -> 3.5x */
45, /* 0110 -> 4.5x */
95, /* 0111 -> 9.5x */
90, /* 1000 -> 9.0x */
70, /* 1001 -> 7.0x */
80, /* 1010 -> 8.0x */
60, /* 1011 -> 6.0x */
120, /* 1100 -> 12.0x */
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
65, /* 1111 -> 6.5x */
-1, /* 0000 -> RESERVED (9.0x) */
110, /* 0001 -> 11.0x */
120, /* 0010 -> 12.0x */
-1, /* 0011 -> RESERVED (10.0x)*/
135, /* 0100 -> 13.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
105, /* 0111 -> 10.5x */
130, /* 1000 -> 13.0x */
150, /* 1001 -> 15.0x */
160, /* 1010 -> 16.0x */
140, /* 1011 -> 14.0x */
-1, /* 1100 -> RESERVED (12.0x) */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
145, /* 1111 -> 14.5x */
};
/*
* Voltage scales. Div/Mod by 1000 to get actual voltage.
* Which scale to use depends on the VRM type in use.
*/
static int __initdata vrm85scales[32] = {
1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700,
1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300,
1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725,
1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325,
};
static int __initdata mobilevrmscales[32] = {
2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
1600, 1550, 1500, 1450, 1500, 1350, 1300, -1,
1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
1075, 1050, 1025, 1000, 975, 950, 925, -1,
};
......@@ -120,7 +120,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
if (policy->policy == CPUFREQ_POLICY_GOVERNOR)
if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
(policy->policy != CPUFREQ_POLICY_PERFORMANCE))
return -EINVAL;
return 0;
......
......@@ -211,7 +211,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
/* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 1000;
policy->cur = stock_freq;
......
......@@ -157,7 +157,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
}
/* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = busfreq * max_multiplier;
......
/*
* AMD K7 Powernow driver.
* (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs.
* (C) 2003 Dave Jones <davej@redhat.com>
*
* Licensed under the terms of the GNU GPL License version 2.
* Based upon datasheets & sample CPUs kindly provided by AMD.
......@@ -325,6 +326,8 @@ static int powernow_decode_bios (int maxfid, int startvid)
p+=2;
}
}
printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);
printk ("This is indicative of a broken BIOS. Email davej@redhat.com\n");
return -EINVAL;
}
p++;
......@@ -372,7 +375,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
minimum_speed, maximum_speed);
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = latency;
policy->cur = maximum_speed;
......
......@@ -201,9 +201,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
freq = get_cur_freq();
policy->policy = (freq == centrino_model->max_freq) ?
CPUFREQ_POLICY_PERFORMANCE :
CPUFREQ_POLICY_POWERSAVE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */
policy->cur = freq;
......
......@@ -299,8 +299,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
(speed / 1000));
/* cpuinfo and default policy values */
policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ?
CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = speed;
......@@ -309,7 +308,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
static struct cpufreq_driver speedstep_driver = {
.name = "speedstep",
.name = "speedstep-ich",
.verify = speedstep_verify,
.target = speedstep_target,
.init = speedstep_cpu_init,
......
......@@ -257,8 +257,7 @@ pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0)
return -ENODEV;
policy->policy = (cur_freq == low_freq) ?
CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = cur_freq;
......
......@@ -160,7 +160,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
sh_freqs[SH_FREQ_MIN].frequency = min_freq;
/* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = max_freq;
......
......@@ -309,7 +309,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
table[2].index = 5;
table[3].frequency = CPUFREQ_TABLE_END;
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick;
......
......@@ -163,7 +163,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
table[3].index = 0;
table[3].frequency = CPUFREQ_TABLE_END;
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick;
......
......@@ -10,6 +10,51 @@ config CPU_FREQ_PROC_INTF
If in doubt, say N.
choice
prompt "Default CPUFreq governor"
depends on CPU_FREQ
default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
help
This option sets which CPUFreq governor shall be loaded at
startup. If in doubt, select 'performance'.
config CPU_FREQ_DEFAULT_GOV_PERFORMANCE
bool "performance"
select CPU_FREQ_GOV_PERFORMANCE
help
Use the CPUFreq governor 'performance' as default. This sets
the frequency statically to the highest frequency supported by
the CPU.
config CPU_FREQ_DEFAULT_GOV_USERSPACE
bool "userspace"
select CPU_FREQ_GOV_USERSPACE
help
Use the CPUFreq governor 'userspace' as default. This allows
you to set the CPU frequency manually or when an userspace
programm shall be able to set the CPU dynamically without having
to enable the userspace governor manually.
endchoice
config CPU_FREQ_GOV_PERFORMANCE
tristate "'performance' governor"
depends on CPU_FREQ
help
This cpufreq governors set the frequency statically to the
highest available CPU frequency.
If in doubt, say Y.
config CPU_FREQ_GOV_POWERSAVE
tristate "'powersave' governor"
depends on CPU_FREQ
help
Theis cpufreq governors set the frequency statically to the
lowest available CPU frequency.
If in doubt, say Y.
config CPU_FREQ_GOV_USERSPACE
tristate "'userspace' governor for userspace frequency scaling"
depends on CPU_FREQ
......
# CPUfreq core
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
# CPUfreq governors
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
......
......@@ -109,12 +109,17 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data)
int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
struct cpufreq_governor **governor)
{
if (!cpufreq_driver)
return -EINVAL;
if (cpufreq_driver->setpolicy) {
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_PERFORMANCE;
return 0;
} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
return -EINVAL;
} else {
struct cpufreq_governor *t;
down(&cpufreq_governor_sem);
......@@ -123,7 +128,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
*governor = t;
*policy = CPUFREQ_POLICY_GOVERNOR;
up(&cpufreq_governor_sem);
return 0;
}
......@@ -190,16 +194,13 @@ store_one(scaling_max_freq,max);
*/
static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
{
switch (policy->policy) {
case CPUFREQ_POLICY_POWERSAVE:
if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
return sprintf(buf, "powersave\n");
case CPUFREQ_POLICY_PERFORMANCE:
else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
return sprintf(buf, "performance\n");
case CPUFREQ_POLICY_GOVERNOR:
else if (policy->governor)
return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
default:
return -EINVAL;
}
}
......@@ -246,15 +247,15 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
ssize_t i = 0;
struct cpufreq_governor *t;
if (!cpufreq_driver->target) {
i += sprintf(buf, "performance powersave");
if (!cpufreq_driver->target)
goto out;
}
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
goto out;
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
}
out:
i += sprintf(&buf[i], "\n");
......@@ -396,10 +397,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_cpu_data[cpu] = policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
up(&policy->lock);
/* set default policy */
ret = cpufreq_set_policy(&new_policy);
if (ret)
goto err_out_unregister;
......@@ -492,6 +495,13 @@ static int cpufreq_resume(struct sys_device * sysdev)
if (!cpu_policy)
return -EINVAL;
if (cpufreq_driver->resume)
ret = cpufreq_driver->resume(cpu_policy);
if (ret) {
printk(KERN_ERR "cpufreq: resume failed in ->resume step on CPU %u\n", cpu_policy->cpu);
goto out;
}
if (cpufreq_driver->setpolicy)
ret = cpufreq_driver->setpolicy(cpu_policy);
else
......@@ -500,6 +510,12 @@ static int cpufreq_resume(struct sys_device * sysdev)
*/
ret = cpufreq_driver->target(cpu_policy, cpu_policy->cur, CPUFREQ_RELATION_H);
if (ret) {
printk(KERN_ERR "cpufreq: resume failed in ->setpolicy/target step on CPU %u\n", cpu_policy->cpu);
goto out;
}
out:
cpufreq_cpu_put(cpu_policy);
return ret;
......@@ -622,33 +638,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target);
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
{
int ret = 0;
int ret = -EINVAL;
switch (policy->policy) {
case CPUFREQ_POLICY_POWERSAVE:
if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
}
break;
case CPUFREQ_POLICY_PERFORMANCE:
if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
}
break;
case CPUFREQ_POLICY_GOVERNOR:
ret = -EINVAL;
if (!try_module_get(policy->governor->owner))
break;
return -EINVAL;
ret = policy->governor->governor(policy, event);
/* we keep one module reference alive for each CPU governed by this CPU */
if ((event != CPUFREQ_GOV_START) || ret)
module_put(policy->governor->owner);
if ((event == CPUFREQ_GOV_STOP) && !ret)
module_put(policy->governor->owner);
break;
default:
ret = -EINVAL;
}
return ret;
}
......@@ -680,11 +681,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
if (!governor)
return -EINVAL;
if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN))
return -EBUSY;
if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
return -EBUSY;
down(&cpufreq_governor_sem);
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
......@@ -808,24 +804,25 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
data->policy = policy->policy;
ret = cpufreq_driver->setpolicy(policy);
} else {
if ((policy->policy != data->policy) ||
((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
if (policy->governor != data->governor) {
/* save old, working values */
unsigned int old_pol = data->policy;
struct cpufreq_governor *old_gov = data->governor;
/* end old governor */
if (data->governor)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
/* start new governor */
data->policy = policy->policy;
data->governor = policy->governor;
if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
/* new governor failed, so re-start old one */
data->policy = old_pol;
if (old_gov) {
data->governor = old_gov;
__cpufreq_governor(data, CPUFREQ_GOV_START);
}
ret = -EINVAL;
goto error_out;
}
/* might be a policy change, too, so fall through */
}
__cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
......
/*
* linux/drivers/cpufreq/cpufreq_performance.c
*
* Copyright (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
*
* 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
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpufreq.h>
#include <linux/init.h>
static int cpufreq_governor_performance(struct cpufreq_policy *policy,
unsigned int event)
{
switch (event) {
case CPUFREQ_GOV_START:
case CPUFREQ_GOV_LIMITS:
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
break;
default:
break;
}
return 0;
}
struct cpufreq_governor cpufreq_gov_performance = {
.name = "performance",
.governor = cpufreq_governor_performance,
.owner = THIS_MODULE,
};
EXPORT_SYMBOL(cpufreq_gov_performance);
static int __init cpufreq_gov_performance_init(void)
{
return cpufreq_register_governor(&cpufreq_gov_performance);
}
static void __exit cpufreq_gov_performance_exit(void)
{
cpufreq_unregister_governor(&cpufreq_gov_performance);
}
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("CPUfreq policy governor 'performance'");
MODULE_LICENSE("GPL");
fs_initcall(cpufreq_gov_performance_init);
module_exit(cpufreq_gov_performance_exit);
/*
* linux/drivers/cpufreq/cpufreq_powersave.c
*
* Copyright (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
*
* 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
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpufreq.h>
#include <linux/init.h>
static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
unsigned int event)
{
switch (event) {
case CPUFREQ_GOV_START:
case CPUFREQ_GOV_LIMITS:
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
break;
default:
break;
}
return 0;
}
static struct cpufreq_governor cpufreq_gov_powersave = {
.name = "powersave",
.governor = cpufreq_governor_powersave,
.owner = THIS_MODULE,
};
static int __init cpufreq_gov_powersave_init(void)
{
return cpufreq_register_governor(&cpufreq_gov_powersave);
}
static void __exit cpufreq_gov_powersave_exit(void)
{
cpufreq_unregister_governor(&cpufreq_gov_powersave);
}
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'");
MODULE_LICENSE("GPL");
module_init(cpufreq_gov_powersave_init);
module_exit(cpufreq_gov_powersave_exit);
......@@ -498,9 +498,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
unsigned int cpu = policy->cpu;
switch (event) {
case CPUFREQ_GOV_START:
if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) ||
!policy->cur)
if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)))
return -EINVAL;
BUG_ON(!policy->cur);
down(&userspace_sem);
cpu_is_managed[cpu] = 1;
cpu_min_freq[cpu] = policy->min;
......@@ -551,7 +551,7 @@ static void cpufreq_sa11x0_compat(void)
#endif
static struct cpufreq_governor cpufreq_gov_userspace = {
struct cpufreq_governor cpufreq_gov_userspace = {
.name = "userspace",
.governor = cpufreq_governor_userspace,
.owner = THIS_MODULE,
......@@ -587,5 +587,5 @@ MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.
MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
MODULE_LICENSE ("GPL");
module_init(cpufreq_gov_userspace_init);
fs_initcall(cpufreq_gov_userspace_init);
module_exit(cpufreq_gov_userspace_exit);
......@@ -126,6 +126,7 @@ static int cpufreq_proc_read (
p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
i , policy.min, min_pctg, policy.max, max_pctg);
if (policy.policy) {
switch (policy.policy) {
case CPUFREQ_POLICY_POWERSAVE:
p += sprintf(p, "powersave\n");
......@@ -133,13 +134,12 @@ static int cpufreq_proc_read (
case CPUFREQ_POLICY_PERFORMANCE:
p += sprintf(p, "performance\n");
break;
case CPUFREQ_POLICY_GOVERNOR:
p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
break;
default:
p += sprintf(p, "INVALID\n");
break;
}
} else
p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
}
end:
len = (p - page);
......
......@@ -36,11 +36,13 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
#define CPUFREQ_POLICY_NOTIFIER (1)
/********************** cpufreq policy notifiers *********************/
/* if (cpufreq_driver->target) exists, the ->governor decides what frequency
* within the limits is used. If (cpufreq_driver->setpolicy> exists, these
* two generic policies are available:
*/
#define CPUFREQ_POLICY_POWERSAVE (1)
#define CPUFREQ_POLICY_PERFORMANCE (2)
#define CPUFREQ_POLICY_GOVERNOR (3)
/* Frequency values here are CPU kHz so that hardware which doesn't run
* with some frequencies can complain without having to guess what per
......@@ -151,6 +153,7 @@ int cpufreq_governor(unsigned int cpu, unsigned int event);
int cpufreq_register_governor(struct cpufreq_governor *governor);
void cpufreq_unregister_governor(struct cpufreq_governor *governor);
/*********************************************************************
* CPUFREQ DRIVER INTERFACE *
*********************************************************************/
......@@ -176,6 +179,7 @@ struct cpufreq_driver {
/* optional */
int (*exit) (struct cpufreq_policy *policy);
int (*resume) (struct cpufreq_policy *policy);
struct freq_attr **attr;
};
......@@ -221,7 +225,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu
/*********************************************************************
* CPUFREQ USERSPACE GOVERNOR *
*********************************************************************/
extern struct cpufreq_governor cpufreq_gov_userspace;
int cpufreq_gov_userspace_init(void);
int cpufreq_setmax(unsigned int cpu);
......@@ -279,6 +282,19 @@ enum {
#endif /* CONFIG_CPU_FREQ_GOV_USERSPACE */
/*********************************************************************
* CPUFREQ DEFAULT GOVERNOR *
*********************************************************************/
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
extern struct cpufreq_governor cpufreq_gov_performance;
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance
#elif CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
extern struct cpufreq_governor cpufreq_gov_userspace;
#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace
#endif
/*********************************************************************
* FREQUENCY TABLE HELPERS *
*********************************************************************/
......
......@@ -15,7 +15,6 @@ obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += ksyms.o module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_COMPAT) += compat.o
obj-$(CONFIG_IKCONFIG) += configs.o
......
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