* [PATCH] clk: send abort notifications when a parent change is vetoed
@ 2026-10-21 21:28 James Hilliard
2026-10-26 14:30 ` Konrad Dybcio
0 siblings, 1 reply; 2+ messages in thread
From: James Hilliard @ 2026-10-21 21:28 UTC (permalink / raw)
To: Stephen Boyd, Brian Masney, Jerome Brunet, Mike Turquette,
Thomas Gleixner, Arnd Bergmann
Cc: Konrad Dybcio, linux-clk, linux-kernel, James Hilliard
clk_core_set_parent_nolock() returns directly when a PRE_RATE_CHANGE
notifier rejects the proposed parent. Consumers notified before the veto
do not receive ABORT_RATE_CHANGE, even though they may have stopped I/O
or reserved resources until the transition finishes. The caller also
receives a positive notifier return value instead of a negative errno.
Recalculate and notify the unchanged subtree with ABORT_RATE_CHANGE before
returning -EBUSY, as for other failed parent changes. This lets prepared
consumers unwind without changing the parent or its rate.
Extend the mux notifier tests to cover both a self-veto and a later
notifier vetoing after the first consumer accepted the change. Check the
abort notification, errno and unchanged parent/rate in both cases.
Fixes: b2476490ef11 ("clk: introduce the common clock framework")
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/clk/clk.c | 5 +++-
drivers/clk/clk_test.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fef87167a60b..a9620d9e0db1 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2983,8 +2983,11 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
ret = __clk_speculate_rates(core, p_rate);
/* abort if a driver objects */
- if (ret & NOTIFY_STOP_MASK)
+ if (ret & NOTIFY_STOP_MASK) {
+ __clk_recalc_rates(core, true, ABORT_RATE_CHANGE);
+ ret = -EBUSY;
goto runtime_put;
+ }
/* do the re-parent */
ret = __clk_set_parent(core, parent, p_index);
diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
index 1c5c8b7c1f3c..e9d0d6f5084b 100644
--- a/drivers/clk/clk_test.c
+++ b/drivers/clk/clk_test.c
@@ -2364,6 +2364,8 @@ struct clk_mux_notifier_ctx {
struct notifier_block clk_nb;
struct clk_mux_notifier_rate_change pre_rate_change;
struct clk_mux_notifier_rate_change post_rate_change;
+ bool veto;
+ bool aborted;
};
#define NOTIFIER_TIMEOUT_MS 100
@@ -2381,6 +2383,8 @@ static int clk_mux_notifier_callback(struct notifier_block *nb,
ctx->pre_rate_change.new_rate = clk_data->new_rate;
ctx->pre_rate_change.done = true;
wake_up_interruptible(&ctx->pre_rate_change.wq);
+ if (ctx->veto)
+ return NOTIFY_BAD;
}
if (action & POST_RATE_CHANGE) {
@@ -2390,7 +2394,10 @@ static int clk_mux_notifier_callback(struct notifier_block *nb,
wake_up_interruptible(&ctx->post_rate_change.wq);
}
- return 0;
+ if (action == ABORT_RATE_CHANGE)
+ ctx->aborted = true;
+
+ return NOTIFY_OK;
}
static int clk_mux_notifier_test_init(struct kunit *test)
@@ -2488,8 +2495,61 @@ static void clk_mux_notifier_set_parent_test(struct kunit *test)
clk_put(clk);
}
+static void clk_mux_notifier_veto_parent_test(struct kunit *test)
+{
+ struct clk_mux_notifier_ctx *ctx = test->priv;
+ struct clk *parent = clk_hw_get_clk(&ctx->mux_ctx.parents_ctx[1].hw, NULL);
+ int ret;
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
+ ctx->veto = true;
+ ret = clk_set_parent(ctx->clk, parent);
+ clk_put(parent);
+
+ KUNIT_EXPECT_EQ(test, ret, -EBUSY);
+ KUNIT_EXPECT_TRUE(test, ctx->pre_rate_change.done);
+ KUNIT_EXPECT_TRUE(test, ctx->aborted);
+ KUNIT_EXPECT_FALSE(test, ctx->post_rate_change.done);
+ KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->clk), DUMMY_CLOCK_RATE_1);
+ KUNIT_EXPECT_EQ(test, ctx->mux_ctx.current_parent, 0);
+}
+
+static int clk_mux_veto_callback(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ return action == PRE_RATE_CHANGE ? NOTIFY_BAD : NOTIFY_OK;
+}
+
+static void clk_mux_notifier_abort_parent_test(struct kunit *test)
+{
+ struct clk_mux_notifier_ctx *ctx = test->priv;
+ struct notifier_block veto = { .notifier_call = clk_mux_veto_callback };
+ struct clk *parent = clk_hw_get_clk(&ctx->mux_ctx.parents_ctx[1].hw, NULL);
+ int ret;
+
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
+ ret = clk_notifier_register(ctx->clk, &veto);
+ if (ret)
+ clk_put(parent);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ /* The first consumer accepts PRE before the second consumer vetoes it. */
+ ret = clk_set_parent(ctx->clk, parent);
+ clk_put(parent);
+ clk_notifier_unregister(ctx->clk, &veto);
+
+ KUNIT_EXPECT_EQ(test, ret, -EBUSY);
+ KUNIT_EXPECT_TRUE(test, ctx->pre_rate_change.done);
+ KUNIT_EXPECT_TRUE(test, ctx->aborted);
+ KUNIT_EXPECT_FALSE(test, ctx->post_rate_change.done);
+ KUNIT_EXPECT_EQ(test, clk_get_rate(ctx->clk), DUMMY_CLOCK_RATE_1);
+ KUNIT_EXPECT_EQ(test, ctx->mux_ctx.current_parent, 0);
+}
+
static struct kunit_case clk_mux_notifier_test_cases[] = {
KUNIT_CASE(clk_mux_notifier_set_parent_test),
+ KUNIT_CASE(clk_mux_notifier_veto_parent_test),
+ KUNIT_CASE(clk_mux_notifier_abort_parent_test),
{}
};
---
base-commit: 81493c1dd1b1ebecb2843a7815973a5bd9a37e5a
change-id: 20261021-submit-clk-parent-abort-v1-b9232ac83dd1
Best regards,
--
James Hilliard <james.hilliard1@gmail.com>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] clk: send abort notifications when a parent change is vetoed
2026-10-21 21:28 [PATCH] clk: send abort notifications when a parent change is vetoed James Hilliard
@ 2026-10-26 14:30 ` Konrad Dybcio
0 siblings, 0 replies; 2+ messages in thread
From: Konrad Dybcio @ 2026-10-26 14:30 UTC (permalink / raw)
To: James Hilliard, Stephen Boyd, Brian Masney, Jerome Brunet,
Mike Turquette, Thomas Gleixner, Arnd Bergmann
Cc: linux-clk, linux-kernel
On 10/21/26 11:28 PM, James Hilliard wrote:
> clk_core_set_parent_nolock() returns directly when a PRE_RATE_CHANGE
> notifier rejects the proposed parent. Consumers notified before the veto
> do not receive ABORT_RATE_CHANGE, even though they may have stopped I/O
> or reserved resources until the transition finishes. The caller also
> receives a positive notifier return value instead of a negative errno.
>
> Recalculate and notify the unchanged subtree with ABORT_RATE_CHANGE before
> returning -EBUSY, as for other failed parent changes. This lets prepared
> consumers unwind without changing the parent or its rate.
>
> Extend the mux notifier tests to cover both a self-veto and a later
> notifier vetoing after the first consumer accepted the change. Check the
> abort notification, errno and unchanged parent/rate in both cases.
>
> Fixes: b2476490ef11 ("clk: introduce the common clock framework")
> Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
> ---
Acked-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-26 14:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21 21:28 [PATCH] clk: send abort notifications when a parent change is vetoed James Hilliard
2026-10-26 14:30 ` Konrad Dybcio
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®