summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Brodowski <linux@brodo.de>2003-02-28 16:54:06 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-02-28 16:54:06 -0800
commit3537d16121f55c115b59d4ecb312463eb92acef3 (patch)
treea89f067ceb3e949e715d7e7770d562988c46abd1
parent5787e471fbd9dec35c927e2c360c336a0293440d (diff)
[PATCH] cpufreq (2/5): x86 driver updates #2 (acpi, longhaul)
- update the VIA Longhaul driver to use frequency table helpers and the advanced cpufreq driver registration interface. - cleanup of the ACPI P-States cpufreq driver - very small update of the core -- set 24API values ahead of the setpolicy call.
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig12
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi.c285
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c291
-rw-r--r--kernel/cpufreq.c14
4 files changed, 272 insertions, 330 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index bf61dd5a9c56..aa0f51b69d10 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -56,6 +56,16 @@ config X86_ACPI_CPUFREQ
If in doubt, say N.
+config X86_ACPI_CPUFREQ_PROC_INTF
+ bool "/proc/acpi/processor/../performance interface (deprecated)"
+ depends on X86_ACPI_CPUFREQ && PROC_FS
+ help
+ This enables the deprecated /proc/acpi/processor/../performance
+ interface. While it is helpful for debugging, the generic,
+ cross-architecture cpufreq interfaces should be used.
+
+ If in doubt, say N.
+
config ELAN_CPUFREQ
tristate "AMD Elan"
depends on CPU_FREQ_TABLE && MELAN
@@ -139,7 +149,7 @@ config X86_LONGRUN
config X86_LONGHAUL
tristate "VIA Cyrix III Longhaul"
- depends on CPU_FREQ
+ depends on CPU_FREQ_TABLE
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
index 1d84b053fc0e..b5fef75c62f8 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c
@@ -50,23 +50,13 @@ MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
MODULE_LICENSE("GPL");
-/* Performance Management */
-
static struct acpi_processor_performance *performance;
static struct cpufreq_driver acpi_cpufreq_driver;
-static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
-static struct file_operations acpi_processor_perf_fops = {
- .open = acpi_processor_perf_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static int
acpi_processor_get_performance_control (
- struct acpi_processor *pr)
+ struct acpi_processor_performance *perf)
{
int result = 0;
acpi_status status = 0;
@@ -77,7 +67,7 @@ acpi_processor_get_performance_control (
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
- status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
+ status = acpi_evaluate_object(perf->pr->handle, "_PCT", NULL, &buffer);
if(ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
return_VALUE(-ENODEV);
@@ -116,7 +106,7 @@ acpi_processor_get_performance_control (
goto end;
}
- pr->performance->control_register = (u16) reg->address;
+ perf->control_register = (u16) reg->address;
/*
* status_register
@@ -143,12 +133,12 @@ acpi_processor_get_performance_control (
goto end;
}
- pr->performance->status_register = (u16) reg->address;
+ perf->status_register = (u16) reg->address;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"control_register[0x%04x] status_register[0x%04x]\n",
- pr->performance->control_register,
- pr->performance->status_register));
+ perf->control_register,
+ perf->status_register));
end:
acpi_os_free(buffer.pointer);
@@ -159,7 +149,7 @@ end:
static int
acpi_processor_get_performance_states (
- struct acpi_processor* pr)
+ struct acpi_processor_performance * perf)
{
int result = 0;
acpi_status status = AE_OK;
@@ -171,7 +161,7 @@ acpi_processor_get_performance_states (
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
- status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
+ status = acpi_evaluate_object(perf->pr->handle, "_PSS", NULL, &buffer);
if(ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
return_VALUE(-ENODEV);
@@ -188,20 +178,20 @@ acpi_processor_get_performance_states (
pss->package.count));
if (pss->package.count > ACPI_PROCESSOR_MAX_PERFORMANCE) {
- pr->performance->state_count = ACPI_PROCESSOR_MAX_PERFORMANCE;
+ perf->state_count = ACPI_PROCESSOR_MAX_PERFORMANCE;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Limiting number of states to max (%d)\n",
ACPI_PROCESSOR_MAX_PERFORMANCE));
}
else
- pr->performance->state_count = pss->package.count;
+ perf->state_count = pss->package.count;
- if (pr->performance->state_count > 1)
- pr->flags.performance = 1;
+ if (perf->state_count > 1)
+ perf->pr->flags.performance = 1;
- for (i = 0; i < pr->performance->state_count; i++) {
+ for (i = 0; i < perf->state_count; i++) {
- struct acpi_processor_px *px = &(pr->performance->states[i]);
+ struct acpi_processor_px *px = &(perf->states[i]);
state.length = sizeof(struct acpi_processor_px);
state.pointer = px;
@@ -236,7 +226,7 @@ end:
static int
acpi_processor_set_performance (
- struct acpi_processor *pr,
+ struct acpi_processor_performance *perf,
int state)
{
u16 port = 0;
@@ -246,38 +236,38 @@ acpi_processor_set_performance (
ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
- if (!pr)
+ if (!perf || !perf->pr)
return_VALUE(-EINVAL);
- if (!pr->flags.performance)
+ if (!perf->pr->flags.performance)
return_VALUE(-ENODEV);
- if (state >= pr->performance->state_count) {
+ if (state >= perf->state_count) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid target state (P%d)\n", state));
return_VALUE(-ENODEV);
}
- if (state < pr->performance_platform_limit) {
+ if (state < perf->pr->performance_platform_limit) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Platform limit (P%d) overrides target state (P%d)\n",
- pr->performance->platform_limit, state));
+ perf->pr->performance_platform_limit, state));
return_VALUE(-ENODEV);
}
- if (state == pr->performance->state) {
+ if (state == perf->state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Already at target state (P%d)\n", state));
return_VALUE(0);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
- pr->performance->state, state));
+ perf->state, state));
/* cpufreq frequency struct */
- cpufreq_freqs.cpu = pr->id;
- cpufreq_freqs.old = pr->performance->states[pr->performance->state].core_frequency;
- cpufreq_freqs.new = pr->performance->states[state].core_frequency;
+ cpufreq_freqs.cpu = perf->pr->id;
+ cpufreq_freqs.old = perf->states[perf->state].core_frequency;
+ cpufreq_freqs.new = perf->states[state].core_frequency;
/* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
@@ -287,8 +277,8 @@ acpi_processor_set_performance (
* control_register.
*/
- port = pr->performance->control_register;
- value = (u16) pr->performance->states[state].control;
+ port = perf->control_register;
+ value = (u16) perf->states[state].control;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Writing 0x%02x to port 0x%04x\n", value, port));
@@ -302,15 +292,15 @@ acpi_processor_set_performance (
* giving up.
*/
- port = pr->performance->status_register;
+ port = perf->status_register;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Looking for 0x%02x from port 0x%04x\n",
- (u8) pr->performance->states[state].status, port));
+ (u8) perf->states[state].status, port));
for (i=0; i<100; i++) {
value = inb(port);
- if (value == (u8) pr->performance->states[state].status)
+ if (value == (u8) perf->states[state].status)
break;
udelay(10);
}
@@ -318,7 +308,7 @@ acpi_processor_set_performance (
/* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
- if (value != pr->performance->states[state].status) {
+ if (value != perf->states[state].status) {
unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp;
@@ -332,11 +322,23 @@ acpi_processor_set_performance (
"Transition successful after %d microseconds\n",
i * 10));
- pr->performance->state = state;
+ perf->state = state;
return_VALUE(0);
}
+
+#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
+/* /proc/acpi/processor/../performance interface (DEPRECATED) */
+
+static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
+static struct file_operations acpi_processor_perf_fops = {
+ .open = acpi_processor_perf_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_processor *pr = (struct acpi_processor *)seq->private;
@@ -347,7 +349,7 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
if (!pr)
goto end;
- if (!pr->flags.performance) {
+ if (!pr->flags.performance || !pr->performance) {
seq_puts(seq, "<not supported>\n");
goto end;
}
@@ -379,8 +381,8 @@ static int
acpi_processor_write_performance (
struct file *file,
const char *buffer,
- unsigned long count,
- void *data)
+ size_t count,
+ loff_t *data)
{
int result = 0;
struct acpi_processor *pr = (struct acpi_processor *) data;
@@ -411,24 +413,78 @@ acpi_processor_write_performance (
return_VALUE(count);
}
+static void
+acpi_cpufreq_add_file (
+ struct acpi_processor *pr)
+{
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_device *device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
+
+ if (acpi_bus_get_device(pr->handle, &device))
+ return_VOID;
+
+ /* add file 'performance' [R/W] */
+ entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
+ S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
+ if (!entry)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_PROCESSOR_FILE_PERFORMANCE));
+ else {
+ entry->proc_fops = &acpi_processor_perf_fops;
+ entry->proc_fops->write = acpi_processor_write_performance;
+ entry->data = acpi_driver_data(device);
+ }
+ return_VOID;
+}
+
+static void
+acpi_cpufreq_remove_file (
+ struct acpi_processor *pr)
+{
+ struct acpi_device *device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
+
+ if (acpi_bus_get_device(pr->handle, &device))
+ return_VOID;
+
+ /* remove file 'performance' */
+ remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
+ acpi_device_dir(device));
+
+ return_VOID;
+}
+
+#else
+static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
+static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
+#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
+
static int
-acpi_cpufreq_setpolicy (
- struct cpufreq_policy *policy)
+acpi_cpufreq_target (
+ struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
- struct acpi_processor *pr = performance[policy->cpu].pr;
+ struct acpi_processor_performance *perf = &performance[policy->cpu];
unsigned int next_state = 0;
unsigned int result = 0;
ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy");
- result = cpufreq_frequency_table_setpolicy(policy,
- &performance[policy->cpu].freq_table[pr->limit.state.px],
+ result = cpufreq_frequency_table_target(policy,
+ &perf->freq_table[perf->pr->limit.state.px],
+ target_freq,
+ relation,
&next_state);
if (result)
return_VALUE(result);
- result = acpi_processor_set_performance (pr, next_state);
+ result = acpi_processor_set_performance (perf, next_state);
return_VALUE(result);
}
@@ -439,18 +495,17 @@ acpi_cpufreq_verify (
struct cpufreq_policy *policy)
{
unsigned int result = 0;
- unsigned int cpu = policy->cpu;
- struct acpi_processor *pr = performance[policy->cpu].pr;
+ struct acpi_processor_performance *perf = &performance[policy->cpu];
ACPI_FUNCTION_TRACE("acpi_cpufreq_verify");
result = cpufreq_frequency_table_verify(policy,
- &performance[cpu].freq_table[pr->limit.state.px]);
+ &perf->freq_table[perf->pr->limit.state.px]);
cpufreq_verify_within_limits(
policy,
- performance[cpu].states[performance[cpu].state_count - 1].core_frequency * 1000,
- performance[cpu].states[pr->limit.state.px].core_frequency * 1000);
+ perf->states[perf->state_count - 1].core_frequency * 1000,
+ perf->states[perf->pr->limit.state.px].core_frequency * 1000);
return_VALUE(result);
}
@@ -458,7 +513,7 @@ acpi_cpufreq_verify (
static int
acpi_processor_get_performance_info (
- struct acpi_processor *pr)
+ struct acpi_processor_performance *perf)
{
int result = 0;
acpi_status status = AE_OK;
@@ -466,31 +521,32 @@ acpi_processor_get_performance_info (
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
- if (!pr)
+ if (!perf || !perf->pr || !perf->pr->handle)
return_VALUE(-EINVAL);
- status = acpi_get_handle(pr->handle, "_PCT", &handle);
+ status = acpi_get_handle(perf->pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"ACPI-based processor performance control unavailable\n"));
return_VALUE(-ENODEV);
}
- result = acpi_processor_get_performance_control(pr);
+ result = acpi_processor_get_performance_control(perf);
if (result)
return_VALUE(result);
- result = acpi_processor_get_performance_states(pr);
+ result = acpi_processor_get_performance_states(perf);
if (result)
return_VALUE(result);
- result = acpi_processor_get_platform_limit(pr);
+ result = acpi_processor_get_platform_limit(perf->pr);
if (result)
return_VALUE(result);
return_VALUE(0);
}
+
static int
acpi_cpufreq_cpu_init (
struct cpufreq_policy *policy)
@@ -498,22 +554,18 @@ acpi_cpufreq_cpu_init (
unsigned int i;
unsigned int cpu = policy->cpu;
struct acpi_processor *pr = NULL;
+ struct acpi_processor_performance *perf = &performance[policy->cpu];
unsigned int result = 0;
- struct proc_dir_entry *entry = NULL;
- struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
- acpi_processor_register_performance(&performance[cpu], &pr, cpu);
+ acpi_processor_register_performance(perf, &pr, cpu);
pr = performance[cpu].pr;
if (!pr)
return_VALUE(-ENODEV);
- if (acpi_bus_get_device(pr->handle, &device))
- return_VALUE(-ENODEV);
-
- result = acpi_processor_get_performance_info(performance[cpu].pr);
+ result = acpi_processor_get_performance_info(perf);
if (result)
return_VALUE(-ENODEV);
@@ -523,52 +575,64 @@ acpi_cpufreq_cpu_init (
/* detect transition latency */
policy->cpuinfo.transition_latency = 0;
- for (i=0;i<performance[cpu].state_count;i++) {
- if (performance[cpu].states[i].transition_latency > policy->cpuinfo.transition_latency)
- policy->cpuinfo.transition_latency = performance[cpu].states[i].transition_latency;
+ for (i=0;i<perf->state_count;i++) {
+ if (perf->states[i].transition_latency > policy->cpuinfo.transition_latency)
+ policy->cpuinfo.transition_latency = perf->states[i].transition_latency;
}
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+#ifdef CONFIG_CPU_FREQ_24_API
+ acpi_cpufreq_driver.cpu_cur_freq[policy->cpu] = perf->states[pr->limit.state.px].core_frequency * 1000;
+#endif
/* table init */
- for (i=0; i<=performance[cpu].state_count; i++)
+ for (i=0; i<=perf->state_count; i++)
{
- performance[cpu].freq_table[i].index = i;
- if (i<performance[cpu].state_count)
- performance[cpu].freq_table[i].frequency = performance[cpu].states[i].core_frequency * 1000;
+ perf->freq_table[i].index = i;
+ if (i<perf->state_count)
+ perf->freq_table[i].frequency = perf->states[i].core_frequency * 1000;
else
- performance[cpu].freq_table[i].frequency = CPUFREQ_TABLE_END;
+ perf->freq_table[i].frequency = CPUFREQ_TABLE_END;
}
-#ifdef CONFIG_CPU_FREQ_24_API
- acpi_cpufreq_driver.cpu_cur_freq[policy->cpu] = performance[cpu].states[pr->limit.state.px].core_frequency * 1000;
-#endif
-
- result = cpufreq_frequency_table_cpuinfo(policy, &performance[cpu].freq_table[0]);
+ result = cpufreq_frequency_table_cpuinfo(policy, &perf->freq_table[0]);
- /* add file 'performance' [R/W] */
- entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
- S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
- if (!entry)
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Unable to create '%s' fs entry\n",
- ACPI_PROCESSOR_FILE_PERFORMANCE));
- else {
- entry->proc_fops = &acpi_processor_perf_fops;
- entry->write_proc = acpi_processor_write_performance;
- entry->data = acpi_driver_data(device);
- }
+ acpi_cpufreq_add_file(pr);
return_VALUE(result);
}
+static int
+acpi_cpufreq_cpu_exit (
+ struct cpufreq_policy *policy)
+{
+ struct acpi_processor *pr = performance[policy->cpu].pr;
+
+ ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_exit");
+
+ acpi_cpufreq_remove_file(pr);
+
+ return_VALUE(0);
+}
+
+
+static struct cpufreq_driver acpi_cpufreq_driver = {
+ .verify = acpi_cpufreq_verify,
+ .target = acpi_cpufreq_target,
+ .init = acpi_cpufreq_cpu_init,
+ .exit = acpi_cpufreq_cpu_exit,
+ .name = "acpi-cpufreq",
+};
+
+
static int __init
acpi_cpufreq_init (void)
{
int result = 0;
int current_state = 0;
int i = 0;
- struct acpi_processor *pr;
+ struct acpi_processor *pr = NULL;
+ struct acpi_processor_performance *perf = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_init");
@@ -579,10 +643,9 @@ acpi_cpufreq_init (void)
performance = kmalloc(NR_CPUS * sizeof(struct acpi_processor_performance), GFP_KERNEL);
if (!performance)
return_VALUE(-ENOMEM);
-
memset(performance, 0, NR_CPUS * sizeof(struct acpi_processor_performance));
- /* register struct acpi_performance performance */
+ /* register struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (cpu_online(i))
acpi_processor_register_performance(&performance[i], &pr, i);
@@ -591,11 +654,13 @@ acpi_cpufreq_init (void)
/* initialize */
for (i=0; i<NR_CPUS; i++) {
if (cpu_online(i) && performance[i].pr)
- result = acpi_processor_get_performance_info(performance[i].pr);
+ result = acpi_processor_get_performance_info(&performance[i]);
}
/* test it on one CPU */
for (i=0; i<NR_CPUS; i++) {
+ if (cpu_online(i))
+ continue;
pr = performance[i].pr;
if (pr && pr->flags.performance)
goto found_capable_cpu;
@@ -604,10 +669,11 @@ acpi_cpufreq_init (void)
goto err;
found_capable_cpu:
- current_state = pr->performance->state;
+ perf = pr->performance;
+ current_state = perf->state;
if (current_state == pr->limit.state.px) {
- result = acpi_processor_set_performance(pr, (pr->performance->state_count - 1));
+ result = acpi_processor_set_performance(perf, (perf->state_count - 1));
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Disabled P-States due to failure while switching.\n"));
result = -ENODEV;
@@ -615,7 +681,7 @@ acpi_cpufreq_init (void)
}
}
- result = acpi_processor_set_performance(pr, pr->limit.state.px);
+ result = acpi_processor_set_performance(perf, pr->limit.state.px);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Disabled P-States due to failure while switching.\n"));
result = -ENODEV;
@@ -623,7 +689,7 @@ acpi_cpufreq_init (void)
}
if (current_state != 0) {
- result = acpi_processor_set_performance(pr, current_state);
+ result = acpi_processor_set_performance(perf, current_state);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Disabled P-States due to failure while switching.\n"));
result = -ENODEV;
@@ -639,7 +705,7 @@ acpi_cpufreq_init (void)
/* error handling */
err:
- /* unregister struct acpi_performance performance */
+ /* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
performance[i].pr->flags.performance = 0;
@@ -647,9 +713,7 @@ acpi_cpufreq_init (void)
performance[i].pr = NULL;
}
}
-
kfree(performance);
-
return_VALUE(result);
}
@@ -668,7 +732,7 @@ acpi_cpufreq_exit (void)
cpufreq_unregister_driver(&acpi_cpufreq_driver);
- /* unregister struct acpi_performance performance */
+ /* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
performance[i].pr->flags.performance = 0;
@@ -682,15 +746,6 @@ acpi_cpufreq_exit (void)
return_VOID;
}
-static struct cpufreq_driver acpi_cpufreq_driver = {
- .verify = acpi_cpufreq_verify,
- .setpolicy = acpi_cpufreq_setpolicy,
- .init = acpi_cpufreq_cpu_init,
- .exit = NULL,
- .policy = NULL,
- .name = "acpi-cpufreq",
-};
-
late_initcall(acpi_cpufreq_init);
module_exit(acpi_cpufreq_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 79fa2499719b..9b87bf9bd582 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -1,5 +1,5 @@
/*
- * $Id: longhaul.c,v 1.77 2002/10/31 21:17:40 db Exp $
+ * $Id: longhaul.c,v 1.86 2003/02/12 13:59:11 davej Exp $
*
* (C) 2001 Dave Jones. <davej@suse.de>
* (C) 2002 Padraig Brady. <padraig@antefacto.com>
@@ -48,6 +48,7 @@ static int vrmrev;
/* Module parameters */
+static int prefer_slow_fsb;
static int dont_scale_voltage;
static int dont_scale_fsb;
static int current_fsb;
@@ -237,7 +238,6 @@ static unsigned int power_fsb_table[] = { 66, 100, 133, -1 };
/* fsb values to favour high fsb speed (for e.g. if lowering CPU
freq because of heat, but want to maintain highest performance possible) */
static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 };
-static unsigned int *fsb_search_table;
/* Voltage scales. Div by 1000 to get actual voltage. */
static int __initdata vrm85scales[32] = {
@@ -260,7 +260,7 @@ static int eblcr_table[32];
static int voltage_table[32];
static int highest_speed, lowest_speed; /* kHz */
static int longhaul; /* version. */
-static struct cpufreq_driver *longhaul_driver;
+static struct cpufreq_frequency_table *longhaul_table;
static int longhaul_get_cpu_fsb (void)
@@ -428,7 +428,7 @@ bad_voltage:
}
-static void __init longhaul_get_ranges (void)
+static int __init longhaul_get_ranges (void)
{
unsigned long lo, hi, invalue;
unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0;
@@ -436,6 +436,9 @@ static void __init longhaul_get_ranges (void)
50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
-1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
unsigned int fsb_table[4] = { 133, 100, -1, 66 };
+ unsigned int fsbcount = 1;
+ unsigned int i, j, k = 0;
+ static unsigned int *fsb_search_table;
switch (longhaul) {
case 1:
@@ -472,6 +475,11 @@ static void __init longhaul_get_ranges (void)
dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n",
minfsb, maxfsb);
+ fsbcount = 0;
+ for (i=0;i<4;i++) {
+ if((fsb_table[i] >= minfsb) && (fsb_table[i] <= maxfsb))
+ fsbcount++;
+ }
} else {
minfsb = maxfsb = current_fsb;
}
@@ -480,11 +488,37 @@ static void __init longhaul_get_ranges (void)
highest_speed = maxmult * maxfsb * 100;
lowest_speed = minmult * minfsb * 100;
-
dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n",
- minmult, maxmult);
+ minmult, maxmult);
dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n",
- lowest_speed, highest_speed);
+ lowest_speed, highest_speed);
+
+ longhaul_table = kmalloc((numscales * fsbcount + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
+ if(!longhaul_table)
+ return -ENOMEM;
+
+ if (prefer_slow_fsb)
+ fsb_search_table = perf_fsb_table; // yep, this is right: the last entry is preferred by cpufreq_frequency_table_* ...
+ else
+ fsb_search_table = power_fsb_table;
+
+ for (i=0; (i<4); i++) {
+ if ((fsb_search_table[i] > maxfsb) || (fsb_search_table[i] < minfsb) || (fsb_search_table[i] == -1))
+ continue;
+ for (j=0; (j<numscales); j++) {
+ if ((clock_ratio[j] > maxmult) || (clock_ratio[j] < minmult) || (clock_ratio[j] == -1))
+ continue;
+ longhaul_table[k].frequency= clock_ratio[j] * fsb_search_table[i] * 100;
+ longhaul_table[k].index = (j << 8) | (i);
+ k++;
+ }
+ }
+
+ longhaul_table[k].frequency = CPUFREQ_TABLE_END;
+ if (!k)
+ return -EINVAL;
+
+ return 0;
}
@@ -523,182 +557,43 @@ static void __init longhaul_setup_voltagescaling (unsigned long lo, unsigned lon
}
-static inline unsigned int longhaul_statecount_fsb(struct cpufreq_policy *policy, unsigned int fsb) {
- unsigned int i, count = 0;
-
- for(i=0; i<numscales; i++) {
- if ((clock_ratio[i] != -1) &&
- ((clock_ratio[i] * fsb * 100) <= policy->max) &&
- ((clock_ratio[i] * fsb * 100) >= policy->min))
- count++;
- }
-
- return count;
-}
-
-
static int longhaul_verify(struct cpufreq_policy *policy)
{
- unsigned int number_states = 0;
- unsigned int i;
- unsigned int fsb_index = 0;
- unsigned int tmpfreq = 0;
- unsigned int newmax = -1;
-
- if (!policy || !longhaul_driver)
- return -EINVAL;
-
- policy->cpu = 0;
- cpufreq_verify_within_limits(policy, lowest_speed, highest_speed);
-
- if (can_scale_fsb==1) {
- for (fsb_index=0; fsb_search_table[fsb_index]!=-1; fsb_index++)
- number_states += longhaul_statecount_fsb(policy, fsb_search_table[fsb_index]);
- } else
- number_states = longhaul_statecount_fsb(policy, current_fsb);
-
- if (number_states)
- return 0;
-
- /* get frequency closest above current policy->max */
- if (can_scale_fsb==1) {
- for (fsb_index=0; fsb_search_table[fsb_index] != -1; fsb_index++)
- for(i=0; i<numscales; i++) {
- if (clock_ratio[i] == -1)
- continue;
-
- tmpfreq = clock_ratio[i] * fsb_search_table[fsb_index];
- if ((tmpfreq > policy->max) &&
- (tmpfreq < newmax))
- newmax = tmpfreq;
- }
- } else {
- for(i=0; i<numscales; i++) {
- if (clock_ratio[i] == -1)
- continue;
-
- tmpfreq = clock_ratio[i] * current_fsb;
- if ((tmpfreq > policy->max) &&
- (tmpfreq < newmax))
- newmax = tmpfreq;
- }
- }
-
- policy->max = newmax;
-
- cpufreq_verify_within_limits(policy, lowest_speed, highest_speed);
-
- return 0;
-}
-
-
-static int longhaul_get_best_freq_for_fsb(struct cpufreq_policy *policy,
- unsigned int min_mult,
- unsigned int max_mult,
- unsigned int fsb,
- unsigned int *new_mult)
-{
- unsigned int optimal = 0;
- unsigned int found_optimal = 0;
- unsigned int i;
-
- switch(policy->policy) {
- case CPUFREQ_POLICY_POWERSAVE:
- optimal = max_mult;
- break;
- case CPUFREQ_POLICY_PERFORMANCE:
- optimal = min_mult;
- }
-
- for(i=0; i<numscales; i++) {
- unsigned int freq = fsb * clock_ratio[i] * 100;
- if ((freq > policy->max) ||
- (freq < policy->min))
- continue;
- switch(policy->policy) {
- case CPUFREQ_POLICY_POWERSAVE:
- if (clock_ratio[i] < clock_ratio[optimal]) {
- found_optimal = 1;
- optimal = i;
- }
- break;
- case CPUFREQ_POLICY_PERFORMANCE:
- if (clock_ratio[i] > clock_ratio[optimal]) {
- found_optimal = 1;
- optimal = i;
- }
- break;
- }
- }
-
- if (found_optimal) {
- *new_mult = optimal;
- return 1;
- }
- return 0;
+ return cpufreq_frequency_table_verify(policy, longhaul_table);
}
-static int longhaul_setpolicy (struct cpufreq_policy *policy)
+static int longhaul_target (struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
- unsigned int i;
- unsigned int fsb_index = 0;
- unsigned int new_fsb = 0;
- unsigned int new_clock_ratio = 0;
- unsigned int min_mult = 0;
- unsigned int max_mult = 0;
+ unsigned int table_index = 0;
+ unsigned int new_fsb = 0;
+ unsigned int new_clock_ratio = 0;
-
- if (!longhaul_driver)
+ if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
return -EINVAL;
- if (policy->policy==CPUFREQ_POLICY_PERFORMANCE)
- fsb_search_table = perf_fsb_table;
- else
- fsb_search_table = power_fsb_table;
-
- for(i=0;i<numscales;i++) {
- if (clock_ratio[max_mult] < clock_ratio[i])
- max_mult = i;
- else if (clock_ratio[min_mult] > clock_ratio[i])
- min_mult = i;
- }
-
- if (can_scale_fsb==1) {
- unsigned int found = 0;
- for (fsb_index=0; fsb_search_table[fsb_index]!=-1; fsb_index++)
- {
- if (longhaul_get_best_freq_for_fsb(policy,
- min_mult, max_mult,
- fsb_search_table[fsb_index],
- &new_clock_ratio)) {
- new_fsb = fsb_search_table[fsb_index];
- break;
- }
- }
- if (!found)
- return -EINVAL;
- } else {
- new_fsb = current_fsb;
- if (!longhaul_get_best_freq_for_fsb(policy, min_mult,
- max_mult, new_fsb, &new_clock_ratio))
- return -EINVAL;
- }
-
+ new_clock_ratio = longhaul_table[table_index].index & 0xFF;
+ new_fsb = power_fsb_table[(longhaul_table[table_index].index & 0xFF00) >> 8];
+
longhaul_setstate(new_clock_ratio, new_fsb);
return 0;
}
+static int longhaul_cpu_init (struct cpufreq_policy *policy);
-static int __init longhaul_init (void)
+static struct cpufreq_driver longhaul_driver = {
+ .verify = longhaul_verify,
+ .target = longhaul_target,
+ .init = longhaul_cpu_init,
+ .name = "longhaul",
+};
+
+static int longhaul_cpu_init (struct cpufreq_policy *policy)
{
struct cpuinfo_x86 *c = cpu_data;
- unsigned int currentspeed;
- static int currentmult;
- unsigned long lo, hi;
- int ret;
- struct cpufreq_driver *driver;
if ((c->x86_vendor != X86_VENDOR_CENTAUR) || (c->x86 !=6) )
return -ENODEV;
@@ -733,21 +628,12 @@ static int __init longhaul_init (void)
memcpy (eblcr_table, c5m_eblcr, sizeof(c5m_eblcr));
break;
- default:
- printk (KERN_INFO "longhaul: Unknown VIA CPU. Contact davej@suse.de\n");
- return -ENODEV;
}
printk (KERN_INFO "longhaul: VIA CPU detected. Longhaul version %d supported\n", longhaul);
- current_fsb = longhaul_get_cpu_fsb();
- currentmult = longhaul_get_cpu_mult();
- currentspeed = currentmult * current_fsb * 100;
-
- dprintk (KERN_INFO "longhaul: CPU currently at %dMHz (%d x %d.%d)\n",
- (currentspeed/1000), current_fsb, currentmult/10, currentmult%10);
-
if (longhaul==2 || longhaul==3) {
+ unsigned long lo, hi;
rdmsr (MSR_VIA_LONGHAUL, lo, hi);
if ((lo & (1<<0)) && (dont_scale_voltage==0))
longhaul_setup_voltagescaling (lo, hi);
@@ -756,57 +642,48 @@ static int __init longhaul_init (void)
can_scale_fsb = 1;
}
- longhaul_get_ranges();
-
- driver = kmalloc(sizeof(struct cpufreq_driver) +
- NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
- if (!driver)
+ if (longhaul_get_ranges())
return -ENOMEM;
- memset(driver, 0, sizeof(struct cpufreq_driver) +
- NR_CPUS * sizeof(struct cpufreq_policy));
- driver->policy = (struct cpufreq_policy *) (driver + 1);
+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
#ifdef CONFIG_CPU_FREQ_24_API
- driver->cpu_cur_freq[0] = currentspeed;
+ longhaul_driver.cpu_cur_freq[0] = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100);
#endif
- driver->verify = &longhaul_verify;
- driver->setpolicy = &longhaul_setpolicy;
-
- strncpy(driver->name, "longhaul", CPUFREQ_NAME_LEN);
+ return cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
+}
- driver->policy[0].cpu = 0;
- driver->policy[0].min = (unsigned int) lowest_speed;
- driver->policy[0].max = (unsigned int) highest_speed;
- driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
- driver->policy[0].cpuinfo.min_freq = (unsigned int) lowest_speed;
- driver->policy[0].cpuinfo.max_freq = (unsigned int) highest_speed;
- driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+static int __init longhaul_init (void)
+{
+ struct cpuinfo_x86 *c = cpu_data;
- longhaul_driver = driver;
+ if ((c->x86_vendor != X86_VENDOR_CENTAUR) || (c->x86 !=6) )
+ return -ENODEV;
- ret = cpufreq_register(driver);
- if (ret) {
- longhaul_driver = NULL;
- kfree(driver);
+ switch (c->x86_model) {
+ case 6 ... 7:
+ return cpufreq_register_driver(&longhaul_driver);
+ case 8:
+ return -ENODEV;
+ default:
+ printk (KERN_INFO "longhaul: Unknown VIA CPU. Contact davej@suse.de\n");
}
- return ret;
+ return -ENODEV;
}
-
static void __exit longhaul_exit (void)
{
- if (longhaul_driver) {
- cpufreq_unregister();
- kfree(longhaul_driver);
- }
+ cpufreq_unregister_driver(&longhaul_driver);
+ kfree(longhaul_table);
}
MODULE_PARM (dont_scale_fsb, "i");
MODULE_PARM (dont_scale_voltage, "i");
MODULE_PARM (current_fsb, "i");
+MODULE_PARM (prefer_slow_fsb, "i");
MODULE_AUTHOR ("Dave Jones <davej@suse.de>");
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c
index 17d2845accfd..de4b015ec9aa 100644
--- a/kernel/cpufreq.c
+++ b/kernel/cpufreq.c
@@ -350,6 +350,13 @@ static int cpufreq_add_dev (struct device * dev)
&cpufreq_driver->policy[cpu],
sizeof(struct cpufreq_policy));
+ /* 2.4-API init for this CPU */
+#ifdef CONFIG_CPU_FREQ_24_API
+ cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
+ cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
+ cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
+#endif
+
if (cpufreq_driver->target)
cpufreq_governor(cpu, CPUFREQ_GOV_START);
@@ -359,13 +366,6 @@ static int cpufreq_add_dev (struct device * dev)
return -EINVAL;
down(&cpufreq_driver_sem);
- /* 2.4-API init for this CPU */
-#ifdef CONFIG_CPU_FREQ_24_API
- cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
- cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
- cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
-#endif
-
/* prepare interface data */
cpufreq_driver->policy[cpu].intf.dev = dev;
cpufreq_driver->policy[cpu].intf.intf = &cpufreq_interface;