[PATCH] clk: sunxi: clean up rate counting

Anastasia Belova
2025-02-03T11:30:20Z

If n = 255, the result of multiplication of n and 24000000
may not fit int type. Swap division and shift with multiplication.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: 6424e0aeebc4 ("clk: sunxi: rewrite sun9i_a80_get_pll4_factors()")
Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
---
drivers/clk/sunxi/clk-sun9i-core.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
index d93c7a53c6c0..639c83ed63b8 100644
--- a/drivers/clk/sunxi/clk-sun9i-core.c
+++ b/drivers/clk/sunxi/clk-sun9i-core.c
@@ -25,12 +25,12 @@

static void sun9i_a80_get_pll4_factors(struct factors_request *req)
{
- int n;
- int m = 1;
- int p = 1;
+ unsigned int n;
+ unsigned int m = 1;
+ unsigned int p = 1;

/* Normalize value to a 6 MHz multiple (24 MHz / 4) */
- n = DIV_ROUND_UP(req->rate, 6000000);
+ n = DIV_ROUND_UP(req->rate, 6000000ul);

/* If n is too large switch to steps of 12 MHz */
if (n > 255) {
@@ -50,7 +50,11 @@ static void sun9i_a80_get_pll4_factors(struct factors_request *req)
else if (n < 12)
n = 12;

- req->rate = ((24000000 * n) >> p) / (m + 1);
+ /* Division and shift should be done before multiplication to
+ * avoid overflow. The result will be correct because '>> p' and
+ * '/ (m + 1)' are both just conditional 'divide by 2'
+ */
+ req->rate = ((24000000ul >> p) / (m + 1)) * n;
req->n = n;
req->m = m;
req->p = p;
--
2.43.0