diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-11 09:59:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-11 09:59:37 -0700 |
commit | 07d306c838c5c30196619baae36107d0615e459b (patch) | |
tree | 5a96d43b193cc001853e3fd8f0fcf853a7bd9d67 /drivers/watchdog/gpio_wdt.c | |
parent | a3ddacbae5abc0a5aabb1e75b655e8cd6dc83888 (diff) | |
parent | c013b65ad8a1e132f733404809afc72f7d00e768 (diff) |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- Add Renesas RZ/A WDT Watchdog driver
- STM32 Independent WatchDoG (IWDG) support
- UniPhier watchdog support
- Add F71868 support
- Add support for NCT6793D and NCT6795D
- dw_wdt: add reset lines support
- core: add option to avoid early handling of watchdog
- core: introduce watchdog_worker_should_ping helper
- Cleanups and improvements for sama5d4, intel-mid_wdt, s3c2410_wdt,
orion_wdt, gpio_wdt, it87_wdt, meson_wdt, davinci_wdt, bcm47xx_wdt,
zx2967_wdt, cadence_wdt
* git://www.linux-watchdog.org/linux-watchdog: (32 commits)
watchdog: introduce watchdog_worker_should_ping helper
watchdog: uniphier: add UniPhier watchdog driver
dt-bindings: watchdog: add description for UniPhier WDT controller
watchdog: cadence_wdt: make of_device_ids const.
watchdog: zx2967: constify zx2967_wdt_ops.
watchdog: bcm47xx_wdt: constify bcm47xx_wdt_hard_ops and bcm47xx_wdt_soft_ops
watchdog: davinci: Add missing clk_disable_unprepare().
watchdog: davinci: Handle return value of clk_prepare_enable
watchdog: meson: Handle return value of clk_prepare_enable
watchdog: it87: Add support for various Super-IO chips
watchdog: it87: Use infrastructure to stop watchdog on reboot
watchdog: it87: Drop support for resetting watchdog though CIR and Game port
watchdog: it87: Convert to use watchdog core infrastructure
watchdog: it87: Drop FSF mailing address
watchdog: dw_wdt: get reset lines from dt
watchdog: bindings: dw_wdt: add reset lines
watchdog: w83627hf: Add support for NCT6793D and NCT6795D
watchdog: core: add option to avoid early handling of watchdog
watchdog: f71808e_wdt: Add F71868 support
watchdog: Add STM32 IWDG driver
...
Diffstat (limited to 'drivers/watchdog/gpio_wdt.c')
-rw-r--r-- | drivers/watchdog/gpio_wdt.c | 73 |
1 files changed, 13 insertions, 60 deletions
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index 93457cabc178..cb66c2f99ff1 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c @@ -18,7 +18,6 @@ #define SOFT_TIMEOUT_MIN 1 #define SOFT_TIMEOUT_DEF 60 -#define SOFT_TIMEOUT_MAX 0xffff enum { HW_ALGO_TOGGLE, @@ -30,11 +29,7 @@ struct gpio_wdt_priv { bool active_low; bool state; bool always_running; - bool armed; unsigned int hw_algo; - unsigned int hw_margin; - unsigned long last_jiffies; - struct timer_list timer; struct watchdog_device wdd; }; @@ -47,21 +42,10 @@ static void gpio_wdt_disable(struct gpio_wdt_priv *priv) gpio_direction_input(priv->gpio); } -static void gpio_wdt_hwping(unsigned long data) +static int gpio_wdt_ping(struct watchdog_device *wdd) { - struct watchdog_device *wdd = (struct watchdog_device *)data; struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); - if (priv->armed && time_after(jiffies, priv->last_jiffies + - msecs_to_jiffies(wdd->timeout * 1000))) { - dev_crit(wdd->parent, - "Timer expired. System will reboot soon!\n"); - return; - } - - /* Restart timer */ - mod_timer(&priv->timer, jiffies + priv->hw_margin); - switch (priv->hw_algo) { case HW_ALGO_TOGGLE: /* Toggle output pin */ @@ -75,55 +59,33 @@ static void gpio_wdt_hwping(unsigned long data) gpio_set_value_cansleep(priv->gpio, priv->active_low); break; } -} - -static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv) -{ - priv->state = priv->active_low; - gpio_direction_output(priv->gpio, priv->state); - priv->last_jiffies = jiffies; - gpio_wdt_hwping((unsigned long)&priv->wdd); + return 0; } static int gpio_wdt_start(struct watchdog_device *wdd) { struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); - gpio_wdt_start_impl(priv); - priv->armed = true; + priv->state = priv->active_low; + gpio_direction_output(priv->gpio, priv->state); - return 0; + set_bit(WDOG_HW_RUNNING, &wdd->status); + + return gpio_wdt_ping(wdd); } static int gpio_wdt_stop(struct watchdog_device *wdd) { struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); - priv->armed = false; if (!priv->always_running) { - mod_timer(&priv->timer, 0); gpio_wdt_disable(priv); + clear_bit(WDOG_HW_RUNNING, &wdd->status); } return 0; } -static int gpio_wdt_ping(struct watchdog_device *wdd) -{ - struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd); - - priv->last_jiffies = jiffies; - - return 0; -} - -static int gpio_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) -{ - wdd->timeout = t; - - return gpio_wdt_ping(wdd); -} - static const struct watchdog_info gpio_wdt_ident = { .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, @@ -135,7 +97,6 @@ static const struct watchdog_ops gpio_wdt_ops = { .start = gpio_wdt_start, .stop = gpio_wdt_stop, .ping = gpio_wdt_ping, - .set_timeout = gpio_wdt_set_timeout, }; static int gpio_wdt_probe(struct platform_device *pdev) @@ -185,9 +146,6 @@ static int gpio_wdt_probe(struct platform_device *pdev) if (hw_margin < 2 || hw_margin > 65535) return -EINVAL; - /* Use safe value (1/2 of real timeout) */ - priv->hw_margin = msecs_to_jiffies(hw_margin / 2); - priv->always_running = of_property_read_bool(pdev->dev.of_node, "always-running"); @@ -196,31 +154,26 @@ static int gpio_wdt_probe(struct platform_device *pdev) priv->wdd.info = &gpio_wdt_ident; priv->wdd.ops = &gpio_wdt_ops; priv->wdd.min_timeout = SOFT_TIMEOUT_MIN; - priv->wdd.max_timeout = SOFT_TIMEOUT_MAX; + priv->wdd.max_hw_heartbeat_ms = hw_margin; priv->wdd.parent = &pdev->dev; if (watchdog_init_timeout(&priv->wdd, 0, &pdev->dev) < 0) priv->wdd.timeout = SOFT_TIMEOUT_DEF; - setup_timer(&priv->timer, gpio_wdt_hwping, (unsigned long)&priv->wdd); - watchdog_stop_on_reboot(&priv->wdd); - ret = watchdog_register_device(&priv->wdd); - if (ret) - return ret; - if (priv->always_running) - gpio_wdt_start_impl(priv); + gpio_wdt_start(&priv->wdd); - return 0; + ret = watchdog_register_device(&priv->wdd); + + return ret; } static int gpio_wdt_remove(struct platform_device *pdev) { struct gpio_wdt_priv *priv = platform_get_drvdata(pdev); - del_timer_sync(&priv->timer); watchdog_unregister_device(&priv->wdd); return 0; |