mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
BACKPORT: watchdog: dw_wdt: Read clock rate only once and validate it
Coverity reports: divide_by_zero: In expression readl(dw_wdt->regs + 8) / clk_get_rate(dw_wdt->clk), division by expression clk_get_rate(dw_wdt->clk) which may be zero has undefined behavior. The clock used for the watchdog timer won't change its rate, so read it only once during probe. Also validate it and abort the probe function with an error if it is 0. Cc: Douglas Anderson <dianders@chromium.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> (cherry picked from commitc97344f73f) Conflicts: drivers/watchdog/dw_wdt.c [due to missing:f29a72c24a"watchdog: dw_wdt: Convert to use watchdog infrastructure" and local version of:3024e0d13b"watchdog: dw_wdt: fix signedness bug in dw_wdt_top_in_seconds()"] Change-Id: Iea745e27224532bf4da560e5952b372289d1c6ae Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
This commit is contained in:
@@ -63,6 +63,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
|
||||
static struct {
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
unsigned long rate;
|
||||
unsigned long in_use;
|
||||
unsigned long next_heartbeat;
|
||||
struct timer_list timer;
|
||||
@@ -85,9 +86,7 @@ static inline int dw_wdt_top_in_seconds(unsigned top)
|
||||
* There are 16 possible timeout values in 0..15 where the number of
|
||||
* cycles is 2 ^ (16 + i) and the watchdog counts down.
|
||||
*/
|
||||
unsigned int cycles = 1 << (16 + top);
|
||||
|
||||
return cycles / clk_get_rate(dw_wdt.clk);
|
||||
return (1U << (16 + top)) / dw_wdt.rate;
|
||||
}
|
||||
|
||||
static int dw_wdt_get_top(void)
|
||||
@@ -236,7 +235,7 @@ static ssize_t dw_wdt_write(struct file *filp, const char __user *buf,
|
||||
static u32 dw_wdt_time_left(void)
|
||||
{
|
||||
return readl(dw_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
|
||||
clk_get_rate(dw_wdt.clk);
|
||||
dw_wdt.rate;
|
||||
}
|
||||
|
||||
static const struct watchdog_info dw_wdt_ident = {
|
||||
@@ -362,6 +361,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dw_wdt.rate = clk_get_rate(dw_wdt.clk);
|
||||
if (dw_wdt.rate == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_disable_clk;
|
||||
}
|
||||
|
||||
ret = misc_register(&dw_wdt_miscdev);
|
||||
if (ret)
|
||||
goto out_disable_clk;
|
||||
|
||||
Reference in New Issue
Block a user