aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2015-07-31 03:21:36 -0400
committerWim Van Sebroeck <wim@iguana.be>2015-09-09 15:35:37 -0400
commit4f2d0b2d1b31cbe704c8f94e74e46cb64187ab0c (patch)
tree30a9e56910f1f654f0ef240ca0d771c7067e9203
parent0a0a542f6bbb2ebe956f0117c842302442ef52da (diff)
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: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r--drivers/watchdog/gpio_wdt.c60
1 files changed, 30 insertions, 30 deletions
diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c
index 57d30f1f55ab..5e16b0983e2a 100644
--- a/drivers/watchdog/gpio_wdt.c
+++ b/drivers/watchdog/gpio_wdt.c
@@ -50,12 +50,41 @@ static void gpio_wdt_disable(struct gpio_wdt_priv *priv)
50 gpio_direction_input(priv->gpio); 50 gpio_direction_input(priv->gpio);
51} 51}
52 52
53static void gpio_wdt_hwping(unsigned long data)
54{
55 struct watchdog_device *wdd = (struct watchdog_device *)data;
56 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd);
57
58 if (priv->armed && time_after(jiffies, priv->last_jiffies +
59 msecs_to_jiffies(wdd->timeout * 1000))) {
60 dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n");
61 return;
62 }
63
64 /* Restart timer */
65 mod_timer(&priv->timer, jiffies + priv->hw_margin);
66
67 switch (priv->hw_algo) {
68 case HW_ALGO_TOGGLE:
69 /* Toggle output pin */
70 priv->state = !priv->state;
71 gpio_set_value_cansleep(priv->gpio, priv->state);
72 break;
73 case HW_ALGO_LEVEL:
74 /* Pulse */
75 gpio_set_value_cansleep(priv->gpio, !priv->active_low);
76 udelay(1);
77 gpio_set_value_cansleep(priv->gpio, priv->active_low);
78 break;
79 }
80}
81
53static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv) 82static void gpio_wdt_start_impl(struct gpio_wdt_priv *priv)
54{ 83{
55 priv->state = priv->active_low; 84 priv->state = priv->active_low;
56 gpio_direction_output(priv->gpio, priv->state); 85 gpio_direction_output(priv->gpio, priv->state);
57 priv->last_jiffies = jiffies; 86 priv->last_jiffies = jiffies;
58 mod_timer(&priv->timer, priv->last_jiffies + priv->hw_margin); 87 gpio_wdt_hwping((unsigned long)&priv->wdd);
59} 88}
60 89
61static int gpio_wdt_start(struct watchdog_device *wdd) 90static 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 return gpio_wdt_ping(wdd); 126 return gpio_wdt_ping(wdd);
98} 127}
99 128
100static void gpio_wdt_hwping(unsigned long data)
101{
102 struct watchdog_device *wdd = (struct watchdog_device *)data;
103 struct gpio_wdt_priv *priv = watchdog_get_drvdata(wdd);
104
105 if (priv->armed && time_after(jiffies, priv->last_jiffies +
106 msecs_to_jiffies(wdd->timeout * 1000))) {
107 dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n");
108 return;
109 }
110
111 /* Restart timer */
112 mod_timer(&priv->timer, jiffies + priv->hw_margin);
113
114 switch (priv->hw_algo) {
115 case HW_ALGO_TOGGLE:
116 /* Toggle output pin */
117 priv->state = !priv->state;
118 gpio_set_value_cansleep(priv->gpio, priv->state);
119 break;
120 case HW_ALGO_LEVEL:
121 /* Pulse */
122 gpio_set_value_cansleep(priv->gpio, !priv->active_low);
123 udelay(1);
124 gpio_set_value_cansleep(priv->gpio, priv->active_low);
125 break;
126 }
127}
128
129static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code, 129static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code,
130 void *unused) 130 void *unused)
131{ 131{