Re: [PATCH v10 1/8] opp: Add dev_pm_opp_get_current()
From: Dmitry Osipenko <digetx@gmail.com>
Date: 2021-09-01 05:43:48
Also in:
linux-pm, lkml
01.09.2021 07:39, Viresh Kumar пишет:
On 31-08-21, 16:54, Dmitry Osipenko wrote:quoted
Add dev_pm_opp_get_current() helper that returns OPP corresponding to the current clock rate of a device. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- drivers/opp/core.c | 43 +++++++++++++++++++++++++++++++++++++++--- include/linux/pm_opp.h | 6 ++++++ 2 files changed, 46 insertions(+), 3 deletions(-)diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 04b4691a8aac..dde8a5cc948c 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c@@ -939,7 +939,7 @@ static int _set_required_opps(struct device *dev, return ret; } -static void _find_current_opp(struct device *dev, struct opp_table *opp_table) +static struct dev_pm_opp *_find_current_opp(struct opp_table *opp_table) { struct dev_pm_opp *opp = ERR_PTR(-ENODEV); unsigned long freq;@@ -949,6 +949,18 @@ static void _find_current_opp(struct device *dev, struct opp_table *opp_table) opp = _find_freq_ceil(opp_table, &freq); } + return opp; +} + +static void _find_and_set_current_opp(struct opp_table *opp_table) +{ + struct dev_pm_opp *opp; + + if (opp_table->current_opp) + return;Why move this from caller as well ?
To make code cleaner.
quoted
+ + opp = _find_current_opp(opp_table); + /* * Unable to find the current OPP ? Pick the first from the list since * it is in ascending order, otherwise rest of the code will need toIf we aren't able to find current OPP based on current freq, then this picks the first value from the list. Why shouldn't this be done in your case as well ?
You will get OPP which corresponds to the lowest freq, while h/w runs on unsupported high freq. This may end with a tragedy.
quoted
@@ -1002,8 +1014,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, return _disable_opp_table(dev, opp_table); /* Find the currently set OPP if we don't know already */ - if (unlikely(!opp_table->current_opp)) - _find_current_opp(dev, opp_table); + _find_and_set_current_opp(opp_table); old_opp = opp_table->current_opp;@@ -2931,3 +2942,29 @@ int dev_pm_opp_sync_regulators(struct device *dev) return ret; } EXPORT_SYMBOL_GPL(dev_pm_opp_sync_regulators); + +/** + * dev_pm_opp_get_current() - Get current OPP + * @dev: device for which we do this operation + * + * Get current OPP of a device based on current clock rate or by other means. + * + * Return: pointer to 'struct dev_pm_opp' on success and errorno otherwise. + */ +struct dev_pm_opp *dev_pm_opp_get_current(struct device *dev) +{ + struct opp_table *opp_table; + struct dev_pm_opp *opp; + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) + return ERR_CAST(opp_table); + + opp = _find_current_opp(opp_table);This should not just go find the OPP based on current freq. This first needs to check if curret_opp is set or not. If set, then just return it, else run the _find_current_opp() function and update the current_opp pointer as well.
Alright, I'll change it.