diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2016-06-16 19:03:11 +0530 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-06-16 15:50:36 +0200 |
commit | 79ee2e8f730411a30b271d5f9cdeae189fa66174 (patch) | |
tree | a81eb12f087ea733260210bba0fa9a1a612f54d3 /drivers/base/power/opp/cpu.c | |
parent | c8541203a680a63ba7dcc4e50cd25d40e9a13dff (diff) | |
download | lwn-79ee2e8f730411a30b271d5f9cdeae189fa66174.tar.gz lwn-79ee2e8f730411a30b271d5f9cdeae189fa66174.zip |
PM / OPP: Add 'UNKNOWN' status for shared_opp in struct opp_table
dev_pm_opp_get_sharing_cpus() returns 0 even in the case when the OPP
core doesn't know whether or not the table is shared. It works on the
majority of platforms, where the OPP table is never created before
invoking the function and then -ENODEV is returned by it.
But in the case of one platform (Jetson TK1) at least, the situation
is a bit different. The OPP table has been created (somehow) before
dev_pm_opp_get_sharing_cpus() is called and it returns 0. Its caller
treats that as 'the CPUs don't share OPPs' and that leads to degraded
performance.
Fix this by converting 'shared_opp' in struct opp_table to an enum
and making dev_pm_opp_get_sharing_cpus() return -EINVAL in case when
the value of that field is "access unknown", so that the caller can
handle it accordingly (cpufreq-dt considers that as 'all CPUs share
the table', for example).
Fixes: 6f707daa3833 "PM / OPP: Add dev_pm_opp_get_sharing_cpus()"
Reported-and-tested-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw : Subject & changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base/power/opp/cpu.c')
-rw-r--r-- | drivers/base/power/opp/cpu.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c index 83d6e7ba1a34..8c3434bdb26d 100644 --- a/drivers/base/power/opp/cpu.c +++ b/drivers/base/power/opp/cpu.c @@ -211,7 +211,7 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, } /* Mark opp-table as multiple CPUs are sharing it now */ - opp_table->shared_opp = true; + opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED; } unlock: mutex_unlock(&opp_table_lock); @@ -227,7 +227,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); * * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev. * - * Returns -ENODEV if OPP table isn't already present. + * Returns -ENODEV if OPP table isn't already present and -EINVAL if the OPP + * table's status is access-unknown. * * Locking: The internal opp_table and opp structures are RCU protected. * Hence this function internally uses RCU updater strategy with mutex locks @@ -249,9 +250,14 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) goto unlock; } + if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) { + ret = -EINVAL; + goto unlock; + } + cpumask_clear(cpumask); - if (opp_table->shared_opp) { + if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) { list_for_each_entry(opp_dev, &opp_table->dev_list, node) cpumask_set_cpu(opp_dev->dev->id, cpumask); } else { |