From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
To: Maxime Ripard <maxime@cerno.tech>
Cc: Mike Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>,
Dave Stevenson <dave.stevenson@raspberrypi.com>,
Phil Elwell <phil@raspberrypi.com>,
Tim Gover <tim.gover@raspberrypi.com>,
Dom Cobley <dom@raspberrypi.com>,
dri-devel@lists.freedesktop.org, linux-clk@vger.kernel.org,
linux-tegra@vger.kernel.org
Subject: Re: [PATCH v7 06/12] clk: Always set the rate on clk_set_range_rate
Date: Thu, 24 Mar 2022 22:25:26 +0300 [thread overview]
Message-ID: <d7a5216a-5092-e051-0850-2e054e0b1275@collabora.com> (raw)
In-Reply-To: <20220323085140.ifeclmttkrqo55ru@houat>
On 3/23/22 11:51, Maxime Ripard wrote:
> Hi,
>
> On Tue, Mar 22, 2022 at 10:05:56PM +0300, Dmitry Osipenko wrote:
>> On 2/25/22 17:35, Maxime Ripard wrote:
>>> When we change a clock minimum or maximum using clk_set_rate_range(),
>>> clk_set_min_rate() or clk_set_max_rate(), the current code will only
>>> trigger a new rate change if the rate is outside of the new boundaries.
>>>
>>> However, a clock driver might want to always keep the clock rate to
>>> one of its boundary, for example the minimum to keep the power
>>> consumption as low as possible.
>>>
>>> Since they don't always get called though, clock providers don't have the
>>> opportunity to implement this behaviour.
>>>
>>> Let's trigger a clk_set_rate() on the previous requested rate every time
>>> clk_set_rate_range() is called. That way, providers that care about the
>>> new boundaries have a chance to adjust the rate, while providers that
>>> don't care about those new boundaries will return the same rate than
>>> before, which will be ignored by clk_set_rate() and won't result in a
>>> new rate change.
>>>
>>> Suggested-by: Stephen Boyd <sboyd@kernel.org>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>> drivers/clk/clk.c | 45 ++++++++++++++++----------------
>>> drivers/clk/clk_test.c | 58 +++++++++++++++++++-----------------------
>>> 2 files changed, 49 insertions(+), 54 deletions(-)
>>>
>>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>>> index c15ee5070f52..9bc8bf434b94 100644
>>> --- a/drivers/clk/clk.c
>>> +++ b/drivers/clk/clk.c
>>> @@ -2373,28 +2373,29 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
>>> goto out;
>>> }
>>>
>>> - rate = clk_core_get_rate_nolock(clk->core);
>>> - if (rate < min || rate > max) {
>>> - /*
>>> - * FIXME:
>>> - * We are in bit of trouble here, current rate is outside the
>>> - * the requested range. We are going try to request appropriate
>>> - * range boundary but there is a catch. It may fail for the
>>> - * usual reason (clock broken, clock protected, etc) but also
>>> - * because:
>>> - * - round_rate() was not favorable and fell on the wrong
>>> - * side of the boundary
>>> - * - the determine_rate() callback does not really check for
>>> - * this corner case when determining the rate
>>> - */
>>> -
>>> - rate = clamp(clk->core->req_rate, min, max);
>>> - ret = clk_core_set_rate_nolock(clk->core, rate);
>>> - if (ret) {
>>> - /* rollback the changes */
>>> - clk->min_rate = old_min;
>>> - clk->max_rate = old_max;
>>> - }
>>> + /*
>>> + * Since the boundaries have been changed, let's give the
>>> + * opportunity to the provider to adjust the clock rate based on
>>> + * the new boundaries.
>>> + *
>>> + * We also need to handle the case where the clock is currently
>>> + * outside of the boundaries. Clamping the last requested rate
>>> + * to the current minimum and maximum will also handle this.
>>> + *
>>> + * FIXME:
>>> + * There is a catch. It may fail for the usual reason (clock
>>> + * broken, clock protected, etc) but also because:
>>> + * - round_rate() was not favorable and fell on the wrong
>>> + * side of the boundary
>>> + * - the determine_rate() callback does not really check for
>>> + * this corner case when determining the rate
>>> + */
>>> + rate = clamp(clk->core->req_rate, min, max);
>>> + ret = clk_core_set_rate_nolock(clk->core, rate);
>>> + if (ret) {
>>> + /* rollback the changes */
>>> + clk->min_rate = old_min;
>>> + clk->max_rate = old_max;
>>> }
>>>
>>> out:
>>
>> NVIDIA Tegra30 no longer boots with this change.
>>
>> You can't assume that rate was requested by clk_set_rate() before
>> clk_set_rate_range() is called, see what [1] does.
>
> We don't, and it would be bad indeed.
>
> We even have (multiple) tests to cover that case:
> https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git/tree/drivers/clk/clk_test.c?h=clk-range&id=a9b269310ad9abb2f206fe814fd3afcadddce3aa#n242
>
>> T30 memory rate now drops to min on boot when clk debug range is
>> inited innocuously and CPU no longer can make any progress because
>> display controller takes out whole memory bandwidth.
>>
>> [1]
>> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/drivers/memory/tegra/tegra30-emc.c#n1437
>>
>> If clk_set_rate() wasn't ever invoked and req_rate=0, then you must not
>> change the clk rate if it's within the new range. Please revert this
>> patch, thanks.
>
> The whole point of this patch is to give an opportunity to every driver
> to change the rate whenever the boundaries have changed, so we very much
> want to have the option to change it if clk_set_rate() has never been
> called.
>
> However, I think the issue is why req_rate would be 0 in the first
> place?
>
> req_rate is initialized to what recalc_rate returns:
> https://elixir.bootlin.com/linux/latest/source/drivers/clk/clk.c#L3607
>
> So the case where req_rate is 0 shouldn't occur unless you had an
> explicit clk_set_rate to 0, or if your clock was orphaned at some point.
>
> Judging from the code, it seems like the latter is the most plausible.
> Indeed, __clk_core_init() will set req_rate to 0 if the clock is
> orphaned (just like rate and accuracy), and
> clk_core_reparent_orphans_nolock will be in charge of updating them when
> the clock is no longer an orphan.
>
> However, clk_core_reparent_orphans_nolock() will update rate by calling
> __clk_recalc_rate and accuracy by calling __clk_recalc_accuracies, but
> it never sets req_rate.
>
> I'm not sure if this is the right patch, Stephen will tell, but could
> you test:
>
> ------------------------ >8 ------------------------
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 9bc8bf434b94..c43340afedee 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -3479,6 +3479,7 @@ static void clk_core_reparent_orphans_nolock(void)
> __clk_set_parent_after(orphan, parent, NULL);
> __clk_recalc_accuracies(orphan);
> __clk_recalc_rates(orphan, 0);
> + orphan->req_rate = orphan->rate;
> }
> }
> }
>
> ------------------------ >8 ------------------------
It works, thank you!
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> # T30 Nexus7
next prev parent reply other threads:[~2022-03-24 19:25 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-25 14:35 [PATCH v7 00/12] clk: Improve clock range handling Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 01/12] clk: Fix clk_hw_get_clk() when dev is NULL Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 02/12] clk: Introduce Kunit Tests for the framework Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 03/12] clk: Enforce that disjoints limits are invalid Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 04/12] clk: Always clamp the rounded rate Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 05/12] clk: Use clamp instead of open-coding our own Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 06/12] clk: Always set the rate on clk_set_range_rate Maxime Ripard
2022-03-22 19:05 ` Dmitry Osipenko
2022-03-23 8:51 ` Maxime Ripard
2022-03-24 19:09 ` Stephen Boyd
2022-03-24 19:25 ` Dmitry Osipenko [this message]
2022-02-25 14:35 ` [PATCH v7 07/12] clk: Add clk_drop_range Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 08/12] clk: bcm: rpi: Add variant structure Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 09/12] clk: bcm: rpi: Set a default minimum rate Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 10/12] clk: bcm: rpi: Run some clocks at the minimum rate allowed Maxime Ripard
2022-02-25 14:35 ` [PATCH v7 11/12] drm/vc4: Add logging and comments Maxime Ripard
2022-04-06 8:50 ` Thomas Zimmermann
2022-02-25 14:35 ` [PATCH v7 12/12] drm/vc4: hdmi: Remove clock rate initialization Maxime Ripard
2022-04-06 8:53 ` Thomas Zimmermann
2022-03-12 3:08 ` [PATCH v7 00/12] clk: Improve clock range handling Stephen Boyd
2022-03-16 8:37 ` Maxime Ripard
2022-04-06 10:42 ` Maxime Ripard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d7a5216a-5092-e051-0850-2e054e0b1275@collabora.com \
--to=dmitry.osipenko@collabora.com \
--cc=dave.stevenson@raspberrypi.com \
--cc=dom@raspberrypi.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=maxime@cerno.tech \
--cc=mturquette@baylibre.com \
--cc=phil@raspberrypi.com \
--cc=sboyd@kernel.org \
--cc=tim.gover@raspberrypi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox