[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-ia64-devel] [PATCH 1/3] IA64: add cpufreq support
On Sat, Sep 27, 2008 at 10:12:03AM +0800, Yu, Ke wrote: > IA64: Add cpufreq ia64 driver > > For IA64 Platform, add cpufreq driver for ia64 cpu, implementing > cpufreq_driver->init()/ exit()/ verify()/ target()/ get() > > Signed-off-by: Yu, Ke <ke.yu@xxxxxxxxx> > Liu, Jinsong <jinsong.liu@xxxxxxxxx> Hi. About indentation. Xen/IA64 have done very badly about indent style. Some files are Linux style, others xen style. I think cpufreq.c is drived from linux so Linux style would be better. Please make it Linux style instead of 4 tab. About xen/include/acpi/cpufreq/cpufreq.h: Since it is the common file which is shared by x86 and ia64. So split out this hunk and send to xen-devel. thanks, > IA64: Add cpufreq ia64 driver > > For IA64 Platform, add cpufreq driver for ia64 cpu, implementing > cpufreq_driver->init()/ exit()/ verify()/ target()/ get() > > Signed-off-by: Yu, Ke <ke.yu@xxxxxxxxx> > Liu, Jinsong <jinsong.liu@xxxxxxxxx> > > diff -r 2aaf950e6f50 xen/arch/ia64/xen/Makefile > --- a/xen/arch/ia64/xen/Makefile Fri Sep 26 15:21:26 2008 +0800 > +++ b/xen/arch/ia64/xen/Makefile Fri Sep 26 15:37:39 2008 +0800 > @@ -1,4 +1,5 @@ > subdir-y += oprofile > +subdir-y += cpufreq > > obj-y += relocate_kernel.o > obj-y += machine_kexec.o > diff -r 2aaf950e6f50 xen/arch/ia64/xen/cpufreq/Makefile > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/xen/arch/ia64/xen/cpufreq/Makefile Fri Sep 26 15:37:39 2008 +0800 > @@ -0,0 +1,1 @@ > +obj-y += cpufreq.o > diff -r 2aaf950e6f50 xen/arch/ia64/xen/cpufreq/cpufreq.c > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/xen/arch/ia64/xen/cpufreq/cpufreq.c Fri Sep 26 15:37:39 2008 +0800 > @@ -0,0 +1,303 @@ > +/* > + * arch/ia64/kernel/cpufreq/acpi-cpufreq.c > + * This file provides the ACPI based P-state support. This > + * module works with generic cpufreq infrastructure. Most of > + * the code is based on i386 version > + * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c) > + * > + * Copyright (C) 2005 Intel Corp > + * Venkatesh Pallipadi <venkatesh.pallipadi@xxxxxxxxx> > + * > + * Sep 2008 - Liu Jinsong <jinsong.liu@xxxxxxxxx> > + * porting IPF acpi-cpufreq.c from Linux 2.6.23 to Xen hypervisor > + */ > + > +#include <xen/types.h> > +#include <xen/errno.h> > +#include <xen/delay.h> > +#include <xen/cpumask.h> > +#include <xen/sched.h> > +#include <xen/timer.h> > +#include <xen/xmalloc.h> > +#include <asm/bug.h> > +#include <asm/io.h> > +#include <asm/config.h> > +#include <asm/processor.h> > +#include <asm/percpu.h> > +#include <asm/pal.h> > +#include <acpi/acpi.h> > +#include <acpi/cpufreq/cpufreq.h> > + > +static struct acpi_cpufreq_data *drv_data[NR_CPUS]; > + > +static struct cpufreq_driver acpi_cpufreq_driver; > + > +static int > +processor_get_pstate (u32 *value) > +{ > + u64 pstate_index = 0; > + s64 retval; > + > + retval = ia64_pal_get_pstate(&pstate_index, > + PAL_GET_PSTATE_TYPE_INSTANT); > + *value = (u32) pstate_index; > + > + if (retval) > + printk("Failed to get current freq\n"); > + > + return (int)retval; > +} > + > +static unsigned int > +extract_clock (unsigned value) > +{ > + unsigned long i; > + unsigned int cpu; > + struct processor_performance *perf; > + > + cpu = smp_processor_id(); > + perf = &processor_pminfo[cpu]->perf; > + > + for (i = 0; i < perf->state_count; i++) { > + if (value == perf->states[i].status) > + return perf->states[i].core_frequency; > + } > + return perf->states[i-1].core_frequency; > +} > + > +static void > +processor_get_freq (void *data) > +{ > + unsigned int *freq = data; > + int ret = 0; > + u32 value = 0; > + unsigned int clock_freq; > + > + ret = processor_get_pstate(&value); > + if (ret) { > + *freq = 0; > + return; > + } > + > + clock_freq = extract_clock(value); > + *freq = (clock_freq*1000); > + return; > +} > + > +static unsigned int > +acpi_cpufreq_get (unsigned int cpu) > +{ > + unsigned int freq; > + > + if (!cpu_online(cpu)) > + return 0; > + > + if (cpu == smp_processor_id()) > + processor_get_freq((void*)&freq); > + else > + smp_call_function_single(cpu, processor_get_freq, (void *)&freq, 0, > 1); > + > + return freq; > +} > + > +static void > +processor_set_pstate (void *data) > +{ > + u32 *value = data; > + s64 retval; > + > + retval = ia64_pal_set_pstate((u64)*value); > + > + if (retval) > + *value = 1; > + else > + *value = 0; > +} > + > +static int > +processor_set_freq (struct acpi_cpufreq_data *data, > + struct cpufreq_policy *policy, int state) > +{ > + u32 value = 0; > + unsigned int cpu = policy->cpu; > + > + if (!cpu_online(cpu)) > + return -ENODEV; > + > + if (state == data->acpi_data->state) { > + if (unlikely(policy->resume)) { > + printk(KERN_INFO"Called after resume, resetting to P%d\n", > state); > + policy->resume = 0; > + } else { > + printk(KERN_DEBUG"Already at target state (P%d)\n", state); > + return 0; > + } > + } > + > + value = (u32) data->acpi_data->states[state].control; > + > + if (cpu == smp_processor_id()) > + processor_set_pstate((void *)&value); > + else > + smp_call_function_single(cpu, processor_set_pstate, > + (void *)&value, 0, 1); > + > + if (value) { > + printk(KERN_WARNING "Transition failed\n"); > + return -ENODEV; > + } > + > + cpufreq_statistic_update(cpu, data->acpi_data->state, state); > + > + data->acpi_data->state = state; > + > + return 0; > +} > + > +static int > +acpi_cpufreq_target (struct cpufreq_policy *policy, > + unsigned int target_freq, unsigned int relation) > +{ > + struct acpi_cpufreq_data *data = drv_data[policy->cpu]; > + unsigned int next_state = 0; > + unsigned int result = 0; > + > + result = cpufreq_frequency_table_target(policy, > + data->freq_table, target_freq, relation, &next_state); > + if (result) > + return (result); > + > + result = processor_set_freq(data, policy, next_state); > + > + return (result); > +} > + > +static int > +acpi_cpufreq_verify (struct cpufreq_policy *policy) > +{ > + struct acpi_cpufreq_data *data = drv_data[policy->cpu]; > + struct processor_performance *perf = > &processor_pminfo[policy->cpu]->perf; > + > + if (!policy || !data) > + return -EINVAL; > + > + cpufreq_verify_within_limits(policy, 0, > + perf->states[perf->platform_limit].core_frequency * 1000); > + > + return cpufreq_frequency_table_verify(policy, data->freq_table); > +} > + > +static int > +acpi_cpufreq_cpu_init (struct cpufreq_policy *policy) > +{ > + unsigned int i; > + unsigned int cpu = policy->cpu; > + unsigned int result = 0; > + struct acpi_cpufreq_data *data; > + > + data = xmalloc(struct acpi_cpufreq_data); > + if (!data) > + return -ENOMEM; > + memset(data, 0, sizeof(struct acpi_cpufreq_data)); > + > + drv_data[cpu] = data; > + > + data->acpi_data = &processor_pminfo[cpu]->perf; > + > + /* capability check */ > + if (data->acpi_data->state_count <= 1) { > + printk(KERN_WARNING "P-States\n"); > + result = -ENODEV; > + goto err_unreg; > + } > + > + if ((data->acpi_data->control_register.space_id != > + ACPI_ADR_SPACE_FIXED_HARDWARE) || > + (data->acpi_data->status_register.space_id != > + ACPI_ADR_SPACE_FIXED_HARDWARE)) { > + result = -ENODEV; > + goto err_unreg; > + } > + > + data->freq_table = xmalloc_array(struct cpufreq_frequency_table, > + (data->acpi_data->state_count + 1)); > + if (!data->freq_table) { > + result = -ENOMEM; > + goto err_unreg; > + } > + > + /* detect transition latency */ > + policy->cpuinfo.transition_latency = 0; > + for (i=0; i<data->acpi_data->state_count; i++) { > + if ((data->acpi_data->states[i].transition_latency * 1000) > > + policy->cpuinfo.transition_latency) { > + policy->cpuinfo.transition_latency = > + data->acpi_data->states[i].transition_latency * 1000; > + } > + } > + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; > + > + policy->cur = acpi_cpufreq_get(policy->cpu); > + printk(KERN_INFO "Current freq of CPU %u is %u\n", cpu, policy->cur); > + > + /* table init */ > + for (i = 0; i <= data->acpi_data->state_count; i++) { > + data->freq_table[i].index = i; > + if (i < data->acpi_data->state_count) { > + data->freq_table[i].frequency = > + data->acpi_data->states[i].core_frequency * 1000; > + } else { > + data->freq_table[i].frequency = CPUFREQ_TABLE_END; > + } > + } > + > + result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); > + if (result) > + goto err_freqfree; > + > + data->acpi_data->state = 0; > + policy->resume = 1; > + > + return result; > + > + err_freqfree: > + xfree(data->freq_table); > + err_unreg: > + xfree(data); > + drv_data[cpu] = NULL; > + > + return result; > +} > + > +static int > +acpi_cpufreq_cpu_exit (struct cpufreq_policy *policy) > +{ > + struct acpi_cpufreq_data *data = drv_data[policy->cpu]; > + > + if (data) { > + drv_data[policy->cpu] = NULL; > + xfree(data->freq_table); > + xfree(data); > + } > + > + return 0; > +} > + > +static struct cpufreq_driver acpi_cpufreq_driver = { > + .verify = acpi_cpufreq_verify, > + .target = acpi_cpufreq_target, > + .get = acpi_cpufreq_get, > + .init = acpi_cpufreq_cpu_init, > + .exit = acpi_cpufreq_cpu_exit, > +}; > + > +static int __init cpufreq_driver_init(void) > +{ > + int ret = 0; > + > + if (cpufreq_controller == FREQCTL_xen) > + ret = cpufreq_register_driver(&acpi_cpufreq_driver); > + > + return ret; > +} > +__initcall(cpufreq_driver_init); > diff -r 2aaf950e6f50 xen/include/acpi/cpufreq/cpufreq.h > --- a/xen/include/acpi/cpufreq/cpufreq.h Fri Sep 26 15:21:26 2008 +0800 > +++ b/xen/include/acpi/cpufreq/cpufreq.h Fri Sep 26 15:37:39 2008 +0800 > @@ -24,8 +24,10 @@ > struct acpi_cpufreq_data { > struct processor_performance *acpi_data; > struct cpufreq_frequency_table *freq_table; > +#ifdef CONFIG_X86 > unsigned int max_freq; > unsigned int cpu_feature; > +#endif > }; > > struct cpufreq_cpuinfo { > > > -- yamahata _______________________________________________ Xen-ia64-devel mailing list Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-ia64-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |