1 From 655e66b0add0aba16e84587dbb939f8ddce612b0 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Fri, 1 Apr 2022 15:27:09 +0200
4 Subject: [PATCH] clk: Skip set_rate_range if our clock is orphan
6 clk_set_rate_range will now force a clk_set_rate() call to
7 core->req_rate. However, if our clock is orphan, req_rate will be 0 and
8 we will thus end up calling a set_rate to 0 on potentially all that
11 This can be fairly invasive and result in poor decisions. In such a
12 case, let's just store the new range but bail out and skip the set_rate.
14 When that clock is no longer orphan though, we should be enforcing the
15 new range but we don't. Let's add a skipped test to make sure we don't
16 forget about that corner case.
18 Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # imx8mp
19 Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> # exynos4210, meson g12b
20 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
22 drivers/clk/clk.c | 6 +++++
23 drivers/clk/clk_test.c | 59 ++++++++++++++++++++++++++++++++++++++++++
24 2 files changed, 65 insertions(+)
26 --- a/drivers/clk/clk.c
27 +++ b/drivers/clk/clk.c
28 @@ -2398,6 +2398,12 @@ static int clk_set_rate_range_nolock(str
29 if (clk->core->flags & CLK_GET_RATE_NOCACHE)
30 rate = clk_core_get_rate_recalc(clk->core);
32 + if (clk->core->orphan && !rate) {
33 + pr_warn("%s: clk %s: Clock is orphan and doesn't have a rate!\n",
34 + __func__, clk->core->name);
39 * Since the boundaries have been changed, let's give the
40 * opportunity to the provider to adjust the clock rate based on
41 --- a/drivers/clk/clk_test.c
42 +++ b/drivers/clk/clk_test.c
43 @@ -737,6 +737,26 @@ clk_test_orphan_transparent_multiple_par
46 * Test that, for a mux whose current parent hasn't been registered yet,
47 + * calling clk_set_rate_range() will succeed but won't affect its rate.
50 +clk_test_orphan_transparent_multiple_parent_mux_set_range_get_rate(struct kunit *test)
52 + struct clk_multiple_parent_ctx *ctx = test->priv;
53 + struct clk_hw *hw = &ctx->hw;
54 + struct clk *clk = hw->clk;
58 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
59 + KUNIT_ASSERT_EQ(test, ret, 0);
61 + rate = clk_get_rate(clk);
62 + KUNIT_EXPECT_EQ(test, rate, 0);
66 + * Test that, for a mux whose current parent hasn't been registered yet,
67 * calling clk_set_rate_range() will succeed, and will be taken into
68 * account when rounding a rate.
70 @@ -758,6 +778,43 @@ clk_test_orphan_transparent_multiple_par
71 KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
75 + * Test that, for a mux that started orphan, was assigned and rate and
76 + * then got switched to a valid parent, its rate is eventually within
79 + * FIXME: Even though we update the rate as part of clk_set_parent(), we
80 + * don't evaluate whether that new rate is within range and needs to be
84 +clk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate(struct kunit *test)
86 + struct clk_multiple_parent_ctx *ctx = test->priv;
87 + struct clk_hw *hw = &ctx->hw;
88 + struct clk *clk = hw->clk, *parent;
92 + kunit_skip(test, "This needs to be fixed in the core.");
94 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
95 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
97 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
98 + KUNIT_ASSERT_EQ(test, ret, 0);
100 + ret = clk_set_parent(clk, parent);
101 + KUNIT_ASSERT_EQ(test, ret, 0);
103 + rate = clk_get_rate(clk);
104 + KUNIT_ASSERT_GT(test, rate, 0);
105 + KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
106 + KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
111 static struct kunit_case clk_orphan_transparent_multiple_parent_mux_test_cases[] = {
112 KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_get_parent),
113 KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent),
114 @@ -766,7 +823,9 @@ static struct kunit_case clk_orphan_tran
115 KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_put),
116 KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified),
117 KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_untouched),
118 + KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_range_get_rate),
119 KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate),
120 + KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate),