Message ID | 20220125141549.747889-2-maxime@cerno.tech (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | clk: Improve clock range handling | expand |
Quoting Maxime Ripard (2022-01-25 06:15:40) > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile > index 6a98291350b6..2664aaab8068 100644 > --- a/drivers/clk/Makefile > +++ b/drivers/clk/Makefile > @@ -2,6 +2,7 @@ > # common clock types > obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o clkdev.o > obj-$(CONFIG_COMMON_CLK) += clk.o > +obj-$(CONFIG_CLK_KUNIT_TEST) += clk-test.o The file name should be clk_test.c with an underscore. > obj-$(CONFIG_COMMON_CLK) += clk-divider.o > obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o > obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o > diff --git a/drivers/clk/clk-test.c b/drivers/clk/clk-test.c > new file mode 100644 > index 000000000000..47a600d590c1 > --- /dev/null > +++ b/drivers/clk/clk-test.c > @@ -0,0 +1,285 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Kunit test for clk rate management > + */ > +#include <linux/clk.h> > +#include <linux/clk-provider.h> > +#include <linux/slab.h> > + > +#include <kunit/test.h> > + > +#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000) > +#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000) > +#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000) > + > +struct clk_dummy_context { > + struct clk_hw hw; > + unsigned long rate; > +}; > + > +static unsigned long clk_dummy_recalc_rate(struct clk_hw *hw, > + unsigned long parent_rate) > +{ > + struct clk_dummy_context *ctx = > + container_of(hw, struct clk_dummy_context, hw); > + > + return ctx->rate; > +} > + > +static int clk_dummy_determine_rate(struct clk_hw *hw, > + struct clk_rate_request *req) > +{ > + /* Just return the same rate without modifying it */ > + return 0; > +} > + > +static int clk_dummy_set_rate(struct clk_hw *hw, > + unsigned long rate, > + unsigned long parent_rate) > +{ > + struct clk_dummy_context *ctx = > + container_of(hw, struct clk_dummy_context, hw); > + > + ctx->rate = rate; > + return 0; > +} > + > +static const struct clk_ops clk_dummy_ops = { Maybe clk_dummy_rate_ops? So we don't mix it up with other dummy ops in this file testing things that aren't rates. > + .recalc_rate = clk_dummy_recalc_rate, > + .determine_rate = clk_dummy_determine_rate, > + .set_rate = clk_dummy_set_rate, > +}; > + > +static int clk_test_init_with_ops(struct kunit *test, const struct clk_ops *ops) > +{ > + struct clk_dummy_context *ctx; > + struct clk_init_data init = { }; > + int ret; > + > + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); > + if (!ctx) > + return -ENOMEM; > + ctx->rate = DUMMY_CLOCK_INIT_RATE; > + test->priv = ctx; > + > + init.name = "test_dummy_rate"; > + init.ops = ops; > + ctx->hw.init = &init; > + > + ret = clk_hw_register(NULL, &ctx->hw); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int clk_test_init(struct kunit *test) > +{ > + return clk_test_init_with_ops(test, &clk_dummy_ops); > +} > + > +static void clk_test_exit(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + > + clk_hw_unregister(&ctx->hw); > +} > + > +/* > + * Test that the actual rate matches what is returned by clk_get_rate() > + */ > +static void clk_test_get_rate(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + unsigned long rate; > + > + rate = clk_get_rate(clk); > + KUNIT_ASSERT_TRUE(test, rate > 0); > + KUNIT_EXPECT_EQ(test, rate, ctx->rate); > +} > + > +/* > + * Test that, after a call to clk_set_rate(), the rate returned by > + * clk_get_rate() matches. > + * > + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't > + * modify the requested rate, which is our case in clk_dummy_rate_ops. > + */ > +static void clk_test_set_get_rate(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + unsigned long rate; > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate(clk, DUMMY_CLOCK_RATE_1), > + 0); > + > + rate = clk_get_rate(clk); > + KUNIT_ASSERT_GT(test, rate, 0); > + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); > +} > + > +/* > + * Test that, after several calls to clk_set_rate(), the rate returned > + * by clk_get_rate() matches the last one. > + * > + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't > + * modify the requested rate, which is our case in clk_dummy_rate_ops. > + */ > +static void clk_test_set_set_get_rate(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + unsigned long rate; > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate(clk, DUMMY_CLOCK_RATE_1), > + 0); > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate(clk, DUMMY_CLOCK_RATE_2), > + 0); > + > + rate = clk_get_rate(clk); > + KUNIT_ASSERT_GT(test, rate, 0); > + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); > +} > + > +static struct kunit_case clk_test_cases[] = { > + KUNIT_CASE(clk_test_get_rate), > + KUNIT_CASE(clk_test_set_get_rate), > + KUNIT_CASE(clk_test_set_set_get_rate), > + {} > +}; > + > +static struct kunit_suite clk_test_suite = { > + .name = "clk-test", > + .init = clk_test_init, > + .exit = clk_test_exit, > + .test_cases = clk_test_cases, > +}; > + > +/* > + * Test that clk_set_rate_range won't return an error for a valid range. > + */ > +static void clk_range_test_set_range(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + unsigned long rate; > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate_range(clk, > + DUMMY_CLOCK_RATE_1, > + DUMMY_CLOCK_RATE_2), > + 0); > + > + rate = clk_get_rate(clk); > + KUNIT_ASSERT_GT(test, rate, 0); > + KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); > + KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); > +} > + > +/* > + * Test that calling clk_set_rate_range with a minimum rate higher than > + * the maximum rate returns an error. > + */ > +static void clk_range_test_set_range_invalid(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + > + KUNIT_EXPECT_LT(test, > + clk_set_rate_range(clk, > + DUMMY_CLOCK_RATE_1 + 1000, > + DUMMY_CLOCK_RATE_1), > + 0); > +} > + > +/* > + * Test that if our clock has a rate lower than the minimum set by a > + * call to clk_set_rate_range(), the rate will be raised to match the > + * new minimum. > + * > + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't > + * modify the requested rate, which is our case in clk_dummy_rate_ops. > + */ > +static void clk_range_test_set_range_get_rate_raised(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + unsigned long rate; > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000), > + 0); > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate_range(clk, > + DUMMY_CLOCK_RATE_1, > + DUMMY_CLOCK_RATE_2), > + 0); > + > + rate = clk_get_rate(clk); > + KUNIT_ASSERT_GT(test, rate, 0); > + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); > +} > + > +/* > + * Test that if our clock has a rate higher than the maximum set by a > + * call to clk_set_rate_range(), the rate will be lowered to match the > + * new maximum. > + * > + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't > + * modify the requested rate, which is our case in clk_dummy_rate_ops. > + */ > +static void clk_range_test_set_range_get_rate_lowered(struct kunit *test) > +{ > + struct clk_dummy_context *ctx = test->priv; > + struct clk_hw *hw = &ctx->hw; > + struct clk *clk = hw->clk; > + unsigned long rate; > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), > + 0); > + > + KUNIT_ASSERT_EQ(test, > + clk_set_rate_range(clk, > + DUMMY_CLOCK_RATE_1, > + DUMMY_CLOCK_RATE_2), > + 0); > + > + rate = clk_get_rate(clk); > + KUNIT_ASSERT_GT(test, rate, 0); > + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); > +} > + > +static struct kunit_case clk_range_test_cases[] = { > + KUNIT_CASE(clk_range_test_set_range), > + KUNIT_CASE(clk_range_test_set_range_invalid), > + KUNIT_CASE(clk_range_test_set_range_get_rate_raised), > + KUNIT_CASE(clk_range_test_set_range_get_rate_lowered), Can you add a test case for round_rate matching what set_rate did, i.e. calling clk_round_rate() and then clk_set_rate() followed by clk_get_rate() with the same argument for round and set rate leads to the same frequency? It would also be good to add a test that tries to set the clk rate with clk_set_rate() after a range has been set that is outside the acceptable range and verify that it fails, and one that tries to set it within the range and make sure it succeeds (and changes it to be exactly what was set). Similarly, a call to set two disjoint ranges and verify that the call that tries to set the second disjoint range fails. We want to test the failure paths as well, to make sure we don't start causing them to pass, unless it's expected. This patch could also contain the failure scenario you're experiencing and mark it as expecting to fail. Then the patch that fixes it in the core could mark the test as expecting to pass, which may help us understand more easily what exactly changed instead of having to figure that out after the fact by reading the entire test. > + {} > +}; > + > +static struct kunit_suite clk_range_test_suite = { > + .name = "clk-range-test", > + .init = clk_test_init, > + .exit = clk_test_exit, > + .test_cases = clk_range_test_cases, > +};
Hi Stephen, Thanks for your review On Fri, Feb 18, 2022 at 06:20:46PM -0800, Stephen Boyd wrote: > It would also be good to add a test that tries to set the clk rate with > clk_set_rate() after a range has been set that is outside the acceptable > range and verify that it fails, and one that tries to set it within the > range and make sure it succeeds (and changes it to be exactly what was > set). Do we expect it to fail though? If we do: clk_set_range_range(clk, 1000, 2000); clk_set_rate(3000); The current behaviour is that the rate is going to be rounded to 2000, but it doesn't fail. Or is it what you meant by fail? ie, that the return code is 0, but the rate isn't what we asked for? > Similarly, a call to set two disjoint ranges and verify that the call > that tries to set the second disjoint range fails. Ok > We want to test the failure paths as well, to make sure we don't start > causing them to pass, unless it's expected. Do you have any other failure condition you want to test? I already tried to come up with those I could think of, but I clearly missed some if you said that :) > This patch could also contain the failure scenario you're experiencing > and mark it as expecting to fail. Then the patch that fixes it in the > core could mark the test as expecting to pass, which may help us > understand more easily what exactly changed instead of having to > figure that out after the fact by reading the entire test.> Ok Maxime
Quoting Maxime Ripard (2022-02-21 07:12:59) > Hi Stephen, > > Thanks for your review > > On Fri, Feb 18, 2022 at 06:20:46PM -0800, Stephen Boyd wrote: > > It would also be good to add a test that tries to set the clk rate with > > clk_set_rate() after a range has been set that is outside the acceptable > > range and verify that it fails, and one that tries to set it within the > > range and make sure it succeeds (and changes it to be exactly what was > > set). > > Do we expect it to fail though? > > If we do: > > clk_set_range_range(clk, 1000, 2000); > clk_set_rate(3000); > > The current behaviour is that the rate is going to be rounded to 2000, > but it doesn't fail. > > Or is it what you meant by fail? ie, that the return code is 0, but the > rate isn't what we asked for? Yeah sorry for not being clear. I meant that it would be constrained to the range from before. > > > We want to test the failure paths as well, to make sure we don't start > > causing them to pass, unless it's expected. > > Do you have any other failure condition you want to test? I already > tried to come up with those I could think of, but I clearly missed some > if you said that :) Not really! :)
diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig index 3754fdb9485a..cdbc7d7deba9 100644 --- a/drivers/clk/.kunitconfig +++ b/drivers/clk/.kunitconfig @@ -1,3 +1,4 @@ CONFIG_KUNIT=y CONFIG_COMMON_CLK=y +CONFIG_CLK_KUNIT_TEST=y CONFIG_CLK_GATE_KUNIT_TEST=y diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3cdf33470a75..2ef6eca297ff 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -429,6 +429,13 @@ source "drivers/clk/xilinx/Kconfig" source "drivers/clk/zynqmp/Kconfig" # Kunit test cases +config CLK_KUNIT_TEST + tristate "Basic Clock Framework Kunit Tests" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Kunit tests for the common clock framework. + config CLK_GATE_KUNIT_TEST tristate "Basic gate type Kunit test" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 6a98291350b6..2664aaab8068 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -2,6 +2,7 @@ # common clock types obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o +obj-$(CONFIG_CLK_KUNIT_TEST) += clk-test.o obj-$(CONFIG_COMMON_CLK) += clk-divider.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o diff --git a/drivers/clk/clk-test.c b/drivers/clk/clk-test.c new file mode 100644 index 000000000000..47a600d590c1 --- /dev/null +++ b/drivers/clk/clk-test.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for clk rate management + */ +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/slab.h> + +#include <kunit/test.h> + +#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000) +#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000) +#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000) + +struct clk_dummy_context { + struct clk_hw hw; + unsigned long rate; +}; + +static unsigned long clk_dummy_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_dummy_context *ctx = + container_of(hw, struct clk_dummy_context, hw); + + return ctx->rate; +} + +static int clk_dummy_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + /* Just return the same rate without modifying it */ + return 0; +} + +static int clk_dummy_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_dummy_context *ctx = + container_of(hw, struct clk_dummy_context, hw); + + ctx->rate = rate; + return 0; +} + +static const struct clk_ops clk_dummy_ops = { + .recalc_rate = clk_dummy_recalc_rate, + .determine_rate = clk_dummy_determine_rate, + .set_rate = clk_dummy_set_rate, +}; + +static int clk_test_init_with_ops(struct kunit *test, const struct clk_ops *ops) +{ + struct clk_dummy_context *ctx; + struct clk_init_data init = { }; + int ret; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->rate = DUMMY_CLOCK_INIT_RATE; + test->priv = ctx; + + init.name = "test_dummy_rate"; + init.ops = ops; + ctx->hw.init = &init; + + ret = clk_hw_register(NULL, &ctx->hw); + if (ret) + return ret; + + return 0; +} + +static int clk_test_init(struct kunit *test) +{ + return clk_test_init_with_ops(test, &clk_dummy_ops); +} + +static void clk_test_exit(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + + clk_hw_unregister(&ctx->hw); +} + +/* + * Test that the actual rate matches what is returned by clk_get_rate() + */ +static void clk_test_get_rate(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + unsigned long rate; + + rate = clk_get_rate(clk); + KUNIT_ASSERT_TRUE(test, rate > 0); + KUNIT_EXPECT_EQ(test, rate, ctx->rate); +} + +/* + * Test that, after a call to clk_set_rate(), the rate returned by + * clk_get_rate() matches. + * + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't + * modify the requested rate, which is our case in clk_dummy_rate_ops. + */ +static void clk_test_set_get_rate(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + unsigned long rate; + + KUNIT_ASSERT_EQ(test, + clk_set_rate(clk, DUMMY_CLOCK_RATE_1), + 0); + + rate = clk_get_rate(clk); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); +} + +/* + * Test that, after several calls to clk_set_rate(), the rate returned + * by clk_get_rate() matches the last one. + * + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't + * modify the requested rate, which is our case in clk_dummy_rate_ops. + */ +static void clk_test_set_set_get_rate(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + unsigned long rate; + + KUNIT_ASSERT_EQ(test, + clk_set_rate(clk, DUMMY_CLOCK_RATE_1), + 0); + + KUNIT_ASSERT_EQ(test, + clk_set_rate(clk, DUMMY_CLOCK_RATE_2), + 0); + + rate = clk_get_rate(clk); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); +} + +static struct kunit_case clk_test_cases[] = { + KUNIT_CASE(clk_test_get_rate), + KUNIT_CASE(clk_test_set_get_rate), + KUNIT_CASE(clk_test_set_set_get_rate), + {} +}; + +static struct kunit_suite clk_test_suite = { + .name = "clk-test", + .init = clk_test_init, + .exit = clk_test_exit, + .test_cases = clk_test_cases, +}; + +/* + * Test that clk_set_rate_range won't return an error for a valid range. + */ +static void clk_range_test_set_range(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + unsigned long rate; + + KUNIT_ASSERT_EQ(test, + clk_set_rate_range(clk, + DUMMY_CLOCK_RATE_1, + DUMMY_CLOCK_RATE_2), + 0); + + rate = clk_get_rate(clk); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); + KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); +} + +/* + * Test that calling clk_set_rate_range with a minimum rate higher than + * the maximum rate returns an error. + */ +static void clk_range_test_set_range_invalid(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + + KUNIT_EXPECT_LT(test, + clk_set_rate_range(clk, + DUMMY_CLOCK_RATE_1 + 1000, + DUMMY_CLOCK_RATE_1), + 0); +} + +/* + * Test that if our clock has a rate lower than the minimum set by a + * call to clk_set_rate_range(), the rate will be raised to match the + * new minimum. + * + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't + * modify the requested rate, which is our case in clk_dummy_rate_ops. + */ +static void clk_range_test_set_range_get_rate_raised(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + unsigned long rate; + + KUNIT_ASSERT_EQ(test, + clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000), + 0); + + KUNIT_ASSERT_EQ(test, + clk_set_rate_range(clk, + DUMMY_CLOCK_RATE_1, + DUMMY_CLOCK_RATE_2), + 0); + + rate = clk_get_rate(clk); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); +} + +/* + * Test that if our clock has a rate higher than the maximum set by a + * call to clk_set_rate_range(), the rate will be lowered to match the + * new maximum. + * + * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't + * modify the requested rate, which is our case in clk_dummy_rate_ops. + */ +static void clk_range_test_set_range_get_rate_lowered(struct kunit *test) +{ + struct clk_dummy_context *ctx = test->priv; + struct clk_hw *hw = &ctx->hw; + struct clk *clk = hw->clk; + unsigned long rate; + + KUNIT_ASSERT_EQ(test, + clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), + 0); + + KUNIT_ASSERT_EQ(test, + clk_set_rate_range(clk, + DUMMY_CLOCK_RATE_1, + DUMMY_CLOCK_RATE_2), + 0); + + rate = clk_get_rate(clk); + KUNIT_ASSERT_GT(test, rate, 0); + KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); +} + +static struct kunit_case clk_range_test_cases[] = { + KUNIT_CASE(clk_range_test_set_range), + KUNIT_CASE(clk_range_test_set_range_invalid), + KUNIT_CASE(clk_range_test_set_range_get_rate_raised), + KUNIT_CASE(clk_range_test_set_range_get_rate_lowered), + {} +}; + +static struct kunit_suite clk_range_test_suite = { + .name = "clk-range-test", + .init = clk_test_init, + .exit = clk_test_exit, + .test_cases = clk_range_test_cases, +}; + +kunit_test_suites( + &clk_test_suite, + &clk_range_test_suite, +); +MODULE_LICENSE("GPL v2");
Let's test various parts of the rate-related clock API with the kunit testing framework. Cc: kunit-dev@googlegroups.com Suggested-by: Stephen Boyd <sboyd@kernel.org> Signed-off-by: Maxime Ripard <maxime@cerno.tech> --- drivers/clk/.kunitconfig | 1 + drivers/clk/Kconfig | 7 + drivers/clk/Makefile | 1 + drivers/clk/clk-test.c | 285 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 294 insertions(+) create mode 100644 drivers/clk/clk-test.c