From cf9b129e5db461835f8b593a0c39182abba0bccc Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 28 Jan 2004 07:34:24 -0500 Subject: [PATCH] [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] --- arch/i386/kernel/cpu/cpufreq/acpi.c | 173 ++++++++++++---------------- drivers/acpi/processor.c | 50 ++++++-- include/acpi/processor.h | 4 +- 3 files changed, 116 insertions(+), 111 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c index f894ef7d3c18a..e38ddb4063813 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c @@ -52,7 +52,7 @@ MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); MODULE_LICENSE("GPL"); -static struct acpi_processor_performance *performance; +static struct acpi_processor_performance *performance[NR_CPUS]; static int @@ -188,9 +188,6 @@ acpi_processor_get_performance_states ( else perf->state_count = pss->package.count; - if (perf->state_count > 1) - perf->pr->flags.performance = 1; - for (i = 0; i < perf->state_count; i++) { struct acpi_processor_px *px = &(perf->states[i]); @@ -217,6 +214,12 @@ acpi_processor_get_performance_states ( (u32) px->bus_master_latency, (u32) px->control, (u32) px->status)); + + if (!px->core_frequency) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "core_frequency is 0\n")); + result = -EFAULT; + goto end; + } } end: @@ -279,22 +282,12 @@ acpi_processor_set_performance ( if (!perf || !perf->pr) return_VALUE(-EINVAL); - if (!perf->pr->flags.performance) - return_VALUE(-ENODEV); - if (state >= perf->state_count) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid target state (P%d)\n", state)); 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) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Already at target state (P%d)\n", state)); @@ -306,8 +299,8 @@ acpi_processor_set_performance ( /* cpufreq frequency struct */ cpufreq_freqs.cpu = perf->pr->id; - cpufreq_freqs.old = perf->states[perf->state].core_frequency; - cpufreq_freqs.new = perf->states[state].core_frequency; + cpufreq_freqs.old = perf->states[perf->state].core_frequency * 1000; + cpufreq_freqs.new = perf->states[state].core_frequency * 1000; /* notify cpufreq */ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); @@ -401,7 +394,7 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) if (!pr) goto end; - if (!pr->flags.performance || !pr->performance) { + if (!pr->performance) { seq_puts(seq, "\n"); goto end; } @@ -437,14 +430,20 @@ acpi_processor_write_performance ( loff_t *data) { 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'}; unsigned int new_state = 0; struct cpufreq_policy policy; 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); if (copy_from_user(state_string, buffer, count)) @@ -453,10 +452,14 @@ acpi_processor_write_performance ( state_string[count] = '\0'; new_state = simple_strtoul(state_string, NULL, 0); + if (new_state >= perf->state_count) + return_VALUE(-EINVAL); + cpufreq_get_policy(&policy, 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); if (result) @@ -522,14 +525,14 @@ acpi_cpufreq_target ( unsigned int target_freq, 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 result = 0; ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy"); result = cpufreq_frequency_table_target(policy, - &perf->freq_table[perf->pr->limit.state.px], + perf->freq_table, target_freq, relation, &next_state); @@ -547,17 +550,17 @@ acpi_cpufreq_verify ( struct cpufreq_policy *policy) { 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"); result = cpufreq_frequency_table_verify(policy, - &perf->freq_table[perf->pr->limit.state.px]); + perf->freq_table); cpufreq_verify_within_limits( policy, 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); } @@ -601,35 +604,43 @@ 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]; - struct acpi_device *device; + struct acpi_processor_performance *perf; unsigned int result = 0; 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; - if (!pr) - return_VALUE(-ENODEV); + result = acpi_processor_register_performance(perf, cpu); + if (result) + goto err_free; result = acpi_processor_get_performance_info(perf); if (result) - return_VALUE(-ENODEV); + goto err_unreg; /* capability check */ - if (!pr->flags.performance) - return_VALUE(-ENODEV); + if (perf->state_count <= 1) + goto err_unreg; /* detect transition latency */ policy->cpuinfo.transition_latency = 0; - for (i=0;istate_count;i++) { + for (i=0; istate_count; i++) { if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; } 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 */ for (i=0; i<=perf->state_count; i++) @@ -643,19 +654,25 @@ acpi_cpufreq_cpu_init ( 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)) - device = NULL; - - 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: CPU%u - ACPI performance management activated.\n", + cpu); + for (i = 0; i < perf->state_count; i++) printk(KERN_INFO "cpufreq: %cP%d: %d MHz, %d mW, %d uS\n", - (i == pr->performance->state?'*':' '), i, - (u32) pr->performance->states[i].core_frequency, - (u32) pr->performance->states[i].power, - (u32) pr->performance->states[i].transition_latency); + (i == perf->state?'*':' '), i, + (u32) perf->states[i].core_frequency, + (u32) perf->states[i].power, + (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); } @@ -664,11 +681,16 @@ static int acpi_cpufreq_cpu_exit ( 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_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); } @@ -688,41 +710,10 @@ static int __init acpi_cpufreq_init (void) { int result = 0; - int i = 0; - struct acpi_processor *pr = NULL; 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; iflags.performance = 0; - performance[i].pr->performance = NULL; - performance[i].pr = NULL; - } - } - kfree(performance); - } return_VALUE(result); } @@ -731,27 +722,9 @@ acpi_cpufreq_init (void) static void __exit acpi_cpufreq_exit (void) { - int i = 0; - ACPI_FUNCTION_TRACE("acpi_cpufreq_exit"); - for (i=0; iflags.performance = 0; - } - - cpufreq_unregister_driver(&acpi_cpufreq_driver); - - /* unregister struct acpi_processor_performance performance */ - for (i=0; iflags.performance = 0; - performance[i].pr->performance = NULL; - performance[i].pr = NULL; - } - } - - kfree(performance); + cpufreq_unregister_driver(&acpi_cpufreq_driver); return_VOID; } diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index 79bda68eb1407..5e2d29669b871 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -3,6 +3,7 @@ * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh + * Copyright (C) 2004 Dominik Brodowski * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -55,7 +56,6 @@ #define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" #define ACPI_PROCESSOR_FILE_POWER "power" -#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" #define ACPI_PROCESSOR_FILE_THROTTLING "throttling" #define ACPI_PROCESSOR_FILE_LIMIT "limit" #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 @@ -827,7 +827,6 @@ acpi_processor_get_platform_limit ( return_VALUE(0); } -EXPORT_SYMBOL(acpi_processor_get_platform_limit); static int acpi_processor_ppc_has_changed( @@ -860,9 +859,10 @@ static void acpi_processor_ppc_exit(void) { int acpi_processor_register_performance ( struct acpi_processor_performance * performance, - struct acpi_processor ** pr, unsigned int cpu) { + struct acpi_processor *pr; + ACPI_FUNCTION_TRACE("acpi_processor_register_performance"); if (!acpi_processor_ppc_is_init) @@ -870,26 +870,56 @@ acpi_processor_register_performance ( down(&performance_sem); - *pr = processors[cpu]; - if (!*pr) { + pr = processors[cpu]; + if (!pr) { up(&performance_sem); return_VALUE(-ENODEV); } - if ((*pr)->performance) { + if (pr->performance) { up(&performance_sem); return_VALUE(-EBUSY); } - (*pr)->performance = performance; - performance->pr = *pr; + pr->performance = performance; + performance->pr = pr; up(&performance_sem); - return 0; + return_VALUE(0); } 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 */ #else /* !CONFIG_CPU_FREQ */ @@ -1399,7 +1429,7 @@ acpi_processor_get_limit_info ( if (!pr) return_VALUE(-EINVAL); - if (pr->flags.performance || pr->flags.throttling) + if (pr->flags.throttling) pr->flags.limit = 1; return_VALUE(0); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index ade6751584d6b..f693a665b00a5 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -135,7 +135,9 @@ struct acpi_processor { extern int acpi_processor_register_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); #endif -- 2.53.0