aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/watchdog_dev.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-07-17 18:04:11 -0400
committerWim Van Sebroeck <wim@iguana.be>2016-07-19 04:09:07 -0400
commit90b826f17a4e1c4ff2b3ef69512a6409e94f4d64 (patch)
tree8eb26b2dd367a2d7ec258ebadbbd989cfab8245c /drivers/watchdog/watchdog_dev.c
parentc7ef68c32265a396a4d977f896a11a4cebb0ace4 (diff)
watchdog: Implement status function in watchdog core
Up to now, the watchdog status function called a driver function, which was supposed to return the watchdog status. All but one driver using the watchdog core did not implement this function, and the driver implementing it did not implement it correctly (the function is supposed to return WDIOF_ flags). At the same time, at least some of the status information can be provided by the watchdog core. Provide the available status bits directly from the watchdog driver core. Call the driver status function if it exists to get the boot status, but always provide WDIOF_MAGICCLOSE and WDIOF_KEEPALIVEPING internally. This patch makes the 'status' sysfs attribute always available. This attribute is now displayed as hex number with 0x prepended to be easier to decode. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog/watchdog_dev.c')
-rw-r--r--drivers/watchdog/watchdog_dev.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 14f8a92fca12..270f4bf291e3 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -69,6 +69,7 @@ struct watchdog_core_data {
69 unsigned long status; /* Internal status bits */ 69 unsigned long status; /* Internal status bits */
70#define _WDOG_DEV_OPEN 0 /* Opened ? */ 70#define _WDOG_DEV_OPEN 0 /* Opened ? */
71#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ 71#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */
72#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */
72}; 73};
73 74
74/* the dev_t structure to store the dynamically allocated watchdog devices */ 75/* the dev_t structure to store the dynamically allocated watchdog devices */
@@ -184,6 +185,8 @@ static int watchdog_ping(struct watchdog_device *wdd)
184 if (!watchdog_active(wdd) && !watchdog_hw_running(wdd)) 185 if (!watchdog_active(wdd) && !watchdog_hw_running(wdd))
185 return 0; 186 return 0;
186 187
188 set_bit(_WDOG_KEEPALIVE, &wd_data->status);
189
187 wd_data->last_keepalive = jiffies; 190 wd_data->last_keepalive = jiffies;
188 return __watchdog_ping(wdd); 191 return __watchdog_ping(wdd);
189} 192}
@@ -223,6 +226,8 @@ static int watchdog_start(struct watchdog_device *wdd)
223 if (watchdog_active(wdd)) 226 if (watchdog_active(wdd))
224 return 0; 227 return 0;
225 228
229 set_bit(_WDOG_KEEPALIVE, &wd_data->status);
230
226 started_at = jiffies; 231 started_at = jiffies;
227 if (watchdog_hw_running(wdd) && wdd->ops->ping) 232 if (watchdog_hw_running(wdd) && wdd->ops->ping)
228 err = wdd->ops->ping(wdd); 233 err = wdd->ops->ping(wdd);
@@ -286,10 +291,27 @@ static int watchdog_stop(struct watchdog_device *wdd)
286 291
287static unsigned int watchdog_get_status(struct watchdog_device *wdd) 292static unsigned int watchdog_get_status(struct watchdog_device *wdd)
288{ 293{
289 if (!wdd->ops->status) 294 struct watchdog_core_data *wd_data = wdd->wd_data;
290 return 0; 295 unsigned int status;
291 296
292 return wdd->ops->status(wdd); 297 if (wdd->ops->status)
298 status = wdd->ops->status(wdd);
299 else
300 status = wdd->bootstatus & (WDIOF_CARDRESET |
301 WDIOF_OVERHEAT |
302 WDIOF_FANFAULT |
303 WDIOF_EXTERN1 |
304 WDIOF_EXTERN2 |
305 WDIOF_POWERUNDER |
306 WDIOF_POWEROVER);
307
308 if (test_bit(_WDOG_ALLOW_RELEASE, &wd_data->status))
309 status |= WDIOF_MAGICCLOSE;
310
311 if (test_and_clear_bit(_WDOG_KEEPALIVE, &wd_data->status))
312 status |= WDIOF_KEEPALIVEPING;
313
314 return status;
293} 315}
294 316
295/* 317/*
@@ -365,7 +387,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
365 status = watchdog_get_status(wdd); 387 status = watchdog_get_status(wdd);
366 mutex_unlock(&wd_data->lock); 388 mutex_unlock(&wd_data->lock);
367 389
368 return sprintf(buf, "%u\n", status); 390 return sprintf(buf, "0x%x\n", status);
369} 391}
370static DEVICE_ATTR_RO(status); 392static DEVICE_ATTR_RO(status);
371 393
@@ -433,9 +455,7 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
433 struct watchdog_device *wdd = dev_get_drvdata(dev); 455 struct watchdog_device *wdd = dev_get_drvdata(dev);
434 umode_t mode = attr->mode; 456 umode_t mode = attr->mode;
435 457
436 if (attr == &dev_attr_status.attr && !wdd->ops->status) 458 if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft)
437 mode = 0;
438 else if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft)
439 mode = 0; 459 mode = 0;
440 460
441 return mode; 461 return mode;