d4f281d6fe6ebd2aa2e72c76127ba7acf3962c65
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0847-clk-Skip-set_rate_range-if-our-clock-is-orphan.patch
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
5
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
9 clock subtree.
10
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.
13
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.
17
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>
21 ---
22 drivers/clk/clk.c | 6 +++++
23 drivers/clk/clk_test.c | 59 ++++++++++++++++++++++++++++++++++++++++++
24 2 files changed, 65 insertions(+)
25
26 --- a/drivers/clk/clk.c
27 +++ b/drivers/clk/clk.c
28 @@ -2387,6 +2387,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);
31
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);
35 + goto out;
36 + }
37 +
38 /*
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
44
45 /*
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.
48 + */
49 +static void
50 +clk_test_orphan_transparent_multiple_parent_mux_set_range_get_rate(struct kunit *test)
51 +{
52 + struct clk_multiple_parent_ctx *ctx = test->priv;
53 + struct clk_hw *hw = &ctx->hw;
54 + struct clk *clk = hw->clk;
55 + unsigned long rate;
56 + int ret;
57 +
58 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
59 + KUNIT_ASSERT_EQ(test, ret, 0);
60 +
61 + rate = clk_get_rate(clk);
62 + KUNIT_EXPECT_EQ(test, rate, 0);
63 +}
64 +
65 +/*
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.
69 */
70 @@ -758,6 +778,43 @@ clk_test_orphan_transparent_multiple_par
71 KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
72 }
73
74 +/*
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
77 + * range.
78 + *
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
81 + * adjusted.
82 + */
83 +static void
84 +clk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate(struct kunit *test)
85 +{
86 + struct clk_multiple_parent_ctx *ctx = test->priv;
87 + struct clk_hw *hw = &ctx->hw;
88 + struct clk *clk = hw->clk, *parent;
89 + unsigned long rate;
90 + int ret;
91 +
92 + kunit_skip(test, "This needs to be fixed in the core.");
93 +
94 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
95 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
96 +
97 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
98 + KUNIT_ASSERT_EQ(test, ret, 0);
99 +
100 + ret = clk_set_parent(clk, parent);
101 + KUNIT_ASSERT_EQ(test, ret, 0);
102 +
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);
107 +
108 + clk_put(parent);
109 +}
110 +
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),
121 {}
122 };
123