Skip to content

Commit 096b256

Browse files
committed
clk: Drive clk_leaf_mux_set_rate_parent test from clk_ops
Running this kunit test with lockdep enabled leads to warning splats about calling clk provider APIs without the clk_prepare lock held. I proposed adding a wrapper around these APIs to grab the prepare lock so we can call them from anywhere, and Maxime implemented that approach[1], but it didn't look great. That's because we had to make more kunit testing APIs just to call code from a place that isn't a clk provider when the prepare lock isn't held. Instead of doing that, let's implement a determine_rate clk_op for a new leaf clk that is the child of the existing leaf clk. We can call __clk_determine_rate() on the existing leaf clk from there, and stash away the clk_rate_request struct to check once the clk_op returns. Drive that clk_op by calling clk_round_rate() to keep things similar to how it was before (i.e. nothing actually changes rate, just the new rate is determined). This silences the warning by driving the test from a clk_op where we know the prepare lock is held. While looking at this in more detail, it was determined that the code we intended to test in commit 262ca38 ("clk: Stop forwarding clk_rate_requests to the parent") wasn't actually tested. The call to __clk_determine_rate() wasn't actually getting to the newly introduced code under the CLK_SET_RATE_PARENT if condition in clk_core_round_rate_nolock() because the parent clk (the mux) could round rates. We introduce a new leaf and make sure the parent of that clk has no clk_ops so that we can be certain that the CLK_SET_RATE_PARENT condition in clk_core_round_rate_nolock() is evaluated. Reported-by: Guenter Roeck <[email protected]> Closes: https://lore.kernel.org/linux-clk/[email protected]/ Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-lkp/[email protected] Cc: Maxime Ripard <[email protected]> Link: https://lore.kernel.org/r/[email protected] [1] Fixes: 262ca38 ("clk: Stop forwarding clk_rate_requests to the parent") Link: https://lore.kernel.org/r/[email protected] Acked-by: Maxime Ripard <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent 0bb80ec commit 096b256

File tree

1 file changed

+48
-17
lines changed

1 file changed

+48
-17
lines changed

drivers/clk/clk_test.c

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include <kunit/test.h>
1212

13+
static const struct clk_ops empty_clk_ops = { };
14+
1315
#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000)
1416
#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000)
1517
#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000)
@@ -2155,6 +2157,30 @@ static struct kunit_suite clk_range_minimize_test_suite = {
21552157
struct clk_leaf_mux_ctx {
21562158
struct clk_multiple_parent_ctx mux_ctx;
21572159
struct clk_hw hw;
2160+
struct clk_hw parent;
2161+
struct clk_rate_request *req;
2162+
};
2163+
2164+
static int clk_leaf_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
2165+
{
2166+
struct clk_leaf_mux_ctx *ctx = container_of(hw, struct clk_leaf_mux_ctx, hw);
2167+
int ret;
2168+
struct clk_rate_request *parent_req = ctx->req;
2169+
2170+
clk_hw_forward_rate_request(hw, req, req->best_parent_hw, parent_req, req->rate);
2171+
ret = __clk_determine_rate(req->best_parent_hw, parent_req);
2172+
if (ret)
2173+
return ret;
2174+
2175+
req->rate = parent_req->rate;
2176+
2177+
return 0;
2178+
}
2179+
2180+
static const struct clk_ops clk_leaf_mux_set_rate_parent_ops = {
2181+
.determine_rate = clk_leaf_mux_determine_rate,
2182+
.set_parent = clk_dummy_single_set_parent,
2183+
.get_parent = clk_dummy_single_get_parent,
21582184
};
21592185

21602186
static int
@@ -2193,8 +2219,14 @@ clk_leaf_mux_set_rate_parent_test_init(struct kunit *test)
21932219
if (ret)
21942220
return ret;
21952221

2196-
ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->mux_ctx.hw,
2197-
&clk_dummy_single_parent_ops,
2222+
ctx->parent.init = CLK_HW_INIT_HW("test-parent", &ctx->mux_ctx.hw,
2223+
&empty_clk_ops, CLK_SET_RATE_PARENT);
2224+
ret = clk_hw_register(NULL, &ctx->parent);
2225+
if (ret)
2226+
return ret;
2227+
2228+
ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->parent,
2229+
&clk_leaf_mux_set_rate_parent_ops,
21982230
CLK_SET_RATE_PARENT);
21992231
ret = clk_hw_register(NULL, &ctx->hw);
22002232
if (ret)
@@ -2208,32 +2240,31 @@ static void clk_leaf_mux_set_rate_parent_test_exit(struct kunit *test)
22082240
struct clk_leaf_mux_ctx *ctx = test->priv;
22092241

22102242
clk_hw_unregister(&ctx->hw);
2243+
clk_hw_unregister(&ctx->parent);
22112244
clk_hw_unregister(&ctx->mux_ctx.hw);
22122245
clk_hw_unregister(&ctx->mux_ctx.parents_ctx[0].hw);
22132246
clk_hw_unregister(&ctx->mux_ctx.parents_ctx[1].hw);
22142247
}
22152248

22162249
/*
2217-
* Test that, for a clock that will forward any rate request to its
2218-
* parent, the rate request structure returned by __clk_determine_rate
2219-
* is sane and will be what we expect.
2250+
* Test that, for a clock that will forward any rate request to its parent, the
2251+
* rate request structure returned by __clk_determine_rate() is sane and
2252+
* doesn't have the clk_rate_request's best_parent_hw pointer point to the
2253+
* clk_hw passed into __clk_determine_rate(). See commit 262ca38f4b6e ("clk:
2254+
* Stop forwarding clk_rate_requests to the parent") for more background.
22202255
*/
2221-
static void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test)
2256+
static void clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent(struct kunit *test)
22222257
{
22232258
struct clk_leaf_mux_ctx *ctx = test->priv;
22242259
struct clk_hw *hw = &ctx->hw;
22252260
struct clk *clk = clk_hw_get_clk(hw, NULL);
22262261
struct clk_rate_request req;
22272262
unsigned long rate;
2228-
int ret;
22292263

2264+
ctx->req = &req;
22302265
rate = clk_get_rate(clk);
22312266
KUNIT_ASSERT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
2232-
2233-
clk_hw_init_rate_request(hw, &req, DUMMY_CLOCK_RATE_2);
2234-
2235-
ret = __clk_determine_rate(hw, &req);
2236-
KUNIT_ASSERT_EQ(test, ret, 0);
2267+
KUNIT_ASSERT_EQ(test, DUMMY_CLOCK_RATE_2, clk_round_rate(clk, DUMMY_CLOCK_RATE_2));
22372268

22382269
KUNIT_EXPECT_EQ(test, req.rate, DUMMY_CLOCK_RATE_2);
22392270
KUNIT_EXPECT_EQ(test, req.best_parent_rate, DUMMY_CLOCK_RATE_2);
@@ -2243,15 +2274,15 @@ static void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test)
22432274
}
22442275

22452276
static struct kunit_case clk_leaf_mux_set_rate_parent_test_cases[] = {
2246-
KUNIT_CASE(clk_leaf_mux_set_rate_parent_determine_rate),
2277+
KUNIT_CASE(clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent),
22472278
{}
22482279
};
22492280

22502281
/*
2251-
* Test suite for a clock whose parent is a mux with multiple parents.
2252-
* The leaf clock has CLK_SET_RATE_PARENT, and will forward rate
2253-
* requests to the mux, which will then select which parent is the best
2254-
* fit for a given rate.
2282+
* Test suite for a clock whose parent is a pass-through clk whose parent is a
2283+
* mux with multiple parents. The leaf and pass-through clocks have the
2284+
* CLK_SET_RATE_PARENT flag, and will forward rate requests to the mux, which
2285+
* will then select which parent is the best fit for a given rate.
22552286
*
22562287
* These tests exercise the behaviour of muxes, and the proper selection
22572288
* of parents.

0 commit comments

Comments
 (0)