You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
clk: Move clk_core_init_rate_req() from clk_core_round_rate_nolock() to its caller
The clk_rate_request structure is used internally as an argument for
the clk_core_determine_round_nolock() and clk_core_round_rate_nolock().
In both cases, the clk_core_init_rate_req() function is used to
initialize the clk_rate_request structure.
However, the expectation on who gets to call that function is
inconsistent between those two functions. Indeed,
clk_core_determine_round_nolock() will assume the structure is properly
initialized and will just use it.
On the other hand, clk_core_round_rate_nolock() will call
clk_core_init_rate_req() itself, expecting the caller to have filled
only a minimal set of parameters (rate, min_rate and max_rate).
If we ignore the calling convention inconsistency, this leads to a
second inconsistency for drivers:
* If they get called by the framework through
clk_core_round_rate_nolock(), the rate, min_rate and max_rate
fields will be filled by the caller, and the best_parent_rate and
best_parent_hw fields will get filled by clk_core_init_rate_req().
* If they get called by a driver through __clk_determine_rate (and
thus clk_core_round_rate_nolock), only best_parent_rate and
best_parent_hw are being explicitly set by the framework. Even
though we can reasonably expect rate to be set, only one of the 6
in-tree users explicitly set min_rate and max_rate.
* If they get called by the framework through
clk_core_determine_round_nolock(), then we have two callpaths.
Either it will be called by clk_core_round_rate_nolock() itself, or
it will be called by clk_calc_new_rates(), which will properly
initialize rate, min_rate, max_rate itself, and best_parent_rate
and best_parent_hw through clk_core_init_rate_req().
Even though the first and third case seems equivalent, they aren't when
the clock has CLK_SET_RATE_PARENT. Indeed, in such a case
clk_core_round_rate_nolock() will call itself on the current parent
clock with the same clk_rate_request structure.
The clk_core_init_rate_req() function will then be called on the parent
clock, with the child clk_rate_request pointer and will fill the
best_parent_rate and best_parent_hw fields with the parent context.
When the whole recursion stops and the call returns, the initial caller
will end up with a clk_rate_request structure with some information of
the child clock (rate, min_rate, max_rate) and some others of the last
clock up the tree whose child had CLK_SET_RATE_PARENT (best_parent_hw,
best_parent_rate).
In the most common case, best_parent_rate is going to be equal on all
the parent clocks so it's not a big deal. However, best_parent_hw is
going to point to a clock that never has been a valid parent for that
clock which is definitely confusing.
In order to fix the calling inconsistency, let's move the
clk_core_init_rate_req() calls to the callers, which will also help a
bit with the clk_core_round_rate_nolock() recursion.
Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # imx8mp
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> # exynos4210, meson g12b
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220816112530.1837489-16-maxime@cerno.tech
Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
Tested-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
0 commit comments