diff mbox series

[RFC,07/10] clk: Ensure all RPM enabled clocks are enabled before reparenting orphans

Message ID 20250326-cross-lock-dep-v1-7-3199e49e8652@bootlin.com (mailing list archive)
State New
Headers show
Series Fix the ABBA locking situation between clk and runtime PM | expand

Commit Message

Miquel Raynal March 26, 2025, 6:26 p.m. UTC
In order to fix the ABBA locking situation between clock and power
domains, let's disimburse these two locks by preventing any runtime PM
call to happen with the clk prepare_lock mutex acquired.

Reparenting orphans upon introduction of a new provider means that if
there is a match, the core will recalculate the rates, which requires
the relevant clocks to be enabled.

There is not much we can do to guess which clocks will need rate
recalculation, so better ensure all registered clocks are resumed before
doing the reparenting operation which obviously requires acquiring the
clk prepare_lock to protect against concurrent accesses on the clk tree
topology.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/clk/clk.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
diff mbox series

Patch

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 95f53bc427d8980287bfe668d1c993023e0e078b..4c2f2d2b7735dfbe323fec4e0d331302534bc849 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -5032,8 +5032,16 @@  int of_clk_add_provider(struct device_node *np,
 	mutex_unlock(&of_clk_mutex);
 	pr_debug("Added clock from %pOF\n", np);
 
+	ret = clk_pm_runtime_get_all();
+	if (ret) {
+		of_clk_del_provider(np);
+		return ret;
+	}
+
 	clk_core_reparent_orphans();
 
+	clk_pm_runtime_put_all();
+
 	ret = of_clk_set_defaults(np, true);
 	if (ret < 0)
 		of_clk_del_provider(np);
@@ -5074,8 +5082,16 @@  int of_clk_add_hw_provider(struct device_node *np,
 	mutex_unlock(&of_clk_mutex);
 	pr_debug("Added clk_hw provider from %pOF\n", np);
 
+	ret = clk_pm_runtime_get_all();
+	if (ret) {
+		of_clk_del_provider(np);
+		return ret;
+	}
+
 	clk_core_reparent_orphans();
 
+	clk_pm_runtime_put_all();
+
 	ret = of_clk_set_defaults(np, true);
 	if (ret < 0)
 		of_clk_del_provider(np);