[RFC PATCH] clk: composite: Fix incorrect rate constraint clamping in determine_rate

YuXuan Liu posted 1 patch 1 month, 2 weeks ago
drivers/clk/clk-composite.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
[RFC PATCH] clk: composite: Fix incorrect rate constraint clamping in determine_rate
Posted by YuXuan Liu 1 month, 2 weeks ago
In clk_composite_determine_rate(), the rate request is currently
modified using clk_hw_forward_rate_request() before being passed to the
rate_hw (divider). This behavior was inadvertently introduced by commit
20220816112530.1837489-22-maxime@cerno.tech ("clk: Stop forwarding
clk_rate_requests to the parent").

While clk_hw_forward_rate_request() effectively prevents context
pollution for pure multiplexers, using it for the internal components
of a composite clock introduces an unintended side effect. It fetches
the parent's rate boundaries and overwrites tmp_req.min_rate and
tmp_req.max_rate.

Consequently, the divider evaluates its own output constraints based on
the parent's operating constraints. For example, if a target rate is
50MHz, but the parent PLL hardware boundaries are [100MHz, 200MHz], the
divider erroneously assumes its output cannot be lower than 100MHz. It
then refuses to divide the frequency down, clamping the output to 100MHz.

Fix this by reverting to a local copy of the request (*req) without
applying parent boundaries before passing it to the rate_hw. This allows
the divider to evaluate boundaries correctly based on its own requirements.

I am submitting this as an RFC because I want to make sure I am not missing
a specific reason why the parent's boundaries must be forwarded to the
divider's output request in this context. Any insights would be
appreciated.

Fixes: 262ca38f4b6e ("clk: Stop forwarding clk_rate_requests to the parent")
Signed-off-by: YuXuan Liu <2021020915018@std.uestc.edu.cn>
---
 drivers/clk/clk-composite.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 66759fe28fad..952df88518c2 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -85,11 +85,10 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
 		req->best_parent_hw = NULL;
 
 		if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
-			struct clk_rate_request tmp_req;
+			struct clk_rate_request tmp_req = *req;
 
 			parent = clk_hw_get_parent(mux_hw);
 
-			clk_hw_forward_rate_request(hw, req, parent, &tmp_req, req->rate);
 			ret = clk_composite_determine_rate_for_parent(rate_hw,
 								      &tmp_req,
 								      parent,
@@ -105,13 +104,12 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
 		}
 
 		for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) {
-			struct clk_rate_request tmp_req;
+			struct clk_rate_request tmp_req = *req;
 
 			parent = clk_hw_get_parent_by_index(mux_hw, i);
 			if (!parent)
 				continue;
 
-			clk_hw_forward_rate_request(hw, req, parent, &tmp_req, req->rate);
 			ret = clk_composite_determine_rate_for_parent(rate_hw,
 								      &tmp_req,
 								      parent,
-- 
2.53.0