cpufreq: Add sfi based cpufreq driver support
PATCH v2 1/1 cpufreq: Add sfi based cpufreq driver support
This adds the sfi based cpu freq driver for some of the Intel's Silver Mont based atom architectures like Merrifield and Moorfield (intel-mid)
--- drivers/cpufreq/Kconfig.x86 | 10 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/sfi-cpufreq.c | 332 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 drivers/cpufreq/sfi-cpufreq.c
drivers/cpufreq/Kconfig.x86 +10 -0
@@ -57,6 +57,16 @@ config X86_ACPI_CPUFREQ_CPB By enabling this option the acpi_cpufreq driver provides the old entry in addition to the new boost ones, for compatibility reasons. +config X86_SFI_CPUFREQ + tristate "SFI Processor P-States driver" + depends on X86_INTEL_MID && SFI + help + This adds a CPUFreq driver for some Silver Mont based Intel + Atom platforms (like INTEL_MID) which utilizes the SFI based + processor performance states. + + If in doubt, say N. + config ELAN_CPUFREQ tristate "AMD Elan SC400 and SC410" depends on MELAN
drivers/cpufreq/Makefile +1 -0
@@ -41,6 +41,7 @@ obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o obj-$(CONFIG_X86_INTEL_PSTATE) += intel_pstate.o obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o +obj-$(CONFIG_X86_SFI_CPUFREQ) += sfi-cpufreq.o ################################################################################## # ARM SoC drivers
drivers/cpufreq/sfi-cpufreq.c new file +332 -0
332 lines not on this page · raw message
Signature · 4 lines
1.7.9.5 --
Viresh Kumar
maintainerQuoted 7 lines · Srinidhi Kasagar
This adds the sfi based cpu freq driver for some of the Intel's Silver Mont based atom architectures like Merrifield and Moorfield (intel-mid)
Signed-off-by Rudramuni, Vishwesh M <[email protected]>Signed-off-by Srinidhi Kasagar <[email protected]>---
Always good to let people know what changed from previous version.
drivers/cpufreq/sfi-cpufreq.c line 179
Quoted 9 lines
drivers/cpufreq/sfi-cpufreq.c +8
-0+static unsigned int get_cur_freq_on_cpu (unsigned int cpu) +{ +struct sfi_cpufreq_data *data =per_cpu (drv_data, cpu); +unsigned int cached_freq; + +pr_debug ("get_cur_freq_on_cpu (%d)\n" , cpu); + + cached_freq = data->freq_table[data->sfi_data->state].frequency;
Are you sure cached_freq is used at all ? And if not, then you don't need to pass 'data' in exact_freq(), just get it there..
Quoted 11 lines
drivers/cpufreq/sfi-cpufreq.c +11
-0+return extract_freq (get_cur_val (cpumask_of (cpu)), data); + +} + +static int sfi_cpufreq_target (struct cpufreq_policy *policy, +unsigned int index) +{ +struct sfi_cpufreq_data *data =per_cpu (drv_data, policy->cpu); +struct sfi_processor_performance *perf; +unsigned int next_perf_state =0 ;/* Index into perf table */ +u32 lo, hi;
drivers/cpufreq/sfi-cpufreq.c line 201
Quoted 10 lines
drivers/cpufreq/sfi-cpufreq.c +10
-0+ + perf = data->sfi_data; + next_perf_state = data->freq_table[index].driver_data; + +rdmsr_on_cpu (policy->cpu,MSR_IA32_PERF_CTL , &lo, &hi); + lo = (lo & ~INTEL_MSR_RANGE ) | + ((u32 ) perf->states[next_perf_state].control &INTEL_MSR_RANGE ); +wrmsr_on_cpu (policy->cpu,MSR_IA32_PERF_CTL , lo, hi); + + perf->state = next_perf_state;
This looks much better now :)
drivers/cpufreq/sfi-cpufreq.c line 213
Quoted 11 lines
drivers/cpufreq/sfi-cpufreq.c +11
-0+return 0 ; +} + +static int sfi_cpufreq_cpu_init (struct cpufreq_policy *policy) +{ +unsigned int i, result =0 , valid_states =0 ; +unsigned int cpu = policy->cpu; +struct sfi_cpufreq_data *data; +struct sfi_processor_performance *perf; + +pr_debug ("%s: CPU:%d\n" , __func__, policy->cpu);
Use cpu here instead of policy->cpu ?
Quoted 40 lines
drivers/cpufreq/sfi-cpufreq.c +40
-0+ + data =kzalloc (sizeof (*data),GFP_KERNEL ); +if (!data) +return -ENOMEM ; + + data->sfi_data =per_cpu_ptr (sfi_perf_data, cpu); +per_cpu (drv_data, cpu) = data; + + result =sfi_processor_register_performance (data->sfi_data); +if (result) + goto err_free; + + perf = data->sfi_data; + policy->shared_type =CPUFREQ_SHARED_TYPE_HW ; + +/* capability check */ +if (perf->state_count <=1 ) { +pr_debug ("No P-States\n" ); + result = -ENODEV ; + goto err_unreg; + } + + data->freq_table =kzalloc (sizeof (*data->freq_table) * + (perf->state_count+1 ),GFP_KERNEL ); +if (!data->freq_table) { + result = -ENOMEM ; + goto err_unreg; + } + +/* detect transition latency */ + policy->cpuinfo.transition_latency =0 ; +for (i =0 ; i < perf->state_count; i++) { +if ((perf->states[i].transition_latency *1000 ) > + policy->cpuinfo.transition_latency) + policy->cpuinfo.transition_latency = + perf->states[i].transition_latency *1000 ; + + pr_debug(" %cP%d: %d MHz, %d uS\n", + (i == perf->state ? '*' : ' '), i, + (u32) perf->states[i].core_frequency,
drivers/cpufreq/sfi-cpufreq.c line 263
Quoted 10 lines
drivers/cpufreq/sfi-cpufreq.c +10
-0+ (u32) perf->states[i].transition_latency); + } + +/* initialize the freq table */ +for (i =0 ; i < perf->state_count; i++) { + data->freq_table[valid_states].driver_data = i; + data->freq_table[valid_states].frequency = + perf->states[i].core_frequency *1000 ; + valid_states++; + }
Why not merge both 'for' loops?
Quoted 59 lines
drivers/cpufreq/sfi-cpufreq.c +59
-0+ data->freq_table[valid_states].frequency =CPUFREQ_TABLE_END ; + perf->state =0 ; + + result =cpufreq_table_validate_and_show (policy, data->freq_table); +if (result) + goto err_freqfree; + +pr_debug ("CPU%u - SFI performance management activated.\n" , cpu); + +return result; + +err_freqfree: +kfree (data->freq_table); +err_unreg: +sfi_processor_unregister_performance (perf); +err_free: +kfree (data); +per_cpu (drv_data, cpu) =NULL ; + +return result; +} + +static int sfi_cpufreq_cpu_exit (struct cpufreq_policy *policy) +{ +struct sfi_cpufreq_data *data =per_cpu (drv_data, policy->cpu); + +pr_debug ("sfi_cpufreq_cpu_exit\n" ); + +per_cpu (drv_data, policy->cpu) =NULL ; +sfi_processor_unregister_performance (data->sfi_data); +kfree (data->freq_table); +kfree (data); + +return 0 ; +} + +static struct cpufreq_driver sfi_cpufreq_driver = { + .flags =CPUFREQ_CONST_LOOPS , + .get = get_cur_freq_on_cpu, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = sfi_cpufreq_target, + .init = sfi_cpufreq_cpu_init, + .exit = sfi_cpufreq_cpu_exit, + .name ="sfi-cpufreq" , + .attr = cpufreq_generic_attr, +}; + +static int __init sfi_cpufreq_init (void ) +{ + sfi_perf_data = alloc_percpu(struct sfi_processor_performance); +if (!sfi_perf_data) { +pr_err ("Memory allocation error for sfi_perf_data.\n" ); +return -ENOMEM ; + } + +return cpufreq_register_driver (&sfi_cpufreq_driver); +} +late_initcall (sfi_cpufreq_init); +
drivers/cpufreq/sfi-cpufreq.c line 332
Quoted 10 lines
drivers/cpufreq/sfi-cpufreq.c +10
-0+static void __exit sfi_cpufreq_exit(void) +{ +cpufreq_unregister_driver (&sfi_cpufreq_driver); +free_percpu (sfi_perf_data); +} +module_exit (sfi_cpufreq_exit); + +MODULE_AUTHOR ("Vishwesh M Rudramuni <[email protected]>" ); +MODULE_DESCRIPTION ("SFI P-States Driver" ); +MODULE_LICENSE ("GPL" );
Looks fine otherwise.
Quoted 10 lines · Viresh Kumar
Quoted 7 lines · Srinidhi Kasagar
This adds the sfi based cpu freq driver for some of the Intel's Silver Mont based atom architectures like Merrifield and Moorfield (intel-mid)
Signed-off-by Rudramuni, Vishwesh M <[email protected]>Signed-off-by Srinidhi Kasagar <[email protected]>---
Always good to let people know what changed from previous version.
Thanks much Viresh. I will respin the patch with the rest of your comments.
Srinidhi