From: Christian Marangi <ansuelsmth@gmail.com>
To: Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>,
linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Miquel Raynal <miquel.raynal@bootlin.com>,
Jerome Brunet <jbrunet@baylibre.com>,
Russell King <linux@armlinux.org.uk>,
Jeffrey Hugo <jhugo@codeaurora.org>, Chen-Yu Tsai <wens@csie.org>
Subject: Re: [PATCH] clk: Fix wrong clock returned in parent_data with .name and no .index
Date: Thu, 16 Feb 2023 00:34:51 +0100 [thread overview]
Message-ID: <63ed6e27.050a0220.ed51a.aae8@mx.google.com> (raw)
In-Reply-To: <20230215232712.17072-1-ansuelsmth@gmail.com>
On Thu, Feb 16, 2023 at 12:27:12AM +0100, Christian Marangi wrote:
> Commit 601b6e93304a ("clk: Allow parents to be specified via clkspec index")
> introduced a regression due to a "fragile" implementation present in some very
> corner case.
>
> Such commit introduced the support for parents to be specified using
> clkspec index. The index is an int and should be -1 if the feature
> should not be used. This is the case with parent_hws or legacy
> parent_names used and the index value is set to -1 by default.
> With parent_data the situation is different, since it's a struct that
> can have multiple value (.index, .name, .fw_name), it's init to all 0 by
> default. This cause the index value to be set to 0 everytime even if not
> intended to be defined and used.
>
> This simple "fragile" implementation cause side-effect and unintended
> behaviour.
>
> Assuming the following scenario (to repro the corner case and doesn't
> reflect real code):
>
> In dt we have a node like this:
> acc1: clock-controller@2098000 {
> compatible = "qcom,kpss-acc-v1";
> reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
> clock-output-names = "acpu1_aux";
> clocks = <&pxo_board>;
> clock-names = "pxo";
> #clock-cells = <0>;
> };
>
> And on the relevant driver we have the parent data defined as such:
> static const struct clk_parent_data aux_parents[] = {
> { .name = "pll8_vote" },
> { .fw_name = "pxo", .name = "pxo_board" },
> };
>
> Someone would expect the first parent to be globally searched and set to
> point to the clock named "pll8_vote".
> But this is not the case and instead under the hood, the parent point to
> the pxo clock. This happen without any warning and was discovered on
> another platform while the gcc driver was converted to parent_data and
> only .name was defined.
>
> The reason is hard to discover but very simple.
>
> Due to the introduction of index support, clk_core_get() won't return
> -ENOENT but insted will correctly return a clock.
> This is because of_parse_clkspec() will use the index (that is set to 0
> due to how things are allocated) and correctly find in the DT node a
> clock at index 0. That in the provided example is exactly the phandle to
> pxo_board.
>
> Clock is found so the parent is now wrongly linked to the pxo_board
> clock.
>
> This only happens in this specific scenario but it's still worth to be
> handled and currently there are some driver that hardcode the
> parent_data and may suffer from this.
>
> To fix this and handle it correctly we can use the following logic:
> 1. With a .fw_name not defined (index searching is skipped if a named
> clock is provided)
> 2. Check if .name is provided
> 3. Compare the provided .name with what clockspec found
> 4. Return -ENOENT if the name doesn't match, return the clock if it does.
>
> Returning -ENOENT permit clk core code flow to fallback to global
> searching and correctly search the right clock.
>
> Fixes: 601b6e93304a ("clk: Allow parents to be specified via clkspec index")
> Cc: Miquel Raynal <miquel.raynal@bootlin.com>
> Cc: Jerome Brunet <jbrunet@baylibre.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Jeffrey Hugo <jhugo@codeaurora.org>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Think this should also be backported to stable kernel just like it was
done with 4f8c6aba37da199155a121c6cdc38505a9eb0259 ?
> ---
> drivers/clk/clk.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 998676d78029..42e297fcfe45 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -395,6 +395,7 @@ of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
> */
> static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
> {
> + const char *global_name = core->parents[p_index].name;
> const char *name = core->parents[p_index].fw_name;
> int index = core->parents[p_index].index;
> struct clk_hw *hw = ERR_PTR(-ENOENT);
> @@ -407,6 +408,23 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
> !of_parse_clkspec(np, index, name, &clkspec)) {
> hw = of_clk_get_hw_from_clkspec(&clkspec);
> of_node_put(clkspec.np);
> +
> + /*
> + * The returned hw may be incorrect and extra check are required in
> + * some corner case.
> + *
> + * In case a .fw_name is not set of_parse_clkspec will use the index
> + * to search the related clock.
> + * But index may be never set and actually never intended to be used
> + * in the defined parent_data since a 0 value is also accepted and that
> + * is what by default each struct is initialized.
> + *
> + * In the following case check if we have .name and check if the returned
> + * clock name match the globally name defined for the parent in the
> + * parent_data .name value.
> + */
> + if (!name && global_name && strcmp(global_name, hw->core->name))
> + return ERR_PTR(-ENOENT);
> } else if (name) {
> /*
> * If the DT search above couldn't find the provider fallback to
> --
> 2.38.1
>
--
Ansuel
next prev parent reply other threads:[~2023-02-15 23:43 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-15 23:27 [PATCH] clk: Fix wrong clock returned in parent_data with .name and no .index Christian Marangi
2023-02-15 23:34 ` Christian Marangi [this message]
2023-02-17 22:11 ` Stephen Boyd
2023-02-17 5:09 ` Christian Marangi
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=63ed6e27.050a0220.ed51a.aae8@mx.google.com \
--to=ansuelsmth@gmail.com \
--cc=jbrunet@baylibre.com \
--cc=jhugo@codeaurora.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=miquel.raynal@bootlin.com \
--cc=mturquette@baylibre.com \
--cc=sboyd@kernel.org \
--cc=wens@csie.org \
/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