Message ID | 20240224-mux-v1-1-608cc704ef43@outlook.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-78818-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:a81b:b0:108:e6aa:91d0 with SMTP id bq27csp726557dyb; Fri, 23 Feb 2024 09:19:32 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXI+u0AcG8C5srwPhpwjhyW6P1Vu4Y8cvYcS0+0rqRfG2V5KuYckXjqMQKSc8DEGH1OBwxIlNnn4QO2nYCynb/pSz6TIg== X-Google-Smtp-Source: AGHT+IGWoFW/hP1GoAqKQFOkkHzyx2rrf0h633AyBxNGuQ20eq4F8rH+ERQ6CTiR8FSPUQzvvn/G X-Received: by 2002:a17:90b:1981:b0:29a:6916:a0b6 with SMTP id mv1-20020a17090b198100b0029a6916a0b6mr578126pjb.0.1708708771838; Fri, 23 Feb 2024 09:19:31 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708708771; cv=pass; d=google.com; s=arc-20160816; b=xVriy/EsoSrl598cr4zGNKHTwuFr6wMt84ip36Tr5c0pm8O+WJtHEPCKfl0yeS0HVP MdPbxxGYwzn9QzryL3kxBwlJf2BZx1Ps0tAYvPfVzrgxdasiTQ504ITFqsRgp7xVh2Dk oJVPeh5mjNnmk7bH0eHwtPBUmstTLKCkNefv/UtH9ZKiqViZadl3lgMFJpMYZKJ8SRmT 9hypTei+ZnwkYZHP+rDRo/JEMXTYABFiYvhNkYbCxMQl7fIkYq4Fz+GZtT/F118H7D5i XXnoSNW7/F+S6sz8mfZNVRwpzLKxJS1/ZA1vgPuTatyPpbUZc6/It4KZFKbrOkaoGYyq ZHIQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=reply-to:cc:to:message-id:content-transfer-encoding:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:subject:date :from:dkim-signature; bh=/49QG7Y9ZC8s3ZWt3sAGsAe+4ZBDeDkZ0IMj7Vub35w=; fh=utIdiGrj5Jo6nUagmhsgB1Yak5swVpCUOlGu/v2oCG4=; b=Lu00Njp1vRYrUsUPrjDr9g9Iok9gB07O4GFpQHJqNPuhIurLwn5oTlaBUJRNHJe/Fg BxT0YEcDNlUaGhdKAQj2hGr5Dj6z1AaHEMtY7ICkFY1AlPpq530bNPt8v9F+IKC/tAFx NnFXt0KXCsIUb+IvfKn1MeJrcq8g01iWj9mcH+66Hf587XiqqNyhn1TW3bvaziqmD5Fc QEBWjKpaFdoz/9Ib5P7tIIFVZEaUg8UhnEQ8Xz8kPPSKn1ID8WjIlMDlkPPtrb5WV7aM lL/P9f2OELufQ6WKADUR7fXJ281UrlCH8PFQQqt6VotMjiyGTeMc8AXgKGVct5RUgdKv R1iw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=XF5+3niz; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-78818-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-78818-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id nl11-20020a17090b384b00b0029a744ab5fdsi1493099pjb.29.2024.02.23.09.19.31 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Feb 2024 09:19:31 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-78818-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=XF5+3niz; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-78818-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-78818-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id A4DAB28760F for <ouuuleilei@gmail.com>; Fri, 23 Feb 2024 17:19:31 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BD71512CD95; Fri, 23 Feb 2024 17:18:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XF5+3niz" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 0E1961272D8; Fri, 23 Feb 2024 17:18:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708708734; cv=none; b=dPO1rSBLIbRQOyvu5zwTIQkiOtW57uJ0oBWaBX3hNXiBFVvgTJwJ8s2Xg8xL1LtPQFwGX+RzMzqXjG5nczkdk4BBjP3BhT+ldIZrDAGn+bQaNHd9ciiVXoUGPnsZj/beaWE2/FyqobWiNtPNnQtCVMm3OkUhn4GvrOZ79ona3vs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708708734; c=relaxed/simple; bh=jPhUX7fseszIBa5Cz4g6HtJ32wY5HpFdNrxQegeyAcU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=dFmsDUeyNEoVTc19/r/SidKfDQTtreNccp0L2lZoQbS37N/TsstN2lIHmVnSSOTmctnLWcO2z47ZllSorUb5vG8MmFowugSdswERQJeL+IOcpfDN1i4Qqo9C6B90WDC538xY4RLjkqHMxo83QC6uifw9qdwWt76WdOHgJT3YWxM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XF5+3niz; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPS id 8925FC433C7; Fri, 23 Feb 2024 17:18:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708708733; bh=jPhUX7fseszIBa5Cz4g6HtJ32wY5HpFdNrxQegeyAcU=; h=From:Date:Subject:To:Cc:Reply-To:From; b=XF5+3niz1AvIp05ztwt2NQuB8gytrjZBE9VbVU8Ge59jvkl6U8I3PaXf0sVbfcngD xJ4HlxqQYpl8bI4RG/SlwpYKhMmwreT7RUEkLphSee8uogcE0N80IBCGPRalXX38+E cU9kANXDxFRDDMGmUmk5BMcu/dKC4FpINudh3wpOcsPKq30XS3TE30gaOSyFZ/rqdh oY4807xtUmjPO6MKY7q4AEVze03XjL0sDRE49QHiHyNxXNW7qqDwnvzNslgF++1CsF jtZqeMPuVrLO8L3m3SlGOt39gPrvZ80/59fajymbUOVLITGYsS/Q5KZrDF3gsDtje3 WWOE0egbf/Jsw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75F77C5478C; Fri, 23 Feb 2024 17:18:53 +0000 (UTC) From: Yang Xiwen via B4 Relay <devnull+forbidden405.outlook.com@kernel.org> Date: Sat, 24 Feb 2024 01:18:52 +0800 Subject: [PATCH RESEND] clk: set initial best mux parent to current parent when determining rate Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240224-mux-v1-1-608cc704ef43@outlook.com> To: Michael Turquette <mturquette@baylibre.com>, Stephen Boyd <sboyd@kernel.org> Cc: linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Yang Xiwen <forbidden405@outlook.com> X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=ed25519-sha256; t=1708708732; l=1451; i=forbidden405@outlook.com; s=20230724; h=from:subject:message-id; bh=fggch9mxMQ8SzPlFXnQcVvzDJCD3ro+vLZXoDYu1RGE=; b=WdFzW2xYhaZML01H7Wn3y7hOtv/t49Ffr8hwuamJTDM1SyPptIImRnP9E/eEQE/s1XsHe1wfJ I2CNZM08YmmCIAk+hVTmfKzxwd98Rl8RXD3aRxo0wP4bLDZ+v0hboHu X-Developer-Key: i=forbidden405@outlook.com; a=ed25519; pk=qOD5jhp891/Xzc+H/PZ8LWVSWE3O/XCQnAg+5vdU2IU= X-Endpoint-Received: by B4 Relay for forbidden405@outlook.com/20230724 with auth_id=67 X-Original-From: Yang Xiwen <forbidden405@outlook.com> Reply-To: <forbidden405@outlook.com> X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791711008823008635 X-GMAIL-MSGID: 1791711008823008635 |
Series |
[RESEND] clk: set initial best mux parent to current parent when determining rate
|
|
Commit Message
Yang Xiwen via B4 Relay
Feb. 23, 2024, 5:18 p.m. UTC
From: Yang Xiwen <forbidden405@outlook.com> Originally, the initial clock rate is hardcoded to 0, this can lead to some problem when setting a very small rate with CLK_MUX_ROUND_NEAREST. For example, if the lowest possible rate privided by the mux is 1000Hz, setting a rate below 500Hz will fail, because no clock can provide a better rate than the non-existant 0. But it should succeed with 1000Hz being set. Setting the initial best parent to current parent could solve this bug very well. Signed-off-by: Yang Xiwen <forbidden405@outlook.com> --- This is actually a v2 of [1], but seems too simple to have a unittest. It's tested in a mmc host driver. [1]: https://lore.kernel.org/linux-clk/20230421-clk-v3-1-9ff79e7e7fed@outlook.com/ --- drivers/clk/clk.c | 4 ++++ 1 file changed, 4 insertions(+) --- base-commit: 8d3dea210042f54b952b481838c1e7dfc4ec751d change-id: 20240215-mux-6db8b3714590 Best regards,
Comments
Quoting Yang Xiwen via B4 Relay (2024-02-23 09:18:52) > From: Yang Xiwen <forbidden405@outlook.com> > > Originally, the initial clock rate is hardcoded to 0, this can lead to > some problem when setting a very small rate with CLK_MUX_ROUND_NEAREST. Did you mean CLK_MUX_ROUND_CLOSEST? > > For example, if the lowest possible rate privided by the mux is 1000Hz, s/privided/provided/ > setting a rate below 500Hz will fail, because no clock can provide a > better rate than the non-existant 0. But it should succeed with 1000Hz > being set. > > Setting the initial best parent to current parent could solve this bug > very well. > > Signed-off-by: Yang Xiwen <forbidden405@outlook.com> > --- > This is actually a v2 of [1], but seems too simple to have a unittest. > It's tested in a mmc host driver. It's not too simple for a unittest. > > [1]: https://lore.kernel.org/linux-clk/20230421-clk-v3-1-9ff79e7e7fed@outlook.com/ In that thread I asked you to please Cc Maxime. Please do that. > --- > drivers/clk/clk.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c > index 2253c154a824..d98cebd7ff03 100644 > --- a/drivers/clk/clk.c > +++ b/drivers/clk/clk.c > @@ -649,6 +649,10 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw, > > /* find the parent that can provide the fastest rate <= rate */ > num_parents = core->num_parents; > + if (core->parent) { > + best_parent = core->parent; > + best = clk_core_get_rate_nolock(best_parent); > + } Is the problem that we're not using abs_diff()? ----8<---- diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index a3bc7fb90d0f..91023345595f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -542,7 +542,7 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, unsigned long best, unsigned long flags) { if (flags & CLK_MUX_ROUND_CLOSEST) - return abs(now - rate) < abs(best - rate); + return abs_diff(now, rate) < abs_diff(best, rate); return now <= rate && now > best; }
On 2/29/2024 9:58 AM, Stephen Boyd wrote: > Quoting Yang Xiwen via B4 Relay (2024-02-23 09:18:52) >> From: Yang Xiwen <forbidden405@outlook.com> >> >> Originally, the initial clock rate is hardcoded to 0, this can lead to >> some problem when setting a very small rate with CLK_MUX_ROUND_NEAREST. > > Did you mean CLK_MUX_ROUND_CLOSEST? You are right :). > >> >> For example, if the lowest possible rate privided by the mux is 1000Hz, > > s/privided/provided/ > >> setting a rate below 500Hz will fail, because no clock can provide a >> better rate than the non-existant 0. But it should succeed with 1000Hz >> being set. >> >> Setting the initial best parent to current parent could solve this bug >> very well. >> >> Signed-off-by: Yang Xiwen <forbidden405@outlook.com> >> --- >> This is actually a v2 of [1], but seems too simple to have a unittest. >> It's tested in a mmc host driver. > > It's not too simple for a unittest. > >> >> [1]: https://lore.kernel.org/linux-clk/20230421-clk-v3-1-9ff79e7e7fed@outlook.com/ > > In that thread I asked you to please Cc Maxime. Please do that. > >> --- >> drivers/clk/clk.c | 4 ++++ >> 1 file changed, 4 insertions(+) >> >> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c >> index 2253c154a824..d98cebd7ff03 100644 >> --- a/drivers/clk/clk.c >> +++ b/drivers/clk/clk.c >> @@ -649,6 +649,10 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw, >> >> /* find the parent that can provide the fastest rate <= rate */ >> num_parents = core->num_parents; >> + if (core->parent) { >> + best_parent = core->parent; >> + best = clk_core_get_rate_nolock(best_parent); >> + } > > Is the problem that we're not using abs_diff()? No, i think. It has nothing to do with the code here. It's because of the initial best_parent/best_parent_rate. > > ----8<---- > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c > index a3bc7fb90d0f..91023345595f 100644 > --- a/drivers/clk/clk.c > +++ b/drivers/clk/clk.c > @@ -542,7 +542,7 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, > unsigned long best, unsigned long flags) > { > if (flags & CLK_MUX_ROUND_CLOSEST) > - return abs(now - rate) < abs(best - rate); > + return abs_diff(now, rate) < abs_diff(best, rate); Without this patch, the initial `best` rate would be always 0. This is wrong for most cases, 0Hz might (usually) be unavailable. We should use a valid rate(i.e. current rate) initially. > > return now <= rate && now > best; > }
Quoting Yang Xiwen (2024-02-28 18:13:04) > On 2/29/2024 9:58 AM, Stephen Boyd wrote: > > Quoting Yang Xiwen via B4 Relay (2024-02-23 09:18:52) > >> From: Yang Xiwen <forbidden405@outlook.com> > >> > >> Originally, the initial clock rate is hardcoded to 0, this can lead to > >> some problem when setting a very small rate with CLK_MUX_ROUND_NEAREST. > > > > Did you mean CLK_MUX_ROUND_CLOSEST? > > You are right :). > > > > >> > >> For example, if the lowest possible rate privided by the mux is 1000Hz, > > > > s/privided/provided/ > > > >> setting a rate below 500Hz will fail, because no clock can provide a > >> better rate than the non-existant 0. But it should succeed with 1000Hz > >> being set. > >> > >> Setting the initial best parent to current parent could solve this bug > >> very well. > >> > >> Signed-off-by: Yang Xiwen <forbidden405@outlook.com> > >> --- > >> This is actually a v2 of [1], but seems too simple to have a unittest. > >> It's tested in a mmc host driver. > > > > It's not too simple for a unittest. > > > >> > >> [1]: https://lore.kernel.org/linux-clk/20230421-clk-v3-1-9ff79e7e7fed@outlook.com/ > > > > In that thread I asked you to please Cc Maxime. Please do that. > > > >> --- > >> drivers/clk/clk.c | 4 ++++ > >> 1 file changed, 4 insertions(+) > >> > >> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c > >> index 2253c154a824..d98cebd7ff03 100644 > >> --- a/drivers/clk/clk.c > >> +++ b/drivers/clk/clk.c > >> @@ -649,6 +649,10 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw, > >> > >> /* find the parent that can provide the fastest rate <= rate */ > >> num_parents = core->num_parents; > >> + if (core->parent) { > >> + best_parent = core->parent; > >> + best = clk_core_get_rate_nolock(best_parent); > >> + } > > > > Is the problem that we're not using abs_diff()? > > > No, i think. It has nothing to do with the code here. It's because of > the initial best_parent/best_parent_rate. Alright. > > > > > ----8<---- > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c > > index a3bc7fb90d0f..91023345595f 100644 > > --- a/drivers/clk/clk.c > > +++ b/drivers/clk/clk.c > > @@ -542,7 +542,7 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, > > unsigned long best, unsigned long flags) > > { > > if (flags & CLK_MUX_ROUND_CLOSEST) > > - return abs(now - rate) < abs(best - rate); > > + return abs_diff(now, rate) < abs_diff(best, rate); > > Without this patch, the initial `best` rate would be always 0. This is > wrong for most cases, 0Hz might (usually) be unavailable. We should use > a valid rate(i.e. current rate) initially. Ok. But you set best to the parent rate. So why not use 'core->rate' directly as 'best'?
On 2/29/2024 10:25 AM, Stephen Boyd wrote: > Quoting Yang Xiwen (2024-02-28 18:13:04) >> On 2/29/2024 9:58 AM, Stephen Boyd wrote: >>> Quoting Yang Xiwen via B4 Relay (2024-02-23 09:18:52) >>>> From: Yang Xiwen <forbidden405@outlook.com> >>>> >>>> Originally, the initial clock rate is hardcoded to 0, this can lead to >>>> some problem when setting a very small rate with CLK_MUX_ROUND_NEAREST. >>> >>> Did you mean CLK_MUX_ROUND_CLOSEST? >> >> You are right :). >> >>> >>>> >>>> For example, if the lowest possible rate privided by the mux is 1000Hz, >>> >>> s/privided/provided/ >>> >>>> setting a rate below 500Hz will fail, because no clock can provide a >>>> better rate than the non-existant 0. But it should succeed with 1000Hz >>>> being set. >>>> >>>> Setting the initial best parent to current parent could solve this bug >>>> very well. >>>> >>>> Signed-off-by: Yang Xiwen <forbidden405@outlook.com> >>>> --- >>>> This is actually a v2 of [1], but seems too simple to have a unittest. >>>> It's tested in a mmc host driver. >>> >>> It's not too simple for a unittest. >>> >>>> >>>> [1]: https://lore.kernel.org/linux-clk/20230421-clk-v3-1-9ff79e7e7fed@outlook.com/ >>> >>> In that thread I asked you to please Cc Maxime. Please do that. >>> >>>> --- >>>> drivers/clk/clk.c | 4 ++++ >>>> 1 file changed, 4 insertions(+) >>>> >>>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c >>>> index 2253c154a824..d98cebd7ff03 100644 >>>> --- a/drivers/clk/clk.c >>>> +++ b/drivers/clk/clk.c >>>> @@ -649,6 +649,10 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw, >>>> >>>> /* find the parent that can provide the fastest rate <= rate */ >>>> num_parents = core->num_parents; >>>> + if (core->parent) { >>>> + best_parent = core->parent; >>>> + best = clk_core_get_rate_nolock(best_parent); >>>> + } >>> >>> Is the problem that we're not using abs_diff()? >> >> >> No, i think. It has nothing to do with the code here. It's because of >> the initial best_parent/best_parent_rate. > > Alright. > >> >>> >>> ----8<---- >>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c >>> index a3bc7fb90d0f..91023345595f 100644 >>> --- a/drivers/clk/clk.c >>> +++ b/drivers/clk/clk.c >>> @@ -542,7 +542,7 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, >>> unsigned long best, unsigned long flags) >>> { >>> if (flags & CLK_MUX_ROUND_CLOSEST) >>> - return abs(now - rate) < abs(best - rate); >>> + return abs_diff(now, rate) < abs_diff(best, rate); >> >> Without this patch, the initial `best` rate would be always 0. This is >> wrong for most cases, 0Hz might (usually) be unavailable. We should use >> a valid rate(i.e. current rate) initially. > > Ok. But you set best to the parent rate. So why not use 'core->rate' > directly as 'best'? I can't remember exactly. I just add this piece of code and found it's working. Is this field already filled prior to setting rate? Anyway, your suggestion is very reasonable. Maybe dear clk maintainers can fix it as i'm not familiar with clk core code.
Quoting Yang Xiwen (2024-02-28 18:33:11) > On 2/29/2024 10:25 AM, Stephen Boyd wrote: > >>> > >>> Is the problem that we're not using abs_diff()? > >> > >> > >> No, i think. It has nothing to do with the code here. It's because of > >> the initial best_parent/best_parent_rate. > > > > Alright. I will have to fix this as well in a different patch. > > > >> > >>> > >>> ----8<---- > >>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c > >>> index a3bc7fb90d0f..91023345595f 100644 > >>> --- a/drivers/clk/clk.c > >>> +++ b/drivers/clk/clk.c > >>> @@ -542,7 +542,7 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, > >>> unsigned long best, unsigned long flags) > >>> { > >>> if (flags & CLK_MUX_ROUND_CLOSEST) > >>> - return abs(now - rate) < abs(best - rate); > >>> + return abs_diff(now, rate) < abs_diff(best, rate); > >> > >> Without this patch, the initial `best` rate would be always 0. This is > >> wrong for most cases, 0Hz might (usually) be unavailable. We should use > >> a valid rate(i.e. current rate) initially. > > > > Ok. But you set best to the parent rate. So why not use 'core->rate' > > directly as 'best'? > > > I can't remember exactly. I just add this piece of code and found it's > working. Is this field already filled prior to setting rate? Anyway, > your suggestion is very reasonable. Maybe dear clk maintainers can fix > it as i'm not familiar with clk core code. Yes the 'struct clk_rate_request' is pre-filled with many details, including the rate of the clk and the current parent rate and parent hw pointer. I'm pretty sure you're trying to fix this fixme from clk_test.c static const struct clk_ops clk_dummy_single_parent_ops = { /* * FIXME: Even though we should probably be able to use * __clk_mux_determine_rate() here, if we use it and call * clk_round_rate() or clk_set_rate() with a rate lower than * what all the parents can provide, it will return -EINVAL. * * This is due to the fact that it has the undocumented * behaviour to always pick up the closest rate higher than the * requested rate. If we get something lower, it thus considers * that it's not acceptable and will return an error. * * It's somewhat inconsistent and creates a weird threshold * between rates above the parent rate which would be rounded to * what the parent can provide, but rates below will simply * return an error. */
On 3/1/2024 9:42 AM, Stephen Boyd wrote: > Quoting Yang Xiwen (2024-02-28 18:33:11) >> On 2/29/2024 10:25 AM, Stephen Boyd wrote: >>>>> >>>>> Is the problem that we're not using abs_diff()? >>>> >>>> >>>> No, i think. It has nothing to do with the code here. It's because of >>>> the initial best_parent/best_parent_rate. >>> >>> Alright. > > I will have to fix this as well in a different patch. > >>> >>>> >>>>> >>>>> ----8<---- >>>>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c >>>>> index a3bc7fb90d0f..91023345595f 100644 >>>>> --- a/drivers/clk/clk.c >>>>> +++ b/drivers/clk/clk.c >>>>> @@ -542,7 +542,7 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now, >>>>> unsigned long best, unsigned long flags) >>>>> { >>>>> if (flags & CLK_MUX_ROUND_CLOSEST) >>>>> - return abs(now - rate) < abs(best - rate); >>>>> + return abs_diff(now, rate) < abs_diff(best, rate); >>>> >>>> Without this patch, the initial `best` rate would be always 0. This is >>>> wrong for most cases, 0Hz might (usually) be unavailable. We should use >>>> a valid rate(i.e. current rate) initially. >>> >>> Ok. But you set best to the parent rate. So why not use 'core->rate' >>> directly as 'best'? >> >> >> I can't remember exactly. I just add this piece of code and found it's >> working. Is this field already filled prior to setting rate? Anyway, >> your suggestion is very reasonable. Maybe dear clk maintainers can fix >> it as i'm not familiar with clk core code. > > Yes the 'struct clk_rate_request' is pre-filled with many details, > including the rate of the clk and the current parent rate and parent hw > pointer. I'm pretty sure you're trying to fix this fixme from clk_test.c > > static const struct clk_ops clk_dummy_single_parent_ops = { > /* > * FIXME: Even though we should probably be able to use > * __clk_mux_determine_rate() here, if we use it and call > * clk_round_rate() or clk_set_rate() with a rate lower than > * what all the parents can provide, it will return -EINVAL. > * > * This is due to the fact that it has the undocumented > * behaviour to always pick up the closest rate higher than the > * requested rate. If we get something lower, it thus considers > * that it's not acceptable and will return an error. > * > * It's somewhat inconsistent and creates a weird threshold > * between rates above the parent rate which would be rounded to > * what the parent can provide, but rates below will simply > * return an error. > */ If CLK_MUX_ROUND_CLOSEST is not specified, I think both setting lowest possible rate and returning -EINVAL are okay, just as documented(It will ONLY return a rate lower or equal to the rate requested). But if CLK_MUX_ROUND_CLOSEST is specified, the behavior would be wrong in no doubt. I don't know which behavior consumers would expect. Maybe some consumer code has already been relying on this (undocumented) behavior. This patch indeed also has an influence on clocks without CLK_MUX_ROUND_CLOSEST. So you are right, I'll have to fix doc for clk_mux_determine_rate too.
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2253c154a824..d98cebd7ff03 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -649,6 +649,10 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw, /* find the parent that can provide the fastest rate <= rate */ num_parents = core->num_parents; + if (core->parent) { + best_parent = core->parent; + best = clk_core_get_rate_nolock(best_parent); + } for (i = 0; i < num_parents; i++) { unsigned long parent_rate;