diff options
author | Saravana Kannan <saravanak@google.com> | 2021-02-04 09:14:22 +0100 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2021-02-04 12:00:14 +0100 |
commit | 7d8658ef65a4f891d0cff6340fa717b378384642 (patch) | |
tree | 6d6d69f3d586c044b91d3eb2615ee6c0db7d183e /drivers/opp | |
parent | opp: Replace ENOTSUPP with EOPNOTSUPP (diff) | |
download | linux-7d8658ef65a4f891d0cff6340fa717b378384642.tar.xz linux-7d8658ef65a4f891d0cff6340fa717b378384642.zip |
OPP: Add function to look up required OPP's for a given OPP
Add a function that allows looking up required OPPs given a source OPP
table, destination OPP table and the source OPP.
Signed-off-by: Saravana Kannan <saravanak@google.com>
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
[ Viresh: Rearranged code, fixed return errors ]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers/opp')
-rw-r--r-- | drivers/opp/core.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c index dc95d29e94c1..c3f3d9249cc5 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -2399,6 +2399,61 @@ devm_pm_opp_attach_genpd(struct device *dev, const char **names, EXPORT_SYMBOL_GPL(devm_pm_opp_attach_genpd); /** + * dev_pm_opp_xlate_required_opp() - Find required OPP for @src_table OPP. + * @src_table: OPP table which has @dst_table as one of its required OPP table. + * @dst_table: Required OPP table of the @src_table. + * @src_opp: OPP from the @src_table. + * + * This function returns the OPP (present in @dst_table) pointed out by the + * "required-opps" property of the @src_opp (present in @src_table). + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + * + * Return: pointer to 'struct dev_pm_opp' on success and errorno otherwise. + */ +struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, + struct opp_table *dst_table, + struct dev_pm_opp *src_opp) +{ + struct dev_pm_opp *opp, *dest_opp = ERR_PTR(-ENODEV); + int i; + + if (!src_table || !dst_table || !src_opp || + !src_table->required_opp_tables) + return ERR_PTR(-EINVAL); + + /* required-opps not fully initialized yet */ + if (lazy_linking_pending(src_table)) + return ERR_PTR(-EBUSY); + + for (i = 0; i < src_table->required_opp_count; i++) { + if (src_table->required_opp_tables[i] == dst_table) { + mutex_lock(&src_table->lock); + + list_for_each_entry(opp, &src_table->opp_list, node) { + if (opp == src_opp) { + dest_opp = opp->required_opps[i]; + dev_pm_opp_get(dest_opp); + break; + } + } + + mutex_unlock(&src_table->lock); + break; + } + } + + if (IS_ERR(dest_opp)) { + pr_err("%s: Couldn't find matching OPP (%p: %p)\n", __func__, + src_table, dst_table); + } + + return dest_opp; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_xlate_required_opp); + +/** * dev_pm_opp_xlate_performance_state() - Find required OPP's pstate for src_table. * @src_table: OPP table which has dst_table as one of its required OPP table. * @dst_table: Required OPP table of the src_table. |