From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 92341235358; Sat, 12 Sep 2026 07:54:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789199683; cv=none; b=dtiar37BvT+qicK8W6avpgdkDx+lb4VLacXeA2uf+2J05yYwpz+xhZnGE4HnpHsdJh6tDNxpgXfsSTYBR9BD1MTVleu3BlXLLxXCqoYBHqDk2oNvTAjJtIjc3Y1h3/5jThxugKggvdAtLczhUWqKKqOgZS9mqWn6jizjuXev3Bk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789199683; c=relaxed/simple; bh=GHlLwdi3tDIJIj/PBwYLN74dcuZshWEZrxsXO+Xfbgw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SpnbwdF+MUvs01tnGd3w/2RJRDsdHgk7iCsnfKKiHtAlEU/VK/lnR3TKfdLfYF+ynf0DNkUSkbWzBr2KfE+sUgCEhFT7fV3z2ma7sJGHf/mJsnDw1+nacZYEoYGFmzkVi6XSA93BoHPW5jFUy7O8zpE1v/9EZXH9Bac5qnq4QFU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=qcN+WaLV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="qcN+WaLV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4BED61F000FF; Sat, 12 Sep 2026 07:54:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1789199682; bh=4nFpqqcqnrbeGpbAOJ+lKAofL+a3HDLKgWZRkSyhss0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=qcN+WaLV//Xm+ostaxtYDDIOwO9Toe5RxA6DOgq5CdmtCKox1wuZjY0svHPzscCJx YA5eDe8DuJQ4LFmpHokOKV60kaOmwlkPvT843msLqpkueMAfNcPgyqQ7E5NeSIyiUY 7e8sYJ0Bll1uMd9CTpWRLdhR0LAewfaO/m2fyZ2A= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Jerome Brunet , Chen-Yu Tsai , Sasha Levin Subject: [PATCH 7.2 0633/1815] clk: sunxi-ng: mux: fix determine helper rate propagation Date: Sat, 12 Sep 2026 08:39:43 +0200 Message-ID: <20260912065703.739640855@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260912065648.999753832@linuxfoundation.org> References: <20260912065648.999753832@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.2-stable review patch. If anyone has any objections, please let me know. ------------------ From: Jerome Brunet [ Upstream commit 4bcba49984ff8c77729f003dd32082b10c02c23b ] Applying the pre divider on the parent rate is wrong because, while handling rate propagation through determine_rate(), the framework will likely round the parent rate again while cycling through the possibilities, throwing away the prediv applied. This means, the parent rate will then be wrong when the prediv is unapplied from a parent rate on which it was never applied to begin with. The right way to do it is to unapply the prediv from the requested rate, which is the wanted rate at the input on the clock element, and pass this to framework to do its thing. Change the determine rate mux helper in this way. Fixes: 1c8d7af61b37 ("clk: sunxi-ng: convert from divider_round_rate_parent() to divider_determine_rate()") Signed-off-by: Jerome Brunet Link: https://patch.msgid.link/20260723-a733-rtc-v7-1-8fd68aab94ae@baylibre.com Signed-off-by: Chen-Yu Tsai Signed-off-by: Sasha Levin --- drivers/clk/sunxi-ng/ccu_mux.c | 57 +++++++++++++++++----------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c index 766f27cff748e..e56a3005548e3 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.c +++ b/drivers/clk/sunxi-ng/ccu_mux.c @@ -93,66 +93,65 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, struct clk_rate_request adj_req = *req; best_parent = clk_hw_get_parent(hw); - best_parent_rate = clk_hw_get_rate(best_parent); - + adj_req.best_parent_rate = clk_hw_get_rate(best_parent); adj_req.best_parent_hw = best_parent; - adj_req.best_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1, - best_parent_rate); + + /* + * This effectively treats the predivider as a postdivider. + * It stays mathematically correct and ensures whatever + * round() will do stays correct while walking the tree. + * It may query the parent rate too while handling rate + * propagation. + */ + adj_req.rate = ccu_mux_helper_unapply_prediv(common, cm, -1, + req->rate); ret = round(cm, &adj_req, data); if (ret) return ret; - best_rate = adj_req.rate; - /* - * best_parent_rate might have been modified by our clock. - * Unapply the pre-divider if there's one, and give - * the actual frequency the parent needs to run at. + * parent_rate might have been modified by our clock as part + * of the rate propagation mechanism. Same goes below. */ - best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1, - adj_req.best_parent_rate); + best_parent_rate = adj_req.best_parent_rate; + best_rate = ccu_mux_helper_apply_prediv(common, cm, -1, + adj_req.rate); goto out; } for (i = 0; i < clk_hw_get_num_parents(hw); i++) { struct clk_rate_request tmp_req = *req; - unsigned long parent_rate; + unsigned long rate; struct clk_hw *parent; parent = clk_hw_get_parent_by_index(hw, i); if (!parent) continue; - parent_rate = ccu_mux_helper_apply_prediv(common, cm, i, - clk_hw_get_rate(parent)); - tmp_req.best_parent_hw = parent; - tmp_req.best_parent_rate = parent_rate; + tmp_req.best_parent_rate = clk_hw_get_rate(parent); + tmp_req.rate = ccu_mux_helper_unapply_prediv(common, cm, i, + req->rate); ret = round(cm, &tmp_req, data); if (ret) continue; - /* - * parent_rate might have been modified by our clock. - * Unapply the pre-divider if there's one, and give - * the actual frequency the parent needs to run at. - */ - parent_rate = ccu_mux_helper_unapply_prediv(common, cm, i, - tmp_req.best_parent_rate); + rate = ccu_mux_helper_apply_prediv(common, cm, i, + tmp_req.rate); - if (tmp_req.rate == req->rate) { + if (rate == req->rate) { best_parent = parent; - best_parent_rate = parent_rate; - best_rate = tmp_req.rate; + best_parent_rate = tmp_req.best_parent_rate; + best_rate = rate; goto out; } - if (ccu_is_better_rate(common, req->rate, tmp_req.rate, best_rate)) { - best_rate = tmp_req.rate; - best_parent_rate = parent_rate; + if (ccu_is_better_rate(common, req->rate, rate, best_rate)) { + best_rate = rate; + best_parent_rate = tmp_req.best_parent_rate; best_parent = parent; } } -- 2.53.0