On 01/25/2016 06:53 PM, Guenter Roeck wrote:
From: Guenter Roeck <linux@xxxxxxxxxxxx> The watchdog infrastructure now supports handling watchdog keepalive if the watchdog is running while the watchdog device is closed. Convert the driver to use this infrastructure. Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
I managed to test this patch with qemu (after implementing the imx2 watchdog in qemu). It works as expected, so please consider it upgraded from RFT to a "real" patch. Guenter
--- v7: Set max_hw_timeout_ms Rebased to v4.5-rc1 v6: Rename WDOG_RUNNING to WDOG_HW_RUNNING Rebased to v4.4-rc2 v5: Rebased to v4.4-rc1 v4: No changes v3: No changes v2: No changes --- drivers/watchdog/imx2_wdt.c | 74 ++++++++------------------------------------- 1 file changed, 13 insertions(+), 61 deletions(-) diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index e47966aa2db0..1a48cb28718f 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -25,14 +25,12 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> -#include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/regmap.h> -#include <linux/timer.h> #include <linux/watchdog.h> #define DRIVER_NAME "imx2-wdt" @@ -60,7 +58,6 @@ struct imx2_wdt_device { struct clk *clk; struct regmap *regmap; - struct timer_list timer; /* Pings the watchdog when closed */ struct watchdog_device wdog; }; @@ -146,16 +143,6 @@ static int imx2_wdt_ping(struct watchdog_device *wdog) return 0; } -static void imx2_wdt_timer_ping(unsigned long arg) -{ - struct watchdog_device *wdog = (struct watchdog_device *)arg; - struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); - - /* ping it every wdog->timeout / 2 seconds to prevent reboot */ - imx2_wdt_ping(wdog); - mod_timer(&wdev->timer, jiffies + wdog->timeout * HZ / 2); -} - static int imx2_wdt_set_timeout(struct watchdog_device *wdog, unsigned int new_timeout) { @@ -172,40 +159,19 @@ static int imx2_wdt_start(struct watchdog_device *wdog) { struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); - if (imx2_wdt_is_running(wdev)) { - /* delete the timer that pings the watchdog after close */ - del_timer_sync(&wdev->timer); + if (imx2_wdt_is_running(wdev)) imx2_wdt_set_timeout(wdog, wdog->timeout); - } else + else imx2_wdt_setup(wdog); - return imx2_wdt_ping(wdog); -} - -static int imx2_wdt_stop(struct watchdog_device *wdog) -{ - /* - * We don't need a clk_disable, it cannot be disabled once started. - * We use a timer to ping the watchdog while /dev/watchdog is closed - */ - imx2_wdt_timer_ping((unsigned long)wdog); - return 0; -} - -static inline void imx2_wdt_ping_if_active(struct watchdog_device *wdog) -{ - struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); + set_bit(WDOG_HW_RUNNING, &wdog->status); - if (imx2_wdt_is_running(wdev)) { - imx2_wdt_set_timeout(wdog, wdog->timeout); - imx2_wdt_timer_ping((unsigned long)wdog); - } + return imx2_wdt_ping(wdog); } static const struct watchdog_ops imx2_wdt_ops = { .owner = THIS_MODULE, .start = imx2_wdt_start, - .stop = imx2_wdt_stop, .ping = imx2_wdt_ping, .set_timeout = imx2_wdt_set_timeout, .restart = imx2_wdt_restart, @@ -253,7 +219,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) wdog->info = &imx2_wdt_info; wdog->ops = &imx2_wdt_ops; wdog->min_timeout = 1; - wdog->max_timeout = IMX2_WDT_MAX_TIME; + wdog->max_hw_timeout_ms = IMX2_WDT_MAX_TIME * 1000; wdog->parent = &pdev->dev; ret = clk_prepare_enable(wdev->clk); @@ -274,9 +240,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) watchdog_set_restart_priority(wdog, 128); watchdog_init_timeout(wdog, timeout, &pdev->dev); - setup_timer(&wdev->timer, imx2_wdt_timer_ping, (unsigned long)wdog); - - imx2_wdt_ping_if_active(wdog); + if (imx2_wdt_is_running(wdev)) { + imx2_wdt_set_timeout(wdog, wdog->timeout); + set_bit(WDOG_HW_RUNNING, &wdog->status); + } /* * Disable the watchdog power down counter at boot. Otherwise the power @@ -309,7 +276,6 @@ static int __exit imx2_wdt_remove(struct platform_device *pdev) watchdog_unregister_device(wdog); if (imx2_wdt_is_running(wdev)) { - del_timer_sync(&wdev->timer); imx2_wdt_ping(wdog); dev_crit(&pdev->dev, "Device removed: Expect reboot!\n"); } @@ -323,10 +289,9 @@ static void imx2_wdt_shutdown(struct platform_device *pdev) if (imx2_wdt_is_running(wdev)) { /* - * We are running, we need to delete the timer but will - * give max timeout before reboot will take place + * We are running, configure max timeout before reboot + * will take place. */ - del_timer_sync(&wdev->timer); imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); imx2_wdt_ping(wdog); dev_crit(&pdev->dev, "Device shutdown: Expect reboot!\n"); @@ -344,10 +309,6 @@ static int imx2_wdt_suspend(struct device *dev) if (imx2_wdt_is_running(wdev)) { imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); imx2_wdt_ping(wdog); - - /* The watchdog is not active */ - if (!watchdog_active(wdog)) - del_timer_sync(&wdev->timer); } clk_disable_unprepare(wdev->clk); @@ -373,19 +334,10 @@ static int imx2_wdt_resume(struct device *dev) * watchdog again. */ imx2_wdt_setup(wdog); + } + if (imx2_wdt_is_running(wdev)) { imx2_wdt_set_timeout(wdog, wdog->timeout); imx2_wdt_ping(wdog); - } else if (imx2_wdt_is_running(wdev)) { - /* Resuming from non-deep sleep state. */ - imx2_wdt_set_timeout(wdog, wdog->timeout); - imx2_wdt_ping(wdog); - /* - * But the watchdog is not active, then start - * the timer again. - */ - if (!watchdog_active(wdog)) - mod_timer(&wdev->timer, - jiffies + wdog->timeout * HZ / 2); } return 0;
-- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html