[RFC/PATCH] clk: add lockdep_ignore_clk_prepare_lock cmdline option
From: Marek Szyprowski
Date: Fri Aug 28 2026 - 09:14:42 EST
The clock framework uses a single global re-entrant mutex, prepare_lock,
to serialize all operations on the whole clock tree. It is taken by
nearly every clk API call and it is held while calling into the clock
providers, which in turn often take their own locks or trigger runtime
PM. As a result prepare_lock sits in the middle of a large number of
lock chains and lockdep frequently reports possible circular locking
dependencies involving it.
Such reports are often not real deadlocks, but once the first one is hit
lockdep turns itself off and all subsequent locking problems - including
the ones actually being investigated - are no longer reported.
Add a "lockdep_ignore_clk_prepare_lock" kernel command line parameter,
which marks the prepare_lock class as novalidate, so lockdep skips the
dependency tracking for it and keeps validating the rest of the system.
The option is only available when CONFIG_LOCKDEP is enabled and is meant
purely as a debugging aid.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
---
The problems with clock framework's prepare_lock are well known and
there are machines that always report lockdep issues related to it. A
good example are Khadas VIM3/VIM3l boards, on which prepare_lock
interferes with locks used in PWM subsytem:
https://lore.kernel.org/all/adqtn6iljcguv3m3ovhltusbbf4mljzlwg73yklaudvjjtazxv@vyf5fvuzic6x/
This new cmdline option allows to hide prepare_lock related issues on
the test machines possibly enabling lockdep to catch other issues.
Best regards,
Marek Szyprowski
---
drivers/clk/clk.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fef87167a60b..a5c8c4256102 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -168,6 +168,17 @@ struct clk {
struct hlist_node clks_node;
};
+#ifdef CONFIG_LOCKDEP
+static int __init lockdep_ignore_clk_prepare_lock_setup(char *__unused)
+{
+ lockdep_set_novalidate_class(&prepare_lock);
+ pr_warn("lockdep: ignoring prepare_lock class in clock subsystem\n");
+ return 1;
+}
+__setup("lockdep_ignore_clk_prepare_lock",
+ lockdep_ignore_clk_prepare_lock_setup);
+#endif
+
/*** runtime pm ***/
static int clk_pm_runtime_get(struct clk_core *core)
{
--
2.43.0