summaryrefslogtreecommitdiff
path: root/include/linux/clk-provider.h
diff options
context:
space:
mode:
authorMaxime Ripard <maxime@cerno.tech>2022-08-16 14:25:26 +0300
committerStephen Boyd <sboyd@kernel.org>2022-09-15 19:32:11 +0300
commit262ca38f4b6eb418b20b8e1d6d8495c6a98727c1 (patch)
tree6c19e04316f465b662ef715dccd025a3b2720734 /include/linux/clk-provider.h
parent22fb0e284fbc3c1b85d24c5a1df8ea3ac82ab1d1 (diff)
downloadlinux-262ca38f4b6eb418b20b8e1d6d8495c6a98727c1.tar.xz
clk: Stop forwarding clk_rate_requests to the parent
If the clock cannot modify its rate and has CLK_SET_RATE_PARENT, clk_mux_determine_rate_flags(), clk_core_round_rate_nolock() and a number of drivers will forward the clk_rate_request to the parent clock. clk_core_round_rate_nolock() will pass the pointer directly, which means that we pass a clk_rate_request to the parent that has the rate, min_rate and max_rate of the child, and the best_parent_rate and best_parent_hw fields will be relative to the child as well, so will point to our current clock and its rate. The most common case for CLK_SET_RATE_PARENT is that the child and parent clock rates will be equal, so the rate field isn't a worry, but the other fields are. Similarly, if the parent clock driver ever modifies the best_parent_rate or best_parent_hw, this will be applied to the child once the call to clk_core_round_rate_nolock() is done. best_parent_hw is probably not going to be a valid parent, and best_parent_rate might lead to a parent rate change different to the one that was initially computed. clk_mux_determine_rate_flags() and the affected drivers will copy the request before forwarding it to the parents, so they won't be affected by the latter issue, but the former is still going to be there and will lead to erroneous data and context being passed to the various clock drivers in the same sub-tree. Let's create two new functions, clk_core_forward_rate_req() and clk_hw_forward_rate_request() for the framework and the clock providers that will copy a request from a child clock and update the context to match the parent's. We also update the relevant call sites in the framework and drivers to use that new function. Let's also add a test to make sure we avoid regressions there. 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-22-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>
Diffstat (limited to 'include/linux/clk-provider.h')
-rw-r--r--include/linux/clk-provider.h5
1 files changed, 5 insertions, 0 deletions
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index d857717aa386..8bce6c524f29 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -65,6 +65,11 @@ struct clk_rate_request {
void clk_hw_init_rate_request(const struct clk_hw *hw,
struct clk_rate_request *req,
unsigned long rate);
+void clk_hw_forward_rate_request(const struct clk_hw *core,
+ const struct clk_rate_request *old_req,
+ const struct clk_hw *parent,
+ struct clk_rate_request *req,
+ unsigned long parent_rate);
/**
* struct clk_duty - Struture encoding the duty cycle ratio of a clock