Commit cf9b129e authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Len Brown

[ACPI] acpi-cpufreq fixups from Dominik Brodowski

- remove unnecessary usage of flags.performance
- remove double check of _PPC in acpi-cpufreq driver as it's handled in
  drivers/acpi/processor.c already
- remove unneeded EXPORT_SYMBOL
- allocation of memory only for probed CPUs
- add unregistration function to the core
- fix OOPS when PST has core_frequency values of zero
- fix cpufreq_get() output
- fix /proc/acpi/processor/*/performance write support [deprecated]
parent e0654edf
...@@ -52,7 +52,7 @@ MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); ...@@ -52,7 +52,7 @@ MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct acpi_processor_performance *performance; static struct acpi_processor_performance *performance[NR_CPUS];
static int static int
...@@ -188,9 +188,6 @@ acpi_processor_get_performance_states ( ...@@ -188,9 +188,6 @@ acpi_processor_get_performance_states (
else else
perf->state_count = pss->package.count; perf->state_count = pss->package.count;
if (perf->state_count > 1)
perf->pr->flags.performance = 1;
for (i = 0; i < perf->state_count; i++) { for (i = 0; i < perf->state_count; i++) {
struct acpi_processor_px *px = &(perf->states[i]); struct acpi_processor_px *px = &(perf->states[i]);
...@@ -217,6 +214,12 @@ acpi_processor_get_performance_states ( ...@@ -217,6 +214,12 @@ acpi_processor_get_performance_states (
(u32) px->bus_master_latency, (u32) px->bus_master_latency,
(u32) px->control, (u32) px->control,
(u32) px->status)); (u32) px->status));
if (!px->core_frequency) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "core_frequency is 0\n"));
result = -EFAULT;
goto end;
}
} }
end: end:
...@@ -279,22 +282,12 @@ acpi_processor_set_performance ( ...@@ -279,22 +282,12 @@ acpi_processor_set_performance (
if (!perf || !perf->pr) if (!perf || !perf->pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
if (!perf->pr->flags.performance)
return_VALUE(-ENODEV);
if (state >= perf->state_count) { if (state >= perf->state_count) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid target state (P%d)\n", state)); "Invalid target state (P%d)\n", state));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
if (state < perf->pr->performance_platform_limit) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Platform limit (P%d) overrides target state (P%d)\n",
perf->pr->performance_platform_limit, state));
return_VALUE(-ENODEV);
}
if (state == perf->state) { if (state == perf->state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Already at target state (P%d)\n", state)); "Already at target state (P%d)\n", state));
...@@ -306,8 +299,8 @@ acpi_processor_set_performance ( ...@@ -306,8 +299,8 @@ acpi_processor_set_performance (
/* cpufreq frequency struct */ /* cpufreq frequency struct */
cpufreq_freqs.cpu = perf->pr->id; cpufreq_freqs.cpu = perf->pr->id;
cpufreq_freqs.old = perf->states[perf->state].core_frequency; cpufreq_freqs.old = perf->states[perf->state].core_frequency * 1000;
cpufreq_freqs.new = perf->states[state].core_frequency; cpufreq_freqs.new = perf->states[state].core_frequency * 1000;
/* notify cpufreq */ /* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
...@@ -401,7 +394,7 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) ...@@ -401,7 +394,7 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
if (!pr) if (!pr)
goto end; goto end;
if (!pr->flags.performance || !pr->performance) { if (!pr->performance) {
seq_puts(seq, "<not supported>\n"); seq_puts(seq, "<not supported>\n");
goto end; goto end;
} }
...@@ -437,14 +430,20 @@ acpi_processor_write_performance ( ...@@ -437,14 +430,20 @@ acpi_processor_write_performance (
loff_t *data) loff_t *data)
{ {
int result = 0; int result = 0;
struct acpi_processor *pr = (struct acpi_processor *) data; struct seq_file *m = (struct seq_file *) file->private_data;
struct acpi_processor *pr = (struct acpi_processor *) m->private;
struct acpi_processor_performance *perf;
char state_string[12] = {'\0'}; char state_string[12] = {'\0'};
unsigned int new_state = 0; unsigned int new_state = 0;
struct cpufreq_policy policy; struct cpufreq_policy policy;
ACPI_FUNCTION_TRACE("acpi_processor_write_performance"); ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
if (!pr || !pr->performance || (count > sizeof(state_string) - 1)) if (!pr || (count > sizeof(state_string) - 1))
return_VALUE(-EINVAL);
perf = pr->performance;
if (!perf)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
if (copy_from_user(state_string, buffer, count)) if (copy_from_user(state_string, buffer, count))
...@@ -453,10 +452,14 @@ acpi_processor_write_performance ( ...@@ -453,10 +452,14 @@ acpi_processor_write_performance (
state_string[count] = '\0'; state_string[count] = '\0';
new_state = simple_strtoul(state_string, NULL, 0); new_state = simple_strtoul(state_string, NULL, 0);
if (new_state >= perf->state_count)
return_VALUE(-EINVAL);
cpufreq_get_policy(&policy, pr->id); cpufreq_get_policy(&policy, pr->id);
policy.cpu = pr->id; policy.cpu = pr->id;
policy.max = pr->performance->states[new_state].core_frequency * 1000; policy.min = perf->states[new_state].core_frequency * 1000;
policy.max = perf->states[new_state].core_frequency * 1000;
result = cpufreq_set_policy(&policy); result = cpufreq_set_policy(&policy);
if (result) if (result)
...@@ -522,14 +525,14 @@ acpi_cpufreq_target ( ...@@ -522,14 +525,14 @@ acpi_cpufreq_target (
unsigned int target_freq, unsigned int target_freq,
unsigned int relation) unsigned int relation)
{ {
struct acpi_processor_performance *perf = &performance[policy->cpu]; struct acpi_processor_performance *perf = performance[policy->cpu];
unsigned int next_state = 0; unsigned int next_state = 0;
unsigned int result = 0; unsigned int result = 0;
ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy"); ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy");
result = cpufreq_frequency_table_target(policy, result = cpufreq_frequency_table_target(policy,
&perf->freq_table[perf->pr->limit.state.px], perf->freq_table,
target_freq, target_freq,
relation, relation,
&next_state); &next_state);
...@@ -547,17 +550,17 @@ acpi_cpufreq_verify ( ...@@ -547,17 +550,17 @@ acpi_cpufreq_verify (
struct cpufreq_policy *policy) struct cpufreq_policy *policy)
{ {
unsigned int result = 0; unsigned int result = 0;
struct acpi_processor_performance *perf = &performance[policy->cpu]; struct acpi_processor_performance *perf = performance[policy->cpu];
ACPI_FUNCTION_TRACE("acpi_cpufreq_verify"); ACPI_FUNCTION_TRACE("acpi_cpufreq_verify");
result = cpufreq_frequency_table_verify(policy, result = cpufreq_frequency_table_verify(policy,
&perf->freq_table[perf->pr->limit.state.px]); perf->freq_table);
cpufreq_verify_within_limits( cpufreq_verify_within_limits(
policy, policy,
perf->states[perf->state_count - 1].core_frequency * 1000, perf->states[perf->state_count - 1].core_frequency * 1000,
perf->states[perf->pr->limit.state.px].core_frequency * 1000); perf->states[0].core_frequency * 1000);
return_VALUE(result); return_VALUE(result);
} }
...@@ -601,35 +604,43 @@ acpi_cpufreq_cpu_init ( ...@@ -601,35 +604,43 @@ acpi_cpufreq_cpu_init (
{ {
unsigned int i; unsigned int i;
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct acpi_processor *pr = NULL; struct acpi_processor_performance *perf;
struct acpi_processor_performance *perf = &performance[policy->cpu];
struct acpi_device *device;
unsigned int result = 0; unsigned int result = 0;
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init"); ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
acpi_processor_register_performance(perf, &pr, cpu); perf = kmalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL);
if (!perf)
return_VALUE(-ENOMEM);
memset(perf, 0, sizeof(struct acpi_processor_performance));
performance[cpu] = perf;
pr = performance[cpu].pr; result = acpi_processor_register_performance(perf, cpu);
if (!pr) if (result)
return_VALUE(-ENODEV); goto err_free;
result = acpi_processor_get_performance_info(perf); result = acpi_processor_get_performance_info(perf);
if (result) if (result)
return_VALUE(-ENODEV); goto err_unreg;
/* capability check */ /* capability check */
if (!pr->flags.performance) if (perf->state_count <= 1)
return_VALUE(-ENODEV); goto err_unreg;
/* detect transition latency */ /* detect transition latency */
policy->cpuinfo.transition_latency = 0; policy->cpuinfo.transition_latency = 0;
for (i=0;i<perf->state_count;i++) { for (i=0; i<perf->state_count; i++) {
if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
} }
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000;
/*
* The current speed is unknown and not detectable by ACPI... argh! Assume
* it's P0, it will be set to this value later during initialization.
*/
policy->cur = perf->states[0].core_frequency * 1000;
/* table init */ /* table init */
for (i=0; i<=perf->state_count; i++) for (i=0; i<=perf->state_count; i++)
...@@ -643,19 +654,25 @@ acpi_cpufreq_cpu_init ( ...@@ -643,19 +654,25 @@ acpi_cpufreq_cpu_init (
result = cpufreq_frequency_table_cpuinfo(policy, &perf->freq_table[0]); result = cpufreq_frequency_table_cpuinfo(policy, &perf->freq_table[0]);
acpi_cpufreq_add_file(pr); acpi_cpufreq_add_file(perf->pr);
if (acpi_bus_get_device(pr->handle, &device)) printk(KERN_INFO "cpufreq: CPU%u - ACPI performance management activated.\n",
device = NULL; cpu);
for (i = 0; i < perf->state_count; i++)
printk(KERN_INFO "cpufreq: %s - ACPI performance management activated.\n",
device ? acpi_device_bid(device) : "CPU??");
for (i = 0; i < pr->performance->state_count; i++)
printk(KERN_INFO "cpufreq: %cP%d: %d MHz, %d mW, %d uS\n", printk(KERN_INFO "cpufreq: %cP%d: %d MHz, %d mW, %d uS\n",
(i == pr->performance->state?'*':' '), i, (i == perf->state?'*':' '), i,
(u32) pr->performance->states[i].core_frequency, (u32) perf->states[i].core_frequency,
(u32) pr->performance->states[i].power, (u32) perf->states[i].power,
(u32) pr->performance->states[i].transition_latency); (u32) perf->states[i].transition_latency);
return_VALUE(result);
err_unreg:
acpi_processor_unregister_performance(perf, cpu);
err_free:
kfree(perf);
performance[cpu] = NULL;
return_VALUE(result); return_VALUE(result);
} }
...@@ -664,11 +681,16 @@ static int ...@@ -664,11 +681,16 @@ static int
acpi_cpufreq_cpu_exit ( acpi_cpufreq_cpu_exit (
struct cpufreq_policy *policy) struct cpufreq_policy *policy)
{ {
struct acpi_processor *pr = performance[policy->cpu].pr; struct acpi_processor_performance *perf = performance[policy->cpu];
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_exit"); ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_exit");
acpi_cpufreq_remove_file(pr); if (perf) {
acpi_cpufreq_remove_file(perf->pr);
performance[policy->cpu] = NULL;
acpi_processor_unregister_performance(perf, policy->cpu);
kfree(perf);
}
return_VALUE(0); return_VALUE(0);
} }
...@@ -688,41 +710,10 @@ static int __init ...@@ -688,41 +710,10 @@ static int __init
acpi_cpufreq_init (void) acpi_cpufreq_init (void)
{ {
int result = 0; int result = 0;
int i = 0;
struct acpi_processor *pr = NULL;
ACPI_FUNCTION_TRACE("acpi_cpufreq_init"); ACPI_FUNCTION_TRACE("acpi_cpufreq_init");
/* alloc memory */
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_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (cpu_online(i))
acpi_processor_register_performance(&performance[i], &pr, i);
}
/* initialize */
for (i=0; i<NR_CPUS; i++) {
if (cpu_online(i) && performance[i].pr)
result = acpi_processor_get_performance_info(&performance[i]);
}
result = cpufreq_register_driver(&acpi_cpufreq_driver); result = cpufreq_register_driver(&acpi_cpufreq_driver);
if (result) {
/* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
performance[i].pr->flags.performance = 0;
performance[i].pr->performance = NULL;
performance[i].pr = NULL;
}
}
kfree(performance);
}
return_VALUE(result); return_VALUE(result);
} }
...@@ -731,27 +722,9 @@ acpi_cpufreq_init (void) ...@@ -731,27 +722,9 @@ acpi_cpufreq_init (void)
static void __exit static void __exit
acpi_cpufreq_exit (void) acpi_cpufreq_exit (void)
{ {
int i = 0;
ACPI_FUNCTION_TRACE("acpi_cpufreq_exit"); ACPI_FUNCTION_TRACE("acpi_cpufreq_exit");
for (i=0; i<NR_CPUS; i++) { cpufreq_unregister_driver(&acpi_cpufreq_driver);
if (performance[i].pr)
performance[i].pr->flags.performance = 0;
}
cpufreq_unregister_driver(&acpi_cpufreq_driver);
/* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
performance[i].pr->flags.performance = 0;
performance[i].pr->performance = NULL;
performance[i].pr = NULL;
}
}
kfree(performance);
return_VOID; return_VOID;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* *
...@@ -55,7 +56,6 @@ ...@@ -55,7 +56,6 @@
#define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_FILE_INFO "info" #define ACPI_PROCESSOR_FILE_INFO "info"
#define ACPI_PROCESSOR_FILE_POWER "power" #define ACPI_PROCESSOR_FILE_POWER "power"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" #define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
#define ACPI_PROCESSOR_FILE_LIMIT "limit" #define ACPI_PROCESSOR_FILE_LIMIT "limit"
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
...@@ -827,7 +827,6 @@ acpi_processor_get_platform_limit ( ...@@ -827,7 +827,6 @@ acpi_processor_get_platform_limit (
return_VALUE(0); return_VALUE(0);
} }
EXPORT_SYMBOL(acpi_processor_get_platform_limit);
static int acpi_processor_ppc_has_changed( static int acpi_processor_ppc_has_changed(
...@@ -860,9 +859,10 @@ static void acpi_processor_ppc_exit(void) { ...@@ -860,9 +859,10 @@ static void acpi_processor_ppc_exit(void) {
int int
acpi_processor_register_performance ( acpi_processor_register_performance (
struct acpi_processor_performance * performance, struct acpi_processor_performance * performance,
struct acpi_processor ** pr,
unsigned int cpu) unsigned int cpu)
{ {
struct acpi_processor *pr;
ACPI_FUNCTION_TRACE("acpi_processor_register_performance"); ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
if (!acpi_processor_ppc_is_init) if (!acpi_processor_ppc_is_init)
...@@ -870,26 +870,56 @@ acpi_processor_register_performance ( ...@@ -870,26 +870,56 @@ acpi_processor_register_performance (
down(&performance_sem); down(&performance_sem);
*pr = processors[cpu]; pr = processors[cpu];
if (!*pr) { if (!pr) {
up(&performance_sem); up(&performance_sem);
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
if ((*pr)->performance) { if (pr->performance) {
up(&performance_sem); up(&performance_sem);
return_VALUE(-EBUSY); return_VALUE(-EBUSY);
} }
(*pr)->performance = performance; pr->performance = performance;
performance->pr = *pr; performance->pr = pr;
up(&performance_sem); up(&performance_sem);
return 0; return_VALUE(0);
} }
EXPORT_SYMBOL(acpi_processor_register_performance); EXPORT_SYMBOL(acpi_processor_register_performance);
void
acpi_processor_unregister_performance (
struct acpi_processor_performance * performance,
unsigned int cpu)
{
struct acpi_processor *pr;
ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
if (!acpi_processor_ppc_is_init)
return_VOID;
down(&performance_sem);
pr = processors[cpu];
if (!pr) {
up(&performance_sem);
return_VOID;
}
pr->performance = NULL;
performance->pr = NULL;
up(&performance_sem);
return_VOID;
}
EXPORT_SYMBOL(acpi_processor_unregister_performance);
/* for the rest of it, check arch/i386/kernel/cpu/cpufreq/acpi.c */ /* for the rest of it, check arch/i386/kernel/cpu/cpufreq/acpi.c */
#else /* !CONFIG_CPU_FREQ */ #else /* !CONFIG_CPU_FREQ */
...@@ -1399,7 +1429,7 @@ acpi_processor_get_limit_info ( ...@@ -1399,7 +1429,7 @@ acpi_processor_get_limit_info (
if (!pr) if (!pr)
return_VALUE(-EINVAL); return_VALUE(-EINVAL);
if (pr->flags.performance || pr->flags.throttling) if (pr->flags.throttling)
pr->flags.limit = 1; pr->flags.limit = 1;
return_VALUE(0); return_VALUE(0);
......
...@@ -135,7 +135,9 @@ struct acpi_processor { ...@@ -135,7 +135,9 @@ struct acpi_processor {
extern int acpi_processor_register_performance ( extern int acpi_processor_register_performance (
struct acpi_processor_performance * performance, struct acpi_processor_performance * performance,
struct acpi_processor ** pr, unsigned int cpu);
extern void acpi_processor_unregister_performance (
struct acpi_processor_performance * performance,
unsigned int cpu); unsigned int cpu);
#endif #endif
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