From: "Kasagar, Srinidhi" <srinidhi.kasagar@intel.com>
To: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Dirk Brandewie <dirk.j.brandewie@intel.com>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
"linux-pm@vger.kernel.org" <linux-pm@vger.kernel.org>,
vishwesh.m.rudramuni@intel.com, srinidhi.kasagar@intel.com
Subject: Re: [PATCH] cpufreq: Add sfi based cpufreq driver support
Date: Thu, 9 Oct 2014 00:44:54 +0530 [thread overview]
Message-ID: <20141008191454.GA6504@intel-desktop> (raw)
In-Reply-To: <CAKohpokLcZPcMUjXYNNxDcwHUzsL1ejYBYd0cDmnAHQu+cBYGA@mail.gmail.com>
The author is on vacation, let me take some of your comments as i'm in the
delivery path..
On Tue, Oct 07, 2014 at 03:52:42PM +0530, Viresh Kumar wrote:
> Adding Dirk as well..
>
> On 7 October 2014 19:37, Kasagar, Srinidhi <srinidhi.kasagar@intel.com> wrote:
> > From b3037348db47f0629316dd0027c7f1a1b28be959 Mon Sep 17 00:00:00 2001
> > From: Srinidhi Kasagar <srinidhi.kasagar@intel.com>
> > Date: Fri, 12 Sep 2014 22:52:37 +0530
> > Subject: [PATCH] cpufreq: Add sfi based cpufreq driver support
>
> You didn't use git send-email ?
No, looks like it is broken. Will fix it anyway.
>
> > 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 <vishwesh.m.rudramuni@intel.com>
> > Signed-off-by: Srinidhi Kasagar <srinidhi.kasagar@intel.com>
> > ---
> > drivers/cpufreq/Kconfig.x86 | 10 +
> > drivers/cpufreq/Makefile | 1 +
> > drivers/cpufreq/sfi-cpufreq.c | 426 +++++++++++++++++++++++++++++++++++++++++
> > drivers/cpufreq/sfi-cpufreq.h | 53 +++++
> > 4 files changed, 490 insertions(+)
> > create mode 100644 drivers/cpufreq/sfi-cpufreq.c
> > create mode 100644 drivers/cpufreq/sfi-cpufreq.h
> >
> > diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
> > index 89ae88f91895..3d6886b558fa 100644
> > --- a/drivers/cpufreq/Kconfig.x86
> > +++ b/drivers/cpufreq/Kconfig.x86
> > @@ -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 driver adds a CPUFreq driver which utilizes the SFI
>
> s/This driver/This/
Thanks, will fix.
>
> > + Processor Performance States enumeration on some Silver Mont
> > + based Intel Atom architecture (like intel-mid)
>
> Looks like the sentence isn't complete here, would you like to?
This is good enough..let me rephrase it.
>
> > +
> > + If in doubt, say N.
> > +
> > config ELAN_CPUFREQ
> > tristate "AMD Elan SC400 and SC410"
> > depends on MELAN
> > diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> > index db6d9a2fea4d..c3b51efd4a85 100644
> > --- a/drivers/cpufreq/Makefile
> > +++ b/drivers/cpufreq/Makefile
> > @@ -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
> > diff --git a/drivers/cpufreq/sfi-cpufreq.c b/drivers/cpufreq/sfi-cpufreq.c
> > new file mode 100644
> > index 000000000000..1400e0387528
> > --- /dev/null
> > +++ b/drivers/cpufreq/sfi-cpufreq.c
> > @@ -0,0 +1,426 @@
> > +/*
> > + * sfi_cpufreq.c - sfi Processor P-States Driver
>
> No need of mentioning file name here.
Thanks for spotting..these are all left over stuffs from the original code.
Let me clean up further..
>
> > + * Based on ACPI Processor P-States Driver
> > + *
>
> How much different is it from that ? Sorry I haven't checked :(
>
> I mean, will it be possible to make changes to acpi-cpufreq driver or
> get the common part out?
I dont think so. That is ACPI, this one is SFI. Both are architecturally not
aligned.
>
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License.
> > + *
> > + * This program is distributed in the hope that it will be useful, but
> > + * WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> > + * General Public License for more details.
> > + *
> > + * Author: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/init.h>
> > +#include <linux/smp.h>
> > +#include <linux/cpufreq.h>
> > +#include <linux/slab.h>
> > +#include <linux/sfi.h>
>
> Keep them in ascending order please.
Hm..Will fix.
>
> > +#include <asm/msr.h>
> > +#include <asm/processor.h>
> > +
> > +#include "sfi-cpufreq.h"
>
> Do you plan to share the definitions here with any other file? If no, please
> merge the .h file here only.
No, will fix it.
>
> > +#define SFI_FREQ_MAX 32
> > +#define INTEL_MSR_RANGE 0xffff
> > +#define INTEL_MSR_BUSRATIO_MASK 0xff00
> > +#define SFI_CPU_MAX 8
>
> Aligning the values in a single column is preferred for readability.
I did, not sure how it got realigned. Let me take a look.
[...]
> > +}
> > +
> > +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;
>
> You meant unsigned int only?
Yes.
>
> > +
> > + if (unlikely(data == NULL ||
> > + data->sfi_data == NULL || data->freq_table == NULL)) {
> > + return -ENODEV;
> > + }
>
> Probably this looks better:
> if (unlikely(!data || !data->sfi_data || !data->freq_table))
> return -ENODEV;
Why not?
>
> But do we need this check at all ? Also same comments for similar usage
> in above routines.
Not really..Will remove these stuffs.
>
> > +
> > + perf = data->sfi_data;
> > + next_perf_state = data->freq_table[index].driver_data;
> > + if (perf->state == next_perf_state) {
>
> Can this happen? Probably cpufreq core will never do it ?
I think it did. Let me keep this.
>
> > + if (unlikely(data->resume)) {
> > + pr_debug("Called after resume, resetting to P%d\n",
> > + next_perf_state);
> > + data->resume = 0;
> > + } else {
> > + pr_debug("Already at target state (P%d)\n",
> > + next_perf_state);
> > + return 0;
> > + }
> > + }
> > +
> > + 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;
> > +
> > + return 0;
> > +}
> > +
> > +static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy)
> > +{
> > + unsigned int i;
> > + unsigned int valid_states = 0;
> > + unsigned int cpu = policy->cpu;
> > + struct sfi_cpufreq_data *data;
> > + unsigned int result = 0;
>
> Can merge all definitions of similar data type in a single line.
Why not?
>
> > + struct sfi_processor_performance *perf;
> > + struct sfi_processor *pr;
> > +
> > + pr = kzalloc(sizeof(struct sfi_processor), GFP_KERNEL);
>
> sizeof(*pr)
Style issues. Will fix.
>
> > + if (!pr)
> > + return -ENOMEM;
> > +
> > + per_cpu(sfi_processors, cpu) = pr;
> > +
> > + pr_debug("sfi_cpufreq_cpu_init CPU:%d\n", policy->cpu);
>
> I would prefer
> pr_debug("%s: CPU:%d\n", __func__, policy->cpu);
Me too. Will fix.
>
> > +
> > + data = kzalloc(sizeof(struct sfi_cpufreq_data), GFP_KERNEL);
>
> sizeof(*data)
ditto..
>
> > + if (!data)
> > + return -ENOMEM;
>
> What about freeing pr ?
My bad. Will fix.
>
> > +
> > + data->sfi_data = per_cpu_ptr(sfi_perf_data, cpu);
> > + per_cpu(drv_data, cpu) = data;
> > +
> > + sfi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
>
> Why here? and not in the structure definition itself..
Hmm..another legacy style. Will add it in the definition rather..Thanks.
>
> > +
> > + result = sfi_processor_register_performance(data->sfi_data, cpu);
> > + if (result)
> > + goto err_free;
> > +
> > + perf = data->sfi_data;
> > + policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
> > +
> > + cpumask_set_cpu(policy->cpu, policy->cpus);
> > + cpumask_set_cpu(policy->cpu, policy->related_cpus);
>
> You don't have to set related_cpus, its done by core. Also policy->cpus
> is already set by core to policy->cpu.
Yes, Will fix.
>
> > +
> > + /* capability check */
> > + if (perf->state_count <= 1) {
> > + pr_debug("No P-States\n");
> > + result = -ENODEV;
> > + goto err_unreg;
> > + }
> > +
> > + data->freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
>
> sizeof (*data->freq_table)
ok..
>
> Also, you want to do kzalloc? or kmalloc will work as well ?
kmalloc makes my table corrupted, perhaps the addition of new flag variable.
Let me keep kzalloc.
>
> > + (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;
> > + }
> > +
> > + /* initialize the freq table */
> > + for (i = 0; i < perf->state_count; i++) {
> > + if (i > 0 && perf->states[i].core_frequency >=
> > + data->freq_table[valid_states-1].frequency / 1000)
> > + continue;
>
> What are you doing here ?
This is unncessary check, not needed. Again a left over stuff. Will clean it.
>
> > +
> > + data->freq_table[valid_states].driver_data = i;
> > + data->freq_table[valid_states].frequency =
> > + perf->states[i].core_frequency * 1000;
> > + valid_states++;
> > + }
> > + 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;
> > +
> > + policy->cur = get_cur_freq_on_cpu(cpu);
>
> This is done by core and so you need to do it.
Agree. Will remove.
>
> > + pr_debug("CPU%u - SFI performance management activated.\n", cpu);
> > + for (i = 0; i < perf->state_count; i++)
> > + pr_debug(" %cP%d: %d MHz, %d uS\n",
> > + (i == perf->state ? '*' : ' '), i,
> > + (u32) perf->states[i].core_frequency,
> > + (u32) perf->states[i].transition_latency);
>
> What about printing this in the above for loop only?
Why not?
>
> > +
> > + data->resume = 1;
> > +
> > + return result;
> > +
> > +err_freqfree:
> > + kfree(data->freq_table);
> > +err_unreg:
> > + sfi_processor_unregister_performance(perf, cpu);
> > +err_free:
> > + kfree(data);
> > + per_cpu(drv_data, cpu) = NULL;
>
> Free pr ?
My bad. Wilf fix
>
> > +
> > + return result;
> > +}
> > +
> > +static int sfi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
> > +{
> > + struct sfi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
> > + struct sfi_processor *pr = per_cpu(sfi_processors, policy->cpu);
> > +
> > + pr_debug("sfi_cpufreq_cpu_exit\n");
> > +
> > + if (data) {
>
> Why will data be NULL here ?
Perhaps to satisfy the static code check tools. Will remove.
>
> > + per_cpu(drv_data, policy->cpu) = NULL;
> > + sfi_processor_unregister_performance(data->sfi_data,
> > + policy->cpu);
> > + kfree(data->freq_table);
> > + kfree(data);
> > + kfree(pr);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int sfi_cpufreq_resume(struct cpufreq_policy *policy)
> > +{
> > + struct sfi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
>
> Your code is dependent on policy->cpu at multiple places and it can change on
> CPU hotplug. You should worry about it only if there can be more than one CPU
> in a single policy, which doesn't look like the case.
Not sure what do you mean by not using policy->cpu. I need all of these
to support hotplug. Can you elaborate if you mean otherwise please?
>
> Also there is a patch from Thomas Petazzoni
> [PATCHv2 1/4] cpufreq: allow driver-specific data
> https://www.mail-archive.com/linux-arm-msm@vger.kernel.org/msg10696.html
>
> you can use that for data.
>
> > +
> > + pr_debug("sfi_cpufreq_resume\n");
> > +
> > + data->resume = 1;
> > +
> > + return 0;
> > +}
> > +
> > +static struct freq_attr *sfi_cpufreq_attr[] = {
> > + &cpufreq_freq_attr_scaling_available_freqs,
> > + NULL,
> > +};
>
> Can reuse cpufreq_generic_attr ??
We should be using that. Will fix.
>
> > +
> > +static struct cpufreq_driver sfi_cpufreq_driver = {
> > + .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,
> > + .resume = sfi_cpufreq_resume,
> > + .name = "sfi-cpufreq",
> > + .attr = sfi_cpufreq_attr,
> > +};
> > +
> > +static int __init sfi_cpufreq_init(void)
> > +{
> > + sfi_perf_data = alloc_percpu(struct sfi_processor_performance);
> > + if (!sfi_perf_data) {
> > + pr_debug("Memory allocation error for sfi_perf_data.\n");
>
> Shouldn't this be pr_err ??
Yes. Will fix.
>
> > + return -ENOMEM;
> > + }
> > +
> > + return cpufreq_register_driver(&sfi_cpufreq_driver);
> > +}
> > +
> > +static void __exit sfi_cpufreq_exit(void)
> > +{
> > + struct sfi_processor *pr;
> > +
> > + pr = per_cpu(sfi_processors, 0);
> > + kfree(pr);
>
> What about: kfree(per_cpu(sfi_processors, 0)); instead of above 4 lines.
> Also why here when its already done in sfi_cpufreq_cpu_exit ?
I think it is not required. Will remove them.
>
> > +
> > + cpufreq_unregister_driver(&sfi_cpufreq_driver);
> > +
> > + free_percpu(sfi_perf_data);
> > +}
> > +late_initcall(sfi_cpufreq_init);
> > +module_exit(sfi_cpufreq_exit);
>
> Normally we add them just below the respective routines.
Some prefer like this :)
>
> > +
> > +MODULE_ALIAS("sfi");
> > +MODULE_AUTHOR("Vishwesh Rudramuni");
>
> Can add email address as well..
Yes..Will add.
Srinidhi
next prev parent reply other threads:[~2014-10-08 11:15 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-07 14:07 [PATCH] cpufreq: Add sfi based cpufreq driver support Kasagar, Srinidhi
2014-10-07 10:22 ` Viresh Kumar
2014-10-08 19:14 ` Kasagar, Srinidhi [this message]
2014-10-09 4:03 ` Viresh Kumar
2014-10-09 18:08 ` Kasagar, Srinidhi
2014-10-09 10:18 ` Viresh Kumar
2014-10-09 19:07 ` Kasagar, Srinidhi
2014-10-09 11:15 ` Viresh Kumar
2014-10-10 16:51 ` Kasagar, Srinidhi
2014-10-10 8:57 ` Viresh Kumar
2014-10-10 17:14 ` Kasagar, Srinidhi
2014-10-10 9:27 ` Viresh Kumar
2014-10-10 10:47 ` Kasagar, Srinidhi
2014-10-10 11:11 ` Viresh Kumar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141008191454.GA6504@intel-desktop \
--to=srinidhi.kasagar@intel.com \
--cc=dirk.j.brandewie@intel.com \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@rjwysocki.net \
--cc=viresh.kumar@linaro.org \
--cc=vishwesh.m.rudramuni@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).