提交 a1f0e7f5 编写于 作者: M Maxime Ripard 提交者: Zheng Zengkai

clk: Initialize orphan req_rate

stable inclusion
from stable-v5.10.110
commit af0c3ced2468dd28d4dc599ba099adc892019a9b
bugzilla: https://gitee.com/openeuler/kernel/issues/I574AL

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=af0c3ced2468dd28d4dc599ba099adc892019a9b

--------------------------------

[ Upstream commit 5f7e2af0 ]

When registering a clock that doesn't have a recalc_rate implementation,
and doesn't have its parent registered yet, we initialize the clk_core
rate and 'req_rate' fields to 0.

The rate field is later updated when the parent is registered in
clk_core_reparent_orphans_nolock() using __clk_recalc_rates(), but the
'req_rate' field is never updated.

This leads to an issue in clk_set_rate_range() and clk_put(), since
those functions will call clk_set_rate() with the content of 'req_rate'
to provide drivers with the opportunity to change the rate based on the
new boundaries. In this case, we would call clk_set_rate() with a rate
of 0, effectively enforcing the minimum allowed for this clock whenever
we would call one of those two functions, even though the actual rate
might be within range.

Let's fix this by setting 'req_rate' in
clk_core_reparent_orphans_nolock() with the rate field content just
updated by the call to __clk_recalc_rates().

Fixes: 1c8e6004 ("clk: Add rate constraints to clocks")
Reported-by: NDmitry Osipenko <dmitry.osipenko@collabora.com>
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> # T30 Nexus7
Signed-off-by: NMaxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220325161144.1901695-2-maxime@cerno.tech
[sboyd@kernel.org: Reword comment]
Signed-off-by: NStephen Boyd <sboyd@kernel.org>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NYu Liao <liaoyu15@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 af18f1b2
...@@ -3384,6 +3384,19 @@ static void clk_core_reparent_orphans_nolock(void) ...@@ -3384,6 +3384,19 @@ static void clk_core_reparent_orphans_nolock(void)
__clk_set_parent_after(orphan, parent, NULL); __clk_set_parent_after(orphan, parent, NULL);
__clk_recalc_accuracies(orphan); __clk_recalc_accuracies(orphan);
__clk_recalc_rates(orphan, 0); __clk_recalc_rates(orphan, 0);
/*
* __clk_init_parent() will set the initial req_rate to
* 0 if the clock doesn't have clk_ops::recalc_rate and
* is an orphan when it's registered.
*
* 'req_rate' is used by clk_set_rate_range() and
* clk_put() to trigger a clk_set_rate() call whenever
* the boundaries are modified. Let's make sure
* 'req_rate' is set to something non-zero so that
* clk_set_rate_range() doesn't drop the frequency.
*/
orphan->req_rate = orphan->rate;
} }
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册