From 823c6a55a620892fb8a284b880d9d5d40e1c2375 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel <sebastian.reichel@collabora.com> Date: Thu, 18 May 2023 05:28:17 +0200 Subject: [PATCH] clk: composite: Fix handling of high clock rates If clk_round_rate(clk, ULONG_MAX) is called to acquire the highest available clock rate and the highest available clock rate is smaller than ULONG_MAX/2, the result of "req->rate - tmp_req.rate" has the highest bit set. Since the input to abs() is signed, that means the number will be miss-interpreted. This results in the logic being reverted and the worst choice being selected as the best one. For example this has been observed on RK3588 for the eMMC clock: GPLL: abs(18446744073709551615 - 1188000000) = 1188000001 CPLL: abs(18446744073709551615 - 1500000000) = 1500000001 XIN24M: abs(18446744073709551615 - 24000000) = 24000001 With the updated logic any casting between signed and unsigned is avoided and the numbers look like this instead: GPLL: 18446744073709551615 - 1188000000 = 18446744072521551615 CPLL: 18446744073709551615 - 1500000000 = 18446744072209551615 XIN24M: 18446744073709551615 - 24000000 = 18446744073685551615 As a result the parent with the highest acceptable rate is chosen instead of the parent clock with the lowest one. Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> --- drivers/clk/clk-composite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index edfa94641bbfe..3fab488704df7 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -119,7 +119,7 @@ static int clk_composite_determine_rate(struct clk_hw *hw, if (ret) continue; - rate_diff = abs(req->rate - tmp_req.rate); + rate_diff = req->rate > tmp_req.rate ? req->rate - tmp_req.rate : tmp_req.rate - req->rate; if (!rate_diff || !req->best_parent_hw || best_rate_diff > rate_diff) { -- GitLab