|
@@ -69,6 +69,7 @@ struct watchdog_core_data {
|
|
|
unsigned long status; /* Internal status bits */
|
|
|
#define _WDOG_DEV_OPEN 0 /* Opened ? */
|
|
|
#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */
|
|
|
+#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */
|
|
|
};
|
|
|
|
|
|
/* the dev_t structure to store the dynamically allocated watchdog devices */
|
|
@@ -184,6 +185,8 @@ static int watchdog_ping(struct watchdog_device *wdd)
|
|
|
if (!watchdog_active(wdd) && !watchdog_hw_running(wdd))
|
|
|
return 0;
|
|
|
|
|
|
+ set_bit(_WDOG_KEEPALIVE, &wd_data->status);
|
|
|
+
|
|
|
wd_data->last_keepalive = jiffies;
|
|
|
return __watchdog_ping(wdd);
|
|
|
}
|
|
@@ -223,6 +226,8 @@ static int watchdog_start(struct watchdog_device *wdd)
|
|
|
if (watchdog_active(wdd))
|
|
|
return 0;
|
|
|
|
|
|
+ set_bit(_WDOG_KEEPALIVE, &wd_data->status);
|
|
|
+
|
|
|
started_at = jiffies;
|
|
|
if (watchdog_hw_running(wdd) && wdd->ops->ping)
|
|
|
err = wdd->ops->ping(wdd);
|
|
@@ -286,10 +291,27 @@ static int watchdog_stop(struct watchdog_device *wdd)
|
|
|
|
|
|
static unsigned int watchdog_get_status(struct watchdog_device *wdd)
|
|
|
{
|
|
|
- if (!wdd->ops->status)
|
|
|
- return 0;
|
|
|
+ struct watchdog_core_data *wd_data = wdd->wd_data;
|
|
|
+ unsigned int status;
|
|
|
|
|
|
- return wdd->ops->status(wdd);
|
|
|
+ if (wdd->ops->status)
|
|
|
+ status = wdd->ops->status(wdd);
|
|
|
+ else
|
|
|
+ status = wdd->bootstatus & (WDIOF_CARDRESET |
|
|
|
+ WDIOF_OVERHEAT |
|
|
|
+ WDIOF_FANFAULT |
|
|
|
+ WDIOF_EXTERN1 |
|
|
|
+ WDIOF_EXTERN2 |
|
|
|
+ WDIOF_POWERUNDER |
|
|
|
+ WDIOF_POWEROVER);
|
|
|
+
|
|
|
+ if (test_bit(_WDOG_ALLOW_RELEASE, &wd_data->status))
|
|
|
+ status |= WDIOF_MAGICCLOSE;
|
|
|
+
|
|
|
+ if (test_and_clear_bit(_WDOG_KEEPALIVE, &wd_data->status))
|
|
|
+ status |= WDIOF_KEEPALIVEPING;
|
|
|
+
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -365,7 +387,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
|
|
|
status = watchdog_get_status(wdd);
|
|
|
mutex_unlock(&wd_data->lock);
|
|
|
|
|
|
- return sprintf(buf, "%u\n", status);
|
|
|
+ return sprintf(buf, "0x%x\n", status);
|
|
|
}
|
|
|
static DEVICE_ATTR_RO(status);
|
|
|
|
|
@@ -433,9 +455,7 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
|
|
|
struct watchdog_device *wdd = dev_get_drvdata(dev);
|
|
|
umode_t mode = attr->mode;
|
|
|
|
|
|
- if (attr == &dev_attr_status.attr && !wdd->ops->status)
|
|
|
- mode = 0;
|
|
|
- else if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft)
|
|
|
+ if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft)
|
|
|
mode = 0;
|
|
|
|
|
|
return mode;
|