提交 4f2d0b2d 编写于 作者: U Uwe Kleine-König 提交者: Wim Van Sebroeck

watchdog: gpio-wdt: ping already at startup for always running devices

During probe for an always-running watchdog a timer is setup to
constantly ping the watchdog while the device is not open. The gpio to
ping the watchdog is setup to inactive.

For a watchdog with hw_algo = "toggle" this results in a ping depending
on the initial state of the gpio, for hw_algo = "level" no ping is
generated.

Make sure that the first automatic ping is sent immediately and not only
when the timer expires the first time. This makes the machine survive in
case more than half of the watchdog timeout is already elapsed. (Which
is very probable for the chip I'm faced with that has a timeout of one
second.)
Signed-off-by: NUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Reviewed-by: NGuenter Roeck <linux@roeck-us.net>
Signed-off-by: NWim Van Sebroeck <wim@iguana.be>
上级 0a0a542f
...@@ -50,12 +50,41 @@ static void gpio_wdt_disable(struct gpio_wdt_priv *priv) ...@@ -50,12 +50,41 @@ static void gpio_wdt_disable(struct gpio_wdt_priv *priv)
gpio_direction_input(priv->gpio); gpio_direction_input(priv->gpio);
} }
static void gpio_wdt_hwping(unsigned long data)
{
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->dev, "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 */
priv->state = !priv->state;
gpio_set_value_cansleep(priv->gpio, priv->state);
break;
case HW_ALGO_LEVEL:
/* Pulse */
gpio_set_value_cansleep(priv->gpio, !priv->active_low);
udelay(1);
gpio_set_value_cansleep(priv->gpio, priv->active_low);
break;
}
}
static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv) static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv)
{ {
priv->state = priv->active_low; priv->state = priv->active_low;
gpio_direction_output(priv->gpio, priv->state); gpio_direction_output(priv->gpio, priv->state);
priv->last_jiffies = jiffies; priv->last_jiffies = jiffies;
mod_timer(&priv->timer, priv->last_jiffies + priv->hw_margin); gpio_wdt_hwping((unsigned long)&priv->wdd);
} }
static int gpio_wdt_start(struct watchdog_device *wdd) static int gpio_wdt_start(struct watchdog_device *wdd)
...@@ -97,35 +126,6 @@ static int gpio_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) ...@@ -97,35 +126,6 @@ static int gpio_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
return gpio_wdt_ping(wdd); return gpio_wdt_ping(wdd);
} }
static void gpio_wdt_hwping(unsigned long data)
{
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->dev, "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 */
priv->state = !priv->state;
gpio_set_value_cansleep(priv->gpio, priv->state);
break;
case HW_ALGO_LEVEL:
/* Pulse */
gpio_set_value_cansleep(priv->gpio, !priv->active_low);
udelay(1);
gpio_set_value_cansleep(priv->gpio, priv->active_low);
break;
}
}
static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code, static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code,
void *unused) void *unused)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册