clk: fractional-divider: cast parent_rate to u64 before multiplying
PATCH 1/1 clk: fractional-divider: cast parent_rate to u64 before multiplying
On 32bit architectures, like ARM calculating the fractional rate will do the multiplication before converting the value to u64 when it gets assigned to ret, which can produce overflows.
The error in question happened with a parent_rate of 386MHz, m = 3000, n = 60000, which resulted in a wrong rate value of 15812Hz.
Therefore cast parent_rate to u64 to make sure the multiplication happens in a 64bit space and produces the correct 192MHz in the example.
--- drivers/clk/clk-fractional-divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/clk-fractional-divider.c +1 -1
@@ -36,7 +36,7 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, m = (val & fd->mmask) >> fd->mshift; n = (val & fd->nmask) >> fd->nshift; - ret = parent_rate * m; + ret = (u64 )parent_rate * m;do_div (ret, n);return ret;
Signature · 1 line
2.0.1
A message that is not in the archive (sent off-list or not yet received): 20140902002629.5251.42667@quantum
Am Montag, 1. September 2014, 17:26:29 schrieb Mike Turquette:
Quoted 12 lines
Quoting Heiko Stübner (2014-08-28 03:46:10)
Quoted 10 lines
On 32bit architectures, like ARM calculating the fractional rate will do the multiplication before converting the value to u64 when it gets assigned to ret, which can produce overflows.
The error in question happened with a
parent_rateof 386MHz, m = 3000, n = 60000, which resulted in a wrong rate value of 15812Hz.Therefore cast
parent_rateto u64 to make sure the multiplication happens in a 64bit space and produces the correct 192MHz in the example.
Quoted 8 lines
Quoted 1 line
Signed-off-by Heiko Stuebner <[email protected]>Looks good to me. Have you observed this issue using the vanilla kernel.org sources or on a downstream tree? I'm trying to decide if I should take this into clk-fixes or clk-next.
If this doesn't happen in practice on any merged platform then I'll take it for 3.18.
It happens on the Rockchip platform with the newly added fractional branches you just applied ... so it doesn't look like anybody else is affected right now.
Heiko
Quoted 24 lines
Regards,
MikeQuoted 20 lines
---
drivers/clk/clk-fractional-divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)(quoted diff) +0
-0
b/drivers/clk/clk-fractional-divider.cindex ede685c..82a59d0 100644drivers/clk/clk-fractional-divider.c +1
-1@@ -36,7 +36,7 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,> m = (val & fd->mmask) >> fd->mshift; n = (val & fd->nmask) >> fd->nshift; - ret = parent_rate * m; + ret = (u64 )parent_rate * m;do_div (ret, n);return ret;
Hi Mike,
Am Dienstag, 2. September 2014, 09:33:21 schrieb Heiko Stübner:
Quoted 19 lines
Am Montag, 1. September 2014, 17:26:29 schrieb Mike Turquette:
Quoted 18 lines
Quoting Heiko Stübner (2014-08-28 03:46:10)
Quoted 11 lines
On 32bit architectures, like ARM calculating the fractional rate will do the multiplication before converting the value to u64 when it gets assigned to ret, which can produce overflows.
The error in question happened with a
parent_rateof 386MHz, m = 3000, n = 60000, which resulted in a wrong rate value of 15812Hz.Therefore cast
parent_rateto u64 to make sure the multiplication happens in a 64bit space and produces the correct 192MHz in the example.Signed-off-by Heiko Stuebner <[email protected]>Looks good to me. Have you observed this issue using the vanilla kernel.org sources or on a downstream tree? I'm trying to decide if I should take this into clk-fixes or clk-next.
Quoted 6 lines
Quoted 2 lines
If this doesn't happen in practice on any merged platform then I'll take it for 3.18.
It happens on the Rockchip platform with the newly added fractional branches you just applied ... so it doesn't look like anybody else is affected right now.
will you take this one into clk-next?
Thanks
Heiko
Quoted 28 lines
Heiko
Quoted 24 lines
Regards,
MikeQuoted 21 lines
---
drivers/clk/clk-fractional-divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)(quoted diff) +0
-0
b/drivers/clk/clk-fractional-divider.cindex ede685c..82a59d0 100644drivers/clk/clk-fractional-divider.c +1
-1@@ -36,7 +36,7 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,> m = (val & fd->mmask) >> fd->mshift; n = (val & fd->nmask) >> fd->nshift; - ret = parent_rate * m; + ret = (u64 )parent_rate * m;do_div(ret, n); return ret;