clk: fractional-divider: Improve approximation when zero based and export
v4 cover clk: fractional-divider: Improve approximation when zero based and export
The fractional divider approximation does not utilize the full available range for clocks that are flagged CLK_FRAC_DIVIDER_ZERO_BASED. This patchset aims to fix that.
It also adds test cases for the edge cases of fractional divider clocks with and without the CLK_FRAC_DIVIDER_ZERO_BASED flag to highlight the changes.
Finally, it also exports clk_fractional_divider_general_approximation so that the test cases (but also other users like rockchip clk driver) can be compiled as a module.
Unfortunately, I have no boards to test this patch. So all we have are the unit tests. It seems the only user of this flag in mainline is drivers/clk/imx/clk-composite-7ulp.c, therefore I'm cc-ing get_maintainers.pl --git-blame -f drivers/clk/imx/clk-composite-7ulp.c in the hopes of a wider audience.
Thank you for considering this contribution,
Frank
V3: https://lore.kernel.org/all/[email protected]/
V2: https://lore.kernel.org/lkml/[email protected]/
V1: https://lore.kernel.org/lkml/[email protected]/
Changes in V4 (since V3):
- Export clk_fractional_divider_general_approximation so that users (e.g., the testcases) can be compiled as modules.
- Change test cases so that they test clk_fractional_divider_general_approximation again (like in V2) instead of clk_fd_round_rate (like in V3), but keeping the structure of V3 with separate file and individual test cases for each edge case.
Changes in V3 (since V2):
- Completely reworked the test cases
- Moved tests to separate file as per Stephen's request
- Move each edge case into their individual test case as per Stephen's request
- Test clk_fd_round_rate instead of clk_fractional_divider_general_approximation as testing the latter broke builds
Changes in V2 (since V1):
- Added test case as requested by Stephen Boyd
- Fixed commit message as the Cc: was missing a closing bracket, so that the original mail unfortunately did not go out to A. s. Dong.
Frank Oltmanns (2):
clk: fractional-divider: Improve approximation when zero based and
export
clk: fractional-divider: tests: Add test suite for edge cases
drivers/clk/.kunitconfig | 1 + drivers/clk/Kconfig | 7 + drivers/clk/Makefile | 1 + drivers/clk/clk-fractional-divider.c | 27 +++- drivers/clk/clk-fractional-divider_test.c | 161 ++++++++++++++++++++++ 5 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 drivers/clk/clk-fractional-divider_test.c
Signature · 1 line
2.41.0
PATCH v4 1/2 clk: fractional-divider: Improve approximation when zero based and export
Consider the CLK_FRAC_DIVIDER_ZERO_BASED flag when finding the best approximation for m and n. By doing so, increase the range of valid values for the numerator and denominator by 1.
Furthermore, export the approximation function so that users of this function can be compiled as modules.
--- drivers/clk/clk-fractional-divider.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
drivers/clk/clk-fractional-divider.c +20 -7
@@ -123,6 +123,7 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw, unsigned long *m, unsigned long *n) { struct clk_fractional_divider *fd = to_clk_fd(hw); +unsigned long max_m, max_n;/* * Get rate closer to *parent_rate to guarantee there is no overflow
@@ -138,10 +139,17 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw, rate <<= scale - fd->nwidth; } -rational_best_approximation (rate, *parent_rate, -GENMASK (fd->mwidth -1 ,0 ),GENMASK (fd->nwidth -1 ,0 ), - m, n); +if (fd->flags &CLK_FRAC_DIVIDER_ZERO_BASED ) { + max_m =1 << fd->mwidth; + max_n =1 << fd->nwidth; + }else { + max_m =GENMASK (fd->mwidth -1 ,0 ); + max_n =GENMASK (fd->nwidth -1 ,0 ); + } + +rational_best_approximation (rate, *parent_rate, max_m, max_n, m, n); } +EXPORT_SYMBOL_GPL (clk_fractional_divider_general_approximation);static long clk_fd_round_rate (struct clk_hw *hw,unsigned long rate,unsigned long *parent_rate)
@@ -169,13 +177,18 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate, {struct clk_fractional_divider *fd =to_clk_fd (hw);unsigned long flags =0 ; -unsigned long m, n; +unsigned long m, n, max_m, max_n;u32 mmask, nmask;u32 val; -rational_best_approximation (rate, parent_rate, -GENMASK (fd->mwidth -1 ,0 ),GENMASK (fd->nwidth -1 ,0 ), - &m, &n); +if (fd->flags &CLK_FRAC_DIVIDER_ZERO_BASED ) { + max_m =1 << fd->mwidth; + max_n =1 << fd->nwidth; + }else { + max_m =GENMASK (fd->mwidth -1 ,0 ); + max_n =GENMASK (fd->nwidth -1 ,0 ); + } +rational_best_approximation (rate, parent_rate, max_m, max_n, &m, &n);if (fd->flags &CLK_FRAC_DIVIDER_ZERO_BASED ) { m--;
Signature · 1 line
2.41.0
PATCH v4 2/2 clk: fractional-divider: tests: Add test suite for edge cases
In reply to Frank OltmannsIn 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 [1], implement tests for the edge cases of this clock type.
---
Please note: I get two checkpatch warnings for this patch:
- Concerning the help text in Kconfig.
- Regarding the file being added, asking if MAINTAINERS needs updating.
Both the help text as well as the MAINTAINERS file seem fine to me.
As expected, when the tests are run *without* PATCH 1, the two "zero based" test cases fail:
================= clk-fd-test (4 subtests) =================
[PASSED] clk_fd_test_approximation_max_denominator
[PASSED] clk_fd_test_approximation_max_numerator
# clk_fd_test_approximation_max_denominator_zero_based: EXPECTATION FAILED at drivers/clk/clk-fractional-divider_test.c:107 Expected n == max_n, but
n == 7 (0x7)
max_n == 8 (0x8)
[FAILED] clk_fd_test_approximation_max_denominator_zero_based
# clk_fd_test_approximation_max_numerator_zero_based: EXPECTATION FAILED at drivers/clk/clk-fractional-divider_test.c:138
Expected m == max_m, but
m == 7 (0x7)
max_m == 8 (0x8)[FAILED] clk_fd_test_approximation_max_numerator_zero_based # clk-fd-test: pass:2 fail:2 skip:0 total:4
# Totals: pass:2 fail:2 skip:0 total:4 =================== [FAILED] clk-fd-test ===================
Best regards,
Frank
drivers/clk/.kunitconfig | 1 + drivers/clk/Kconfig | 7 + drivers/clk/Makefile | 1 + drivers/clk/clk-fractional-divider_test.c | 161 ++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 drivers/clk/clk-fractional-divider_test.c
drivers/clk/Kconfig +7 -0
@@ -513,4 +513,11 @@ config CLK_GATE_KUNIT_TEST help Kunit test for the basic clk gate type. +config CLK_FD_KUNIT_TEST + tristate "Basic fractional divider type Kunit test" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Kunit test for the clk-fractional-divider type. + endif
drivers/clk/Makefile +1 -0
@@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o obj-$(CONFIG_COMMON_CLK) += clk-mux.o obj-$(CONFIG_COMMON_CLK) += clk-composite.o obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o +obj-$(CONFIG_CLK_FD_KUNIT_TEST) += clk-fractional-divider_test.o obj-$(CONFIG_COMMON_CLK) += clk-gpio.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o
drivers/clk/clk-fractional-divider_test.c new file +161 -0
161 lines not on this page · raw message
Signature · 1 line
2.41.0
kernel test robot
build botRe: [PATCH v4 2/2] clk: fractional-divider: tests: Add test suite for edge cases
kernel test robot noticed the following build warnings:
Hi Frank,
kernel test robot noticed the following build warnings:
[auto build test WARNING on clk/clk-next]
[also build test WARNING on linus/master v6.4-rc6 next-20230616] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Frank-Oltmanns/clk-fractional-divider-Improve-approximation-when-zero-based-and-export/20230617-183118 base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next patch link: https://lore.kernel.org/r/20230617102919.27564-3-frank%40oltmanns.dev patch subject: [PATCH v4 2/2] clk: fractional-divider: tests: Add test suite for edge cases config: arm-randconfig-r046-20230617 (https://download.01.org/0day-ci/archive/20230617/[email protected]/config) compiler: arm-linux-gnueabi-gcc (GCC) 12.3.0 reproduce: (https://download.01.org/0day-ci/archive/20230617/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
drivers/clk/clk-fractional-divider_test.c: In function 'clk_fd_test_approximation_max_denominator':
>> drivers/clk/clk-fractional-divider_test.c:26:48: warning: variable 'max_m' set but not used [-Wunused-but-set-variable]
26 | unsigned long rate, parent_rate, m, n, max_m, max_n;
| ^~~~~
drivers/clk/clk-fractional-divider_test.c: In function 'clk_fd_test_approximation_max_denominator_zero_based':
drivers/clk/clk-fractional-divider_test.c:88:48: warning: variable 'max_m' set but not used [-Wunused-but-set-variable]
88 | unsigned long rate, parent_rate, m, n, max_m, max_n;
| ^~~~~vim +/max_m +26 drivers/clk/clk-fractional-divider_test.c
15
16 /*
17 * Test the maximum denominator case for fd clock without flags.
18 *
19 * Expect the highest possible denominator to be used in order to get as close as possible to the
20 * requested rate.
21 */
22 static void clk_fd_test_approximation_max_denominator(struct kunit *test)
23 {
24 struct clk_fractional_divider *fd;
25 struct clk_hw *hw;
> 26 unsigned long rate, parent_rate, m, n, max_m, max_n;
27
28 fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
29 KUNIT_ASSERT_NOT_NULL(test, fd);
30
31 fd->mwidth = 3;
32 max_m = 7;
33 fd->nwidth = 3;
34 max_n = 7;
35
36 hw = &fd->hw;
37
38 rate = 240000000;
39 parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
40
41 clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
42 KUNIT_EXPECT_EQ(test, parent_rate, (max_n + 1) * rate); /* parent remains unchanged */
43 KUNIT_EXPECT_EQ(test, m, 1);
44 KUNIT_EXPECT_EQ(test, n, max_n);
45 }
46 Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [PATCH v4 2/2] clk: fractional-divider: tests: Add test suite for edge cases
In reply to Frank Oltmannskernel test robot noticed the following build warnings:
Hi Frank,
kernel test robot noticed the following build warnings:
[auto build test WARNING on clk/clk-next]
[also build test WARNING on linus/master v6.4-rc6 next-20230616] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Frank-Oltmanns/clk-fractional-divider-Improve-approximation-when-zero-based-and-export/20230617-183118 base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next patch link: https://lore.kernel.org/r/20230617102919.27564-3-frank%40oltmanns.dev patch subject: [PATCH v4 2/2] clk: fractional-divider: tests: Add test suite for edge cases config: hexagon-randconfig-r035-20230617 (https://download.01.org/0day-ci/archive/20230617/[email protected]/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a) reproduce: (https://download.01.org/0day-ci/archive/20230617/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
>> drivers/clk/clk-fractional-divider_test.c:26:41: warning: variable 'max_m' set but not used [-Wunused-but-set-variable]
26 | unsigned long rate, parent_rate, m, n, max_m, max_n;
| ^
drivers/clk/clk-fractional-divider_test.c:88:41: warning: variable 'max_m' set but not used [-Wunused-but-set-variable]
88 | unsigned long rate, parent_rate, m, n, max_m, max_n;
| ^2 warnings generated.
vim +/max_m +26 drivers/clk/clk-fractional-divider_test.c
15
16 /*
17 * Test the maximum denominator case for fd clock without flags.
18 *
19 * Expect the highest possible denominator to be used in order to get as close as possible to the
20 * requested rate.
21 */
22 static void clk_fd_test_approximation_max_denominator(struct kunit *test)
23 {
24 struct clk_fractional_divider *fd;
25 struct clk_hw *hw;
> 26 unsigned long rate, parent_rate, m, n, max_m, max_n;
27
28 fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL);
29 KUNIT_ASSERT_NOT_NULL(test, fd);
30
31 fd->mwidth = 3;
32 max_m = 7;
33 fd->nwidth = 3;
34 max_n = 7;
35
36 hw = &fd->hw;
37
38 rate = 240000000;
39 parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */
40
41 clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n);
42 KUNIT_EXPECT_EQ(test, parent_rate, (max_n + 1) * rate); /* parent remains unchanged */
43 KUNIT_EXPECT_EQ(test, m, 1);
44 KUNIT_EXPECT_EQ(test, n, max_n);
45 }
46 Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Re: [PATCH v4 2/2] clk: fractional-divider: tests: Add test suite for edge cases
Quoted 25 lines · kernel test robot
Hi Frank,
kernel test robot noticed the following build warnings:
[auto build test WARNING on clk/clk-next]
[also build test WARNING on linus/master v6.4-rc6 next-20230616] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]url: https://github.com/intel-lab-lkp/linux/commits/Frank-Oltmanns/clk-fractional-divider-Improve-approximation-when-zero-based-and-export/20230617-183118 base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next patch link: https://lore.kernel.org/r/20230617102919.27564-3-frank%40oltmanns.dev patch subject: [PATCH v4 2/2] clk: fractional-divider: tests: Add test suite for edge cases config: hexagon-randconfig-r035-20230617 (https://download.01.org/0day-ci/archive/20230617/[email protected]/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a) reproduce: (https://download.01.org/0day-ci/archive/20230617/[email protected]/reproduce)If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/All warnings (new ones prefixed by >>):
Quoted 7 lines
Quoted 1 line
Quoted 1 line
drivers/clk/clk-fractional-divider_test.c:26:41: warning: variable 'max_m' set but not used [-Wunused-but-set-variable]26 | unsigned long rate, parent_rate, m, n, max_m, max_n; | ^ drivers/clk/clk-fractional-divider_test.c:88:41: warning: variable 'max_m' set but not used [-Wunused-but-set-variable] 88 | unsigned long rate, parent_rate, m, n, max_m, max_n; | ^2 warnings generated.
Clang compiler warnings are fixed in version 5:
https://lore.kernel.org/all/[email protected]/
Quoted 36 lines
vim +/max_m +26
drivers/clk/clk-fractional-divider_test.c15 16 /* 17 * Test the maximum denominator case for fd clock without flags. 18 * 19 * Expect the highest possible denominator to be used in order to get as close as possible to the 20 * requested rate. 21 */ 22 static void clk_fd_test_approximation_max_denominator(struct kunit *test) 23 { 24 struct clk_fractional_divider *fd; 25 struct clk_hw *hw;Quoted 1 line
26 unsigned long rate,
parent_rate, m, n,max_m,max_n;27 28 fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); 29 KUNIT_ASSERT_NOT_NULL(test, fd); 30 31 fd->mwidth = 3; 32 max_m = 7; 33 fd->nwidth = 3; 34 max_n = 7; 35 36 hw = &fd->hw; 37 38 rate = 240000000; 39 parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */ 40 41 clk_fractional_divider_general_approximation(hw, rate, &parent_rate, &m, &n); 42 KUNIT_EXPECT_EQ(test, parent_rate, (max_n + 1) * rate); /* parent remains unchanged */ 43 KUNIT_EXPECT_EQ(test, m, 1); 44 KUNIT_EXPECT_EQ(test, n, max_n); 45 } 46