Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Vyacheslav Yurkov" <V.Yurkov.EXT@bruker.com>
Cc: conor+dt@kernel.org, devicetree@vger.kernel.org, robh@kernel.org
Subject: Re: [PATCH v4 2/2] clk: Add gpio-locked fixed clock driver
Date: Sun, 26 Jul 2026 17:51:26 +0000	[thread overview]
Message-ID: <20260726175127.67B171F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260726-feature-clock-guard-v4-2-e9c8b372b71c@bruker.com>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] The `.is_enabled` callback completely inverts the clock status logic, returning error codes instead of boolean state.
- [High] The driver attempts to aggregate multiple dependent input clocks by registering them as CCF parents, causing a TOCTOU race and failing to enable parents.
- [High] Using local DT connection IDs to populate `init.parent_names` causes global clock matching to fail and risks NULL pointer dereferences.
- [High] The `enable` callback returns `-EBUSY` immediately rather than waiting for the hardware lock, contradicting CCF semantics.
- [High] The driver requests the lock GPIOs with `GPIOD_ASIS` rather than `GPIOD_IN`, potentially failing to read the pin state correctly.
- [High] The driver fails to validate that provided GPIOs are non-sleeping, risking a kernel panic if slow GPIO controllers are used.
- [Medium] Calling `dev_warn` from a spinlocked, atomic context causes severe latencies.
--

--- Patch [2]: [PATCH v4 2/2] clk: Add gpio-locked fixed clock driver ---
commit 86eabe35b2750726ea6024147b3e2f51a67773ca
Author: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>

clk: Add gpio-locked fixed clock driver

This commit introduces a new clock driver that aggregates input clocks and
GPIOs to expose a clock-valid/PLL-lock status for FPGA-assisted clocking
designs.

> diff --git a/drivers/clk/clk-gpio-locked.c b/drivers/clk/clk-gpio-locked.c
> new file mode 100644
> index 0000000000000..79098f9b65326
> --- /dev/null
> +++ b/drivers/clk/clk-gpio-locked.c
> @@ -0,0 +1,306 @@
[ ... ]
> +static int is_gpio_ready(struct gpio_locked_clk_priv *priv)
> +{
> +	unsigned long values[BITS_TO_LONGS(MAX_INPUT_GPIO_COUNT)] = {0};
> +	int ret = 0;
[ ... ]
> +	for (int i = 0; i < priv->gpios->ndescs; i++) {
> +		if (!test_bit(i, values)) {
> +			dev_warn(priv->dev, "GPIO %s is not ready", priv->gpio_names[i]);

[Severity: Medium]
Is it safe to call dev_warn() while holding the clock framework's enable_lock?

Because is_gpio_ready() is called from the .enable and .is_enabled callbacks,
it executes under a spinlock with hard interrupts disabled. Unconditionally
logging to the console from this context can cause severe IRQ latencies or
hard lockups, especially if a consumer polls the clock state.

> +			return -EBUSY;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int gpio_locked_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct gpio_locked_clk_priv *priv = to_gpio_locked_clk_priv(hw);
> +	int ret = 0;
> +
> +	if (priv->num_gpios > 0) {
> +		ret = is_gpio_ready(priv);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	// Now check for the clocks
> +	for (int i = 0; i < priv->num_clks; i++) {
> +		struct clk_hw *hw_clk = __clk_get_hw(priv->clks[i].clk);
> +
> +		if (!clk_hw_is_enabled(hw_clk)) {
> +			dev_dbg(priv->dev, "Clock %i (%s) is not ready",
> +				i, priv->clks[i].id);
> +			return -EBUSY;
> +		}
> +	}
> +
> +	return 0;

[Severity: Critical]
Does this function invert the expected return logic for .is_enabled?

The clock framework expects .is_enabled to return a non-zero value when the
clock is enabled, and 0 when it is disabled. By returning -EBUSY when not
ready and 0 when ready, the framework will consider the clock enabled when
it is actually not ready, and disabled when it is ready.

> +}
> +
> +/* We can't enable the clock, but the Common Clock Framework calls only
> + * enable() not is_enabled()
> + */
> +static int gpio_locked_clk_enable(struct clk_hw *hw)
> +{
> +	return gpio_locked_clk_is_enabled(hw);

[Severity: High]
Should the enable callback block until the hardware lock is acquired?

Standard clock consumers do not poll clk_prepare_enable(). By doing a single
non-blocking check and failing immediately with -EBUSY, consumer driver probes
will fail if the hardware lock is not instantaneously ready at the moment of
enablement.

> +}
> +
> +/* We have to implement it, but we are not going to control
> + * parent clock selection
> + */
> +static u8 gpio_locked_clk_get_parent(struct clk_hw *hw)
> +{
> +	return 0;

[Severity: High]
Does hardcoding the parent to index 0 break the aggregation of multiple inputs?

When a clock is registered with num_parents > 1 and implements get_parent,
the clock framework treats it as a multiplexer where only one parent is active.

By always returning 0, the framework is told to abandon tracking for all other
parents. This means parents 1 through N will not be enabled when this clock
is enabled.

> +}
> +
> +static const struct clk_ops gpio_locked_clk_ops = {
> +	.enable =	gpio_locked_clk_enable,
> +	.is_enabled =	gpio_locked_clk_is_enabled,
> +	.get_parent =	gpio_locked_clk_get_parent,
> +};
[ ... ]
> +static int gpio_locked_clk_parse_gpios(struct gpio_locked_clk_priv *priv)
> +{
> +	struct device *dev = priv->dev;
> +	struct device_node *np = dev->of_node;
> +	int i;
> +
> +	priv->gpios = devm_gpiod_get_array_optional(dev, "locked", GPIOD_ASIS);

[Severity: High]
Could requesting the GPIO array with GPIOD_ASIS leave the pins in an undefined
state?

Without enforcing the input direction using GPIOD_IN, the hardware
configuration relies on the bootloader. If the bootloader leaves the pins
floating or configured as outputs, reading the pin state may fail to detect
the lock correctly.

[Severity: High]
Does the driver need to verify that these GPIOs are non-sleeping?

The clock framework's .enable and .is_enabled callbacks run in an atomic
context with interrupts disabled. If the device tree provides a sleeping GPIO
(such as an I2C or SPI expander), calling gpiod_get_array_value() from
is_gpio_ready() will trigger a scheduling-while-atomic BUG.

Could the probe function check !gpiod_cansleep() to reject sleeping GPIOs?

> +	if (IS_ERR(priv->gpios)) {
> +		dev_err(dev, "failed to get GPIO array: %ld\n",
> +				PTR_ERR(priv->gpios));
[ ... ]
> +static int gpio_locked_clk_parse_outputs(struct gpio_locked_clk_priv *priv)
> +{
> +	struct device *dev = priv->dev;
> +	struct device_node *np = dev->of_node;
> +	struct clk_init_data init = {};
> +	int ret;
[ ... ]
> +	init.flags = 0;
> +	init.num_parents = priv->num_clks;
> +
> +	if (priv->num_clks) {
> +		const char **parent_names;
> +		int j;
> +
> +		parent_names = devm_kcalloc(dev, priv->num_clks,
> +					    sizeof(*parent_names),
> +					    GFP_KERNEL);
> +		if (!parent_names)
> +			return -ENOMEM;
> +
> +		for (j = 0; j < priv->num_clks; j++)
> +			parent_names[j] = priv->clks[j].id;

[Severity: High]
Does this assignment pass local device tree connection IDs to the clock
framework instead of globally registered provider names?

During probe, devm_clk_bulk_get_all() populates the id field with local
consumer names from the device tree. The clock framework expects
init.parent_names to contain global provider names. This mismatch will
cause the output clock to fail to match its parents.

Additionally, if the optional clock-names property is missing in the DT,
priv->clks[j].id will be NULL, causing a NULL pointer dereference when the
framework evaluates init.parent_names.

> +
> +		init.parent_names = parent_names;
> +	}
> +
> +	priv->output_hw_clk.init = &init;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260726-feature-clock-guard-v4-0-e9c8b372b71c@bruker.com?part=2

      reply	other threads:[~2026-07-26 17:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-26 17:40 [PATCH v4 0/2] A proposal to add a gpio-locked fixed clock driver Vyacheslav Yurkov via B4 Relay
2026-07-26 17:40 ` [PATCH v4 1/2] dt-bindings: Add GPIO-locked fixed clock Vyacheslav Yurkov via B4 Relay
2026-07-26 17:45   ` sashiko-bot
2026-07-26 17:40 ` [PATCH v4 2/2] clk: Add gpio-locked fixed clock driver Vyacheslav Yurkov via B4 Relay
2026-07-26 17:51   ` sashiko-bot [this message]

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=20260726175127.67B171F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=V.Yurkov.EXT@bruker.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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