mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
watchdog: digicolor: Avoid division by zero
clk_get_rate() could return 0. Avoid a division by zero panic.
Since get_timeleft() cannot propagate errors, check the clock rate early
in probe() and cache the rate in the driver data as it is unlikely to
change at runtime.
Fixes: 336694a01d ("watchdog: digicolor: driver for Conexant Digicolor CX92755 SoC")
Cc: stable@vger.kernel.org
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Acked-by: Baruch Siach <baruch@tkos.co.il>
Link: https://patch.msgid.link/20260913064851.8239-2-tzungbi@kernel.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
88f1136340
commit
400cb663ca
|
|
@ -25,6 +25,7 @@ struct dc_wdt {
|
|||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
spinlock_t lock;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
||||
static unsigned timeout;
|
||||
|
|
@ -61,7 +62,7 @@ static int dc_wdt_start(struct watchdog_device *wdog)
|
|||
{
|
||||
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
|
||||
dc_wdt_set(wdt, wdog->timeout * clk_get_rate(wdt->clk));
|
||||
dc_wdt_set(wdt, wdog->timeout * wdt->rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -79,7 +80,7 @@ static int dc_wdt_set_timeout(struct watchdog_device *wdog, unsigned int t)
|
|||
{
|
||||
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
|
||||
dc_wdt_set(wdt, t * clk_get_rate(wdt->clk));
|
||||
dc_wdt_set(wdt, t * wdt->rate);
|
||||
wdog->timeout = t;
|
||||
|
||||
return 0;
|
||||
|
|
@ -90,7 +91,7 @@ static unsigned int dc_wdt_get_timeleft(struct watchdog_device *wdog)
|
|||
struct dc_wdt *wdt = watchdog_get_drvdata(wdog);
|
||||
uint32_t count = readl_relaxed(wdt->base + TIMER_A_COUNT);
|
||||
|
||||
return count / clk_get_rate(wdt->clk);
|
||||
return count / wdt->rate;
|
||||
}
|
||||
|
||||
static const struct watchdog_ops dc_wdt_ops = {
|
||||
|
|
@ -130,7 +131,11 @@ static int dc_wdt_probe(struct platform_device *pdev)
|
|||
wdt->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(wdt->clk))
|
||||
return PTR_ERR(wdt->clk);
|
||||
dc_wdt_wdd.max_timeout = U32_MAX / clk_get_rate(wdt->clk);
|
||||
|
||||
wdt->rate = clk_get_rate(wdt->clk);
|
||||
if (!wdt->rate)
|
||||
return -EINVAL;
|
||||
dc_wdt_wdd.max_timeout = U32_MAX / wdt->rate;
|
||||
dc_wdt_wdd.timeout = dc_wdt_wdd.max_timeout;
|
||||
dc_wdt_wdd.parent = dev;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user