Skip to content

Commit

Permalink
watchdog: Read device status through sysfs attributes
Browse files Browse the repository at this point in the history
This patch adds following attributes to watchdog device's sysfs interface
to read its different status.

* state - reads whether device is active or not
* identity - reads Watchdog device's identity string.
* timeout - reads current timeout.
* timeleft - reads timeleft before watchdog generates a reset
* bootstatus - reads status of the watchdog device at boot
* status - reads watchdog device's  internal status bits
* nowayout - reads whether nowayout feature was set or not

Testing with iTCO_wdt:
 # cd /sys/class/watchdog/watchdog1/
 # ls
bootstatus  dev  device  identity  nowayout  power  state
subsystem  timeleft  timeout  uevent
 # cat identity
iTCO_wdt
 # cat timeout
30
 # cat state
inactive
 # echo > /dev/watchdog1
 # cat timeleft
26
 # cat state
active
 # cat bootstatus
0
 # cat nowayout
0

Signed-off-by: Pratyush Anand <[email protected]>
Reviewed-by: Guenter Roeck <[email protected]>
Signed-off-by: Guenter Roeck <[email protected]>
Signed-off-by: Wim Van Sebroeck <[email protected]>
  • Loading branch information
Pratyush Anand authored and Wim Van Sebroeck committed Dec 27, 2015
1 parent 906d7a5 commit 33b7112
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 1 deletion.
51 changes: 51 additions & 0 deletions Documentation/ABI/testing/sysfs-class-watchdog
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
What: /sys/class/watchdog/watchdogn/bootstatus
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. It contains status of the watchdog
device at boot. It is equivalent to WDIOC_GETBOOTSTATUS of
ioctl interface.

What: /sys/class/watchdog/watchdogn/identity
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. It contains identity string of
watchdog device.

What: /sys/class/watchdog/watchdogn/nowayout
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. While reading, it gives '1' if that
device supports nowayout feature else, it gives '0'.

What: /sys/class/watchdog/watchdogn/state
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. It gives active/inactive status of
watchdog device.

What: /sys/class/watchdog/watchdogn/status
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. It contains watchdog device's
internal status bits. It is equivalent to WDIOC_GETSTATUS
of ioctl interface.

What: /sys/class/watchdog/watchdogn/timeleft
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. It contains value of time left for
reset generation. It is equivalent to WDIOC_GETTIMELEFT of
ioctl interface.

What: /sys/class/watchdog/watchdogn/timeout
Date: August 2015
Contact: Wim Van Sebroeck <[email protected]>
Description:
It is a read only file. It is read to know about current
value of timeout programmed.
7 changes: 7 additions & 0 deletions drivers/watchdog/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ config WATCHDOG_NOWAYOUT
get killed. If you say Y here, the watchdog cannot be stopped once
it has been started.

config WATCHDOG_SYSFS
bool "Read different watchdog information through sysfs"
default n
help
Say Y here if you want to enable watchdog device status read through
sysfs attributes.

#
# General Watchdog drivers
#
Expand Down
2 changes: 1 addition & 1 deletion drivers/watchdog/watchdog_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd)

devno = wdd->cdev.dev;
wdd->dev = device_create(watchdog_class, wdd->parent, devno,
NULL, "watchdog%d", wdd->id);
wdd, "watchdog%d", wdd->id);
if (IS_ERR(wdd->dev)) {
watchdog_dev_unregister(wdd);
ida_simple_remove(&watchdog_ida, id);
Expand Down
114 changes: 114 additions & 0 deletions drivers/watchdog/watchdog_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,119 @@ static int watchdog_get_timeleft(struct watchdog_device *wdd,
return err;
}

#ifdef CONFIG_WATCHDOG_SYSFS
static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);

return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status));
}
static DEVICE_ATTR_RO(nowayout);

static ssize_t status_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);
ssize_t status;
unsigned int val;

status = watchdog_get_status(wdd, &val);
if (!status)
status = sprintf(buf, "%u\n", val);

return status;
}
static DEVICE_ATTR_RO(status);

static ssize_t bootstatus_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);

return sprintf(buf, "%u\n", wdd->bootstatus);
}
static DEVICE_ATTR_RO(bootstatus);

static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);
ssize_t status;
unsigned int val;

status = watchdog_get_timeleft(wdd, &val);
if (!status)
status = sprintf(buf, "%u\n", val);

return status;
}
static DEVICE_ATTR_RO(timeleft);

static ssize_t timeout_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);

return sprintf(buf, "%u\n", wdd->timeout);
}
static DEVICE_ATTR_RO(timeout);

static ssize_t identity_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);

return sprintf(buf, "%s\n", wdd->info->identity);
}
static DEVICE_ATTR_RO(identity);

static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);

if (watchdog_active(wdd))
return sprintf(buf, "active\n");

return sprintf(buf, "inactive\n");
}
static DEVICE_ATTR_RO(state);

static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
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)
mode = 0;

return mode;
}
static struct attribute *wdt_attrs[] = {
&dev_attr_state.attr,
&dev_attr_identity.attr,
&dev_attr_timeout.attr,
&dev_attr_timeleft.attr,
&dev_attr_bootstatus.attr,
&dev_attr_status.attr,
&dev_attr_nowayout.attr,
NULL,
};

static const struct attribute_group wdt_group = {
.attrs = wdt_attrs,
.is_visible = wdt_is_visible,
};
__ATTRIBUTE_GROUPS(wdt);
#else
#define wdt_groups NULL
#endif

/*
* watchdog_ioctl_op: call the watchdog drivers ioctl op if defined
* @wdd: the watchdog device to do the ioctl on
Expand Down Expand Up @@ -584,6 +697,7 @@ int watchdog_dev_unregister(struct watchdog_device *wdd)
static struct class watchdog_class = {
.name = "watchdog",
.owner = THIS_MODULE,
.dev_groups = wdt_groups,
};

/*
Expand Down

0 comments on commit 33b7112

Please sign in to comment.