From: Viresh Kumar <viresh.kumar@linaro.org>
To: rjw@sisk.pl
Cc: linaro-kernel@lists.linaro.org, patches@linaro.org,
cpufreq@vger.kernel.org, linux-pm@vger.kernel.org,
linux-kernel@vger.kernel.org,
Viresh Kumar <viresh.kumar@linaro.org>
Subject: [PATCH V2 Resend 01/34] cpufreq: Implement light weight ->target_index() routine
Date: Fri, 18 Oct 2013 19:29:24 +0530 [thread overview]
Message-ID: <86f6661cef3518a6dba549a547b0a12f1f4b39fc.1382104515.git.viresh.kumar@linaro.org> (raw)
In-Reply-To: <cover.1382104514.git.viresh.kumar@linaro.org>
In-Reply-To: <cover.1382104514.git.viresh.kumar@linaro.org>
Currently prototype of cpufreq_drivers target routines is:
int target(struct cpufreq_policy *policy, unsigned int target_freq,
unsigned int relation);
And most of the drivers call cpufreq_frequency_table_target() to get a valid
index of their frequency table which is closest to the target_freq. And they
don't use target_freq and relation after it.
So, it makes sense to just do this work in cpufreq core before calling
cpufreq_frequency_table_target() and simply pass index instead. But this can be
done only with drivers which expose their frequency table with cpufreq core. For
others we need to stick with the old prototype of target() until those drivers
are converted to expose frequency tables.
This patch implements the new light weight prototype for target_index() routine.
It looks like this:
int target_index(struct cpufreq_policy *policy, unsigned int index);
CPUFreq core will call cpufreq_frequency_table_target() before calling this
routine and pass index to it. Because CPUFreq core now requires to call routines
present in freq_table.c CONFIG_CPU_FREQ_TABLE must be enabled all the time.
This also marks target() interface as deprecated. So, that new drivers avoid
using it. And Documentation is updated accordingly.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
Documentation/cpu-freq/cpu-drivers.txt | 27 ++++++++++------
Documentation/cpu-freq/governors.txt | 4 +--
drivers/cpufreq/cpufreq.c | 57 +++++++++++++++++++++++++++-------
include/linux/cpufreq.h | 4 ++-
4 files changed, 69 insertions(+), 23 deletions(-)
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
index 40282e6..8b1a445 100644
--- a/Documentation/cpu-freq/cpu-drivers.txt
+++ b/Documentation/cpu-freq/cpu-drivers.txt
@@ -23,8 +23,8 @@ Contents:
1.1 Initialization
1.2 Per-CPU Initialization
1.3 verify
-1.4 target or setpolicy?
-1.5 target
+1.4 target/target_index or setpolicy?
+1.5 target/target_index
1.6 setpolicy
2. Frequency Table Helpers
@@ -56,7 +56,8 @@ cpufreq_driver.init - A pointer to the per-CPU initialization
cpufreq_driver.verify - A pointer to a "verification" function.
cpufreq_driver.setpolicy _or_
-cpufreq_driver.target - See below on the differences.
+cpufreq_driver.target/
+target_index - See below on the differences.
And optionally
@@ -66,7 +67,7 @@ cpufreq_driver.resume - A pointer to a per-CPU resume function
which is called with interrupts disabled
and _before_ the pre-suspend frequency
and/or policy is restored by a call to
- ->target or ->setpolicy.
+ ->target/target_index or ->setpolicy.
cpufreq_driver.attr - A pointer to a NULL-terminated list of
"struct freq_attr" which allow to
@@ -103,8 +104,8 @@ policy->governor must contain the "default policy" for
this CPU. A few moments later,
cpufreq_driver.verify and either
cpufreq_driver.setpolicy or
- cpufreq_driver.target is called with
- these values.
+ cpufreq_driver.target/target_index is called
+ with these values.
For setting some of these values (cpuinfo.min[max]_freq, policy->min[max]), the
frequency table helpers might be helpful. See the section 2 for more information
@@ -133,20 +134,28 @@ range) is within policy->min and policy->max. If necessary, increase
policy->max first, and only if this is no solution, decrease policy->min.
-1.4 target or setpolicy?
+1.4 target/target_index or setpolicy?
----------------------------
Most cpufreq drivers or even most cpu frequency scaling algorithms
only allow the CPU to be set to one frequency. For these, you use the
-->target call.
+->target/target_index call.
Some cpufreq-capable processors switch the frequency between certain
limits on their own. These shall use the ->setpolicy call
-1.4. target
+1.4. target/target_index
-------------
+The target_index call has two arguments: struct cpufreq_policy *policy,
+and unsigned int index (into the exposed frequency table).
+
+The CPUfreq driver must set the new frequency when called here. The
+actual frequency must be determined by freq_table[index].frequency.
+
+Deprecated:
+----------
The target call has three arguments: struct cpufreq_policy *policy,
unsigned int target_frequency, unsigned int relation.
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 219970b..77ec215 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -40,7 +40,7 @@ Most cpufreq drivers (in fact, all except one, longrun) or even most
cpu frequency scaling algorithms only offer the CPU to be set to one
frequency. In order to offer dynamic frequency scaling, the cpufreq
core must be able to tell these drivers of a "target frequency". So
-these specific drivers will be transformed to offer a "->target"
+these specific drivers will be transformed to offer a "->target/target_index"
call instead of the existing "->setpolicy" call. For "longrun", all
stays the same, though.
@@ -71,7 +71,7 @@ CPU can be set to switch independently | CPU can only be set
/ the limits of policy->{min,max}
/ \
/ \
- Using the ->setpolicy call, Using the ->target call,
+ Using the ->setpolicy call, Using the ->target/target_index call,
the limits and the the frequency closest
"policy" is set. to target_freq is set.
It is assured that it
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3f03dcb..6c9cbb9 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -47,6 +47,11 @@ static LIST_HEAD(cpufreq_policy_list);
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
#endif
+static inline bool has_target(void)
+{
+ return cpufreq_driver->target_index || cpufreq_driver->target;
+}
+
/*
* rwsem to guarantee that cpufreq driver module doesn't unload during critical
* sections
@@ -351,7 +356,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy,
*policy = CPUFREQ_POLICY_POWERSAVE;
err = 0;
}
- } else if (cpufreq_driver->target) {
+ } else if (has_target()) {
struct cpufreq_governor *t;
mutex_lock(&cpufreq_governor_mutex);
@@ -509,7 +514,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
ssize_t i = 0;
struct cpufreq_governor *t;
- if (!cpufreq_driver->target) {
+ if (!has_target()) {
i += sprintf(buf, "performance powersave");
goto out;
}
@@ -794,7 +799,7 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
if (ret)
goto err_out_kobj_put;
}
- if (cpufreq_driver->target) {
+ if (has_target()) {
ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
if (ret)
goto err_out_kobj_put;
@@ -843,10 +848,10 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
unsigned int cpu, struct device *dev,
bool frozen)
{
- int ret = 0, has_target = !!cpufreq_driver->target;
+ int ret = 0;
unsigned long flags;
- if (has_target) {
+ if (has_target()) {
ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
if (ret) {
pr_err("%s: Failed to stop governor\n", __func__);
@@ -864,7 +869,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
up_write(&policy->rwsem);
- if (has_target) {
+ if (has_target()) {
if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
pr_err("%s: Failed to start governor\n", __func__);
@@ -1169,7 +1174,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
return -EINVAL;
}
- if (cpufreq_driver->target) {
+ if (has_target()) {
ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
if (ret) {
pr_err("%s: Failed to stop governor\n", __func__);
@@ -1234,7 +1239,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
/* If cpu is last user of policy, free policy */
if (cpus == 1) {
- if (cpufreq_driver->target) {
+ if (has_target()) {
ret = __cpufreq_governor(policy,
CPUFREQ_GOV_POLICY_EXIT);
if (ret) {
@@ -1277,7 +1282,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
if (!frozen)
cpufreq_policy_free(policy);
} else {
- if (cpufreq_driver->target) {
+ if (has_target()) {
if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
pr_err("%s: Failed to start governor\n",
@@ -1651,12 +1656,41 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
policy->cpu, target_freq, relation, old_target_freq);
+ /*
+ * This might look like a redundant call as we are checking it again
+ * after finding index. But it is left intentionally for cases where
+ * exactly same freq is called again and so we can save on few function
+ * calls.
+ */
if (target_freq == policy->cur)
return 0;
if (cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
+ else if (cpufreq_driver->target_index) {
+ struct cpufreq_frequency_table *freq_table;
+ int index;
+ freq_table = cpufreq_frequency_get_table(policy->cpu);
+ if (unlikely(!freq_table)) {
+ pr_err("%s: Unable to find freq_table\n", __func__);
+ goto out;
+ }
+
+ retval = cpufreq_frequency_table_target(policy, freq_table,
+ target_freq, relation, &index);
+ if (unlikely(retval)) {
+ pr_err("%s: Unable to find matching freq\n", __func__);
+ goto out;
+ }
+
+ if (freq_table[index].frequency == policy->cur)
+ retval = 0;
+ else
+ retval = cpufreq_driver->target_index(policy, index);
+ }
+
+out:
return retval;
}
EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
@@ -1982,7 +2016,7 @@ int cpufreq_update_policy(unsigned int cpu)
pr_debug("Driver did not initialize current freq");
policy->cur = new_policy.cur;
} else {
- if (policy->cur != new_policy.cur && cpufreq_driver->target)
+ if (policy->cur != new_policy.cur && has_target())
cpufreq_out_of_sync(cpu, policy->cur,
new_policy.cur);
}
@@ -2060,7 +2094,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
return -ENODEV;
if (!driver_data || !driver_data->verify || !driver_data->init ||
- ((!driver_data->setpolicy) && (!driver_data->target)))
+ !(driver_data->setpolicy || driver_data->target_index ||
+ driver_data->target))
return -EINVAL;
pr_debug("trying to register driver %s\n", driver_data->name);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 6b457d0..93a8c34 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -201,9 +201,11 @@ struct cpufreq_driver {
/* define one out of two */
int (*setpolicy) (struct cpufreq_policy *policy);
- int (*target) (struct cpufreq_policy *policy,
+ int (*target) (struct cpufreq_policy *policy, /* Deprecated */
unsigned int target_freq,
unsigned int relation);
+ int (*target_index) (struct cpufreq_policy *policy,
+ unsigned int index);
/* should be defined, if possible */
unsigned int (*get) (unsigned int cpu);
--
1.7.12.rc2.18.g61b472e
next prev parent reply other threads:[~2013-10-18 13:59 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-18 13:59 [PATCH V2 Resend 00/34] CPUFreq Cleanup Part III Viresh Kumar
2013-10-18 13:59 ` Viresh Kumar [this message]
2013-10-18 13:59 ` [PATCH V2 Resend 02/34] cpufreq: acpi: Convert to light weight ->target_index() routine Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 03/34] cpufreq: arm_big_little: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 04/34] cpufreq: at32ap: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 05/34] cpufreq: blackfin: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 06/34] cpufreq: cpu0: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 07/34] cpufreq: cris: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 08/34] cpufreq: davinci: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 09/34] cpufreq: dbx500: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 10/34] cpufreq: e_powersaver: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 11/34] cpufreq: elanfreq: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 12/34] cpufreq: exynos: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 13/34] cpufreq: ia64: " Viresh Kumar
2013-10-22 16:32 ` Luck, Tony
2013-10-18 13:59 ` [PATCH V2 Resend 14/34] cpufreq: imx6q: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 15/34] cpufreq: kirkwood: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 16/34] cpufreq: longhaul: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 17/34] cpufreq: loongson2: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 18/34] cpufreq: maple: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 19/34] cpufreq: omap: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 20/34] cpufreq: p4: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 21/34] cpufreq: pasemi: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 22/34] cpufreq: pmac32: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 23/34] cpufreq: powernow: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 24/34] cpufreq: ppc: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 25/34] cpufreq: pxa: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 26/34] cpufreq: s3c2416: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 27/34] cpufreq: s3c64xx: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 28/34] cpufreq: s5pv210: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 29/34] cpufreq: sa11x0: " Viresh Kumar
2013-10-18 15:46 ` Russell King - ARM Linux
2013-10-21 9:23 ` Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 30/34] cpufreq: sc520: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 31/34] cpufreq: sparc: " Viresh Kumar
2013-10-18 17:30 ` David Miller
2013-10-18 13:59 ` [PATCH V2 Resend 32/34] cpufreq: SPEAr: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 33/34] cpufreq: speedstep: " Viresh Kumar
2013-10-18 13:59 ` [PATCH V2 Resend 34/34] cpufreq: tegra: " Viresh Kumar
2013-10-25 12:56 ` [PATCH V2 Resend 00/34] CPUFreq Cleanup Part III Rafael J. Wysocki
2013-10-25 13:55 ` Viresh Kumar
2013-10-25 14:12 ` Rafael J. Wysocki
2013-10-25 14:16 ` 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=86f6661cef3518a6dba549a547b0a12f1f4b39fc.1382104515.git.viresh.kumar@linaro.org \
--to=viresh.kumar@linaro.org \
--cc=cpufreq@vger.kernel.org \
--cc=linaro-kernel@lists.linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=patches@linaro.org \
--cc=rjw@sisk.pl \
/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).