From 8d2b10eef6f3b1336be2d1197db29b0c697f1d41 Mon Sep 17 00:00:00 2001 From: Surendra Singh Chouhan Date: Thu, 23 Jul 2026 07:56:34 +0530 Subject: [PATCH 1/3] watchdog: atcwdt200: fix return value when watchdog is enabled atcwdt_get_int_timer_type() returned TMR_UNKNOWN (enum value 3) when CTRL_WDT_EN was set in the control register. Because atcwdt_probe() checks "ret = atcwdt_get_int_timer_type(drv_data); if (ret) return ret;", returning TMR_UNKNOWN caused probe() to return 3 instead of a valid negative error code. Fix this by returning -EBUSY via dev_err_probe() when the watchdog is already enabled and update the kernel-doc description accordingly. Fixes: e4e0848ad046 ("watchdog: atcwdt200: Add driver for Andes ATCWDT200") Signed-off-by: Surendra Singh Chouhan Link: https://lore.kernel.org/r/20260723022634.8642-1-kr494167@gmail.com Signed-off-by: Guenter Roeck --- drivers/watchdog/atcwdt200_wdt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/atcwdt200_wdt.c b/drivers/watchdog/atcwdt200_wdt.c index 8e3b18aea368..7e757c217b0b 100644 --- a/drivers/watchdog/atcwdt200_wdt.c +++ b/drivers/watchdog/atcwdt200_wdt.c @@ -260,9 +260,9 @@ static void atcwdt_get_timeout_params(struct atcwdt_drv *drv_data, * register to determine the interrupt timer type supported by the hardware. * * Note: This function must only be called when the ATCWDT200 watchdog is - * disabled. If the watchdog is enabled, this function returns TMR_UNKNOWN. + * disabled. If the watchdog is enabled, this function returns -EBUSY. * - * Returns: The interrupt timer type supported by the hardware. + * Returns: 0 on success or negative error code on failure. */ static int atcwdt_get_int_timer_type(struct atcwdt_drv *drv_data) { @@ -274,7 +274,8 @@ static int atcwdt_get_int_timer_type(struct atcwdt_drv *drv_data) regmap_read(drv_data->regmap, REG_CTRL, &val); if (val & CTRL_WDT_EN) { spin_unlock(&drv_data->lock); - return TMR_UNKNOWN; + return dev_err_probe(dev, -EBUSY, + "Watchdog is enabled, cannot detect timer type\n"); } /* From 1246aa2b6ccc8944676bd24ff3e37cc56b93b51b Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 31 Jul 2026 12:36:28 +0300 Subject: [PATCH 2/3] watchdog: bd96801_wdt: Fix timeout for enabled WDG When watchdog is enabled at the probe time, the bd96801 driver retrieves the timeout configuration from the registers to set-up the heart-beat values. As Sashiko pointed out at https://lore.kernel.org/all/20260722085819.495211F000E9@smtp.kernel.org/ the timeout values are incorrectly computed in driver, resulting wrong heartbeat. This leads to devere problems if watchdog was enabled at probe time. According to the data-sheet, the "too fast" ping limit is configured as multiple of FASTNG_MIN. Furthermore, the "too slow" ping limit is configured as multiples of "too fast" timeout. The FASTNG_MIN is set to 11, meaning 1.1 mS and "too fast" and "too slow" limits are computed from this. Hence, converting the limits to mS should be done by dividing by 10, not by dividing by USEC_PER_MSEC. Fix this by dividing the timeout values with correct scaling factor. While at it, fix whitespace problem (double empty line). Signed-off-by: Matti Vaittinen Fixes: 09dad69757b6 ("watchdog: ROHM BD96801 PMIC WDG driver") Link: https://lore.kernel.org/r/amxskHmQbi9v-8_l@mva-rohm [groeck: Added reference to whitespace change to description] Signed-off-by: Guenter Roeck --- drivers/watchdog/bd96801_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/bd96801_wdt.c b/drivers/watchdog/bd96801_wdt.c index 12b74fd2bc05..a25b7cf1488b 100644 --- a/drivers/watchdog/bd96801_wdt.c +++ b/drivers/watchdog/bd96801_wdt.c @@ -169,7 +169,6 @@ static int bd96801_set_wdt_mode(struct wdtbd96801 *w, unsigned int hw_margin, int fastng, slowng, type, ret, reg, mask; struct device *dev = w->dev; - if (hw_margin_min * 1000 > FASTNG_MAX_US) { dev_err(dev, "Unsupported fast timeout %u uS [max %u]\n", hw_margin_min * 1000, FASTNG_MAX_US); @@ -258,10 +257,10 @@ static int bd96801_set_heartbeat_from_hw(struct wdtbd96801 *w, fast = FASTNG_MIN << sel; sel = (val & BD96801_WD_RATIO_MASK) + 1; - w->wdt.max_hw_heartbeat_ms = (fast << sel) / USEC_PER_MSEC; + w->wdt.max_hw_heartbeat_ms = (fast << sel) / 10; if ((conf_reg & BD96801_WD_TYPE_MASK) == BD96801_WD_TYPE_WIN) - w->wdt.min_hw_heartbeat_ms = fast / USEC_PER_MSEC; + w->wdt.min_hw_heartbeat_ms = fast / 10; return 0; } From 8444d66aa6b6e7fe0a26fa1a00a11cb4d0523783 Mon Sep 17 00:00:00 2001 From: Hongyan Xu Date: Thu, 6 Aug 2026 14:06:13 +0800 Subject: [PATCH 3/3] watchdog: at91sam9_wdt: prevent timer rearm during teardown at91_ping() rearms the watchdog timer from its callback. timer_delete() neither waits for a running callback nor prevents it from rearming the timer, so probe failure or driver removal can leave the timer accessing the devm-allocated at91wdt after it has been freed. Use timer_shutdown_sync() on both teardown paths. It waits for a running callback and rejects any attempt by the callback to rearm the timer. Fixes: 5161b31dc39a ("watchdog: at91sam9_wdt: better watchdog support") Signed-off-by: Hongyan Xu Link: https://lore.kernel.org/r/20260806060613.1830-1-getshell@seu.edu.cn Signed-off-by: Guenter Roeck --- drivers/watchdog/at91sam9_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index aba66b8e9d03..80ba04df54ad 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -242,7 +242,7 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt) return 0; out_stop_timer: - timer_delete(&wdt->timer); + timer_shutdown_sync(&wdt->timer); return err; } @@ -378,7 +378,7 @@ static void at91wdt_remove(struct platform_device *pdev) watchdog_unregister_device(&wdt->wdd); pr_warn("I quit now, hardware will probably reboot!\n"); - timer_delete(&wdt->timer); + timer_shutdown_sync(&wdt->timer); } #if defined(CONFIG_OF)