Commit de04241a authored by Jonathan Marek's avatar Jonathan Marek Committed by Viresh Kumar

opp: Don't skip freq update for different frequency

We skip the OPP update if the current and target OPPs are same. This is
fine for the devices that don't support frequency but may cause issues
for the ones that need to program frequency.

An OPP entry doesn't really signify a single operating frequency but
rather the highest frequency at which the other properties of the OPP
entry apply. And we may reach here with different frequency values,
while all of them would point to the same OPP entry in the OPP table.

We just need to update the clock frequency in that case, though in order
to not add special exit points we reuse the code flow from a normal
path.

While at it, rearrange the conditionals in the 'if' statement to check
'enabled' flag at the end.

Fixes: 81c4d8a3 ("opp: Keep track of currently programmed OPP")
Signed-off-by: default avatarJonathan Marek <jonathan@marek.ca>
[ Viresh: Improved commit log and subject, rename current_freq as
	  current_rate, document it, remove local variable and rearrange
	  code. ]
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 86ad9a24
...@@ -998,14 +998,15 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, ...@@ -998,14 +998,15 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
old_opp = opp_table->current_opp; old_opp = opp_table->current_opp;
/* Return early if nothing to do */ /* Return early if nothing to do */
if (opp_table->enabled && old_opp == opp) { if (old_opp == opp && opp_table->current_rate == freq &&
opp_table->enabled) {
dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__); dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__);
return 0; return 0;
} }
dev_dbg(dev, "%s: switching OPP: Freq %lu -> %lu Hz, Level %u -> %u, Bw %u -> %u\n", dev_dbg(dev, "%s: switching OPP: Freq %lu -> %lu Hz, Level %u -> %u, Bw %u -> %u\n",
__func__, old_opp->rate, freq, old_opp->level, opp->level, __func__, opp_table->current_rate, freq, old_opp->level,
old_opp->bandwidth ? old_opp->bandwidth[0].peak : 0, opp->level, old_opp->bandwidth ? old_opp->bandwidth[0].peak : 0,
opp->bandwidth ? opp->bandwidth[0].peak : 0); opp->bandwidth ? opp->bandwidth[0].peak : 0);
scaling_down = _opp_compare_key(old_opp, opp); scaling_down = _opp_compare_key(old_opp, opp);
...@@ -1061,6 +1062,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, ...@@ -1061,6 +1062,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
/* Make sure current_opp doesn't get freed */ /* Make sure current_opp doesn't get freed */
dev_pm_opp_get(opp); dev_pm_opp_get(opp);
opp_table->current_opp = opp; opp_table->current_opp = opp;
opp_table->current_rate = freq;
return ret; return ret;
} }
......
...@@ -135,6 +135,7 @@ enum opp_table_access { ...@@ -135,6 +135,7 @@ enum opp_table_access {
* @clock_latency_ns_max: Max clock latency in nanoseconds. * @clock_latency_ns_max: Max clock latency in nanoseconds.
* @parsed_static_opps: Count of devices for which OPPs are initialized from DT. * @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
* @shared_opp: OPP is shared between multiple devices. * @shared_opp: OPP is shared between multiple devices.
* @current_rate: Currently configured frequency.
* @current_opp: Currently configured OPP for the table. * @current_opp: Currently configured OPP for the table.
* @suspend_opp: Pointer to OPP to be used during device suspend. * @suspend_opp: Pointer to OPP to be used during device suspend.
* @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers. * @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
...@@ -184,6 +185,7 @@ struct opp_table { ...@@ -184,6 +185,7 @@ struct opp_table {
unsigned int parsed_static_opps; unsigned int parsed_static_opps;
enum opp_table_access shared_opp; enum opp_table_access shared_opp;
unsigned long current_rate;
struct dev_pm_opp *current_opp; struct dev_pm_opp *current_opp;
struct dev_pm_opp *suspend_opp; struct dev_pm_opp *suspend_opp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment