[PATCH v2 2/2] clk: tests: Add tests for fractional divisor approximation

Stephen Boyd sboyd at kernel.org
Wed Jun 14 13:42:00 PDT 2023


Quoting Frank Oltmanns (2023-06-13 23:51:32)
> Hi Stephen,
> 
> Thank you for your feedback.
> 
> On 2023-06-13 at 12:42:05 -0700, Stephen Boyd <sboyd at kernel.org> wrote:
> > Quoting Frank Oltmanns (2023-06-13 01:36:26)
> >> In light of the recent discovery that the fractional divisor
> >> approximation does not utilize the full available range for clocks that
> >> are flagged CLK_FRAC_DIVIDER_ZERO_BASED, implement tests for the edge
> >> cases of this clock type.
> >>
> >> Signed-off-by: Frank Oltmanns <frank at oltmanns.dev>
> >> Link: https://lore.kernel.org/lkml/20230529133433.56215-1-frank@oltmanns.dev
> >
> > What is the link for?
> 
> The intention was to show why the tests were added ("In light of the
> recent discovery..."). I announced this discovery in the mail I referred
> to. Since that intention didn't come across: Should I drop the link?

Ok. You can say that and reference the link with [1] like this.

Link: https://lore.kernel.org/lkml/20230529133433.56215-1-frank@oltmanns.dev [1]

> 
> >
> >> ---
> >>  drivers/clk/clk_test.c | 69 +++++++++++++++++++++++++++++++++++++++++-
> >
> > Please make a new file, drivers/clk/clk-fractional-divider_test.c
> > instead.
> >
> >>  1 file changed, 68 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c
> >> index f9a5c2964c65..b247ba841cbd 100644
> >> --- a/drivers/clk/clk_test.c
> >> +++ b/drivers/clk/clk_test.c
> >> @@ -8,6 +8,9 @@
> >>  /* Needed for clk_hw_get_clk() */
> >>  #include "clk.h"
> >>
> >> +/* Needed for clk_fractional_divider_general_approximation */
> >> +#include "clk-fractional-divider.h"
> >> +
> >>  #include <kunit/test.h>
> >>
> >>  #define DUMMY_CLOCK_INIT_RATE  (42 * 1000 * 1000)
> >> @@ -2394,6 +2397,69 @@ static struct kunit_suite clk_mux_notifier_test_suite = {
> >>         .test_cases = clk_mux_notifier_test_cases,
> >>  };
> >>
> >> +
> >> +/*
> >> + * Test that clk_fractional_divider_general_approximation will work with the
> >> + * highest available numerator and denominator.
> >> + */
> >> +static void clk_fd_test_round_rate_max_mn(struct kunit *test)
> >> +{
> >> +       struct clk_fractional_divider *fd;
> >> +       struct clk_hw *hw;
> >> +       unsigned long rate, parent_rate, m, n;
> >> +
> >> +       fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
> >> +       KUNIT_ASSERT_NOT_NULL(test, fd);
> >> +
> >> +       fd->mwidth = 3;
> >> +       fd->nwidth = 3;
> >> +
> >> +       hw = &fd->hw;
> >> +
> >> +       rate = DUMMY_CLOCK_RATE_1;
> >> +
> >> +       // Highest denominator, no flags
> >
> > Use /* this for comments */
> >
> >> +       parent_rate = 10 * DUMMY_CLOCK_RATE_1;
> >
> > Just write out the actual frequency. Don't use DUMMY_CLOCK_RATE_1 at all
> > in the test.
> 
> Sure, will do. The idea was to highlight that we want to have the parent
> running at 10 times the speed, while the divider has a maximum value of
> 7 (or 8 if zero based).

Ok. In that case, have a local variable for 'rate' that's const and then
have

	parent_rate = 10 * rate;

to make it clear. We don't need a comment for that.

> 
> >
> >> +       clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
> >> +       KUNIT_EXPECT_EQ(test, m, 1);
> >> +       KUNIT_EXPECT_EQ(test, n, 7);
> >
> > This is a different test case.
> >
> >> +
> >> +       // Highest numerator, no flags
> >> +       parent_rate = DUMMY_CLOCK_RATE_1 / 10;
> >> +       clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
> >> +       KUNIT_EXPECT_EQ(test, m, 7);
> >
> > Is 7 related to mwidth? Maybe this should be clk_div_mask(fd->mwidth)
> > instead of 7.
> 
> Yes, 7 is related to mwidth. I thought about this too, but I'm not sure
> that's the best move here. The function under test uses:
>     max_m = GENMASK(fd->mwidth - 1, 0);
>     max_n = GENMASK(fd->nwidth - 1, 0);
> 
> I come from a safety-concerned industry and as a general rule we avoid
> using functions from the code under test in our tests.

GENMASK is a macro, not a function. Does that help? In all seriousness
though, I understand not wanting to test code with the same code. This
is basic math though. Maybe it should be something like this?

	const unsigned long max_m = 8;
	const unsigned long max_n = 8;

	fd->mwidth = bits_per(max_m);
	fd->nwidth = bits_per(max_n);

This expresses that there's a maximum m and n value and we calculate the
width from that information. Then the test can expect to see that max
value come out.

> I'm doing this
> here as a hobby, but still I find it to be a good rule that I'd like to
> stick to unless asked otherwise.

Cool.

> 
> If I use the same code to generate the expected values, I'm not really
> testing my change, but only the underlying best_rational_approximation.
> 
> Instead, how about I add a comment to the test function that more
> thoroughly explains its intention?

No thanks. We shouldn't need more than a sentence indicating what the
test is testing

> 
> Something along those lines:
> 
>     /*
>      * Introduce a parent that runs at 10 times the frequency of the
>      * requested rate.
>      * m and n are 3 bits wide each.
>      * The clock has no flags set, hence the maximum value that fits in
>      * m and n is 7.
>      * Therefore, expect the highest possible divisor.
>      */
>     static void clk_fd_test_round_rate_max_m(struct kunit *test)

I'd just indicate the expected outcome in the function name.

	clk_fd_test_general_approximation_m_saturates()

and then it could be parameterized with KUNIT_ARRAY_PARAM() so that we
make sure any width saturates.

> 
>     /*
>      * Introduce a parent that runs at 1/10th the frequency of the

I'm not sure where 10 times and 1/10th came from. Is it just a magnitude
larger for simplicity?



More information about the linux-arm-kernel mailing list