Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33b71126 authored by Pratyush Anand's avatar Pratyush Anand Committed by Wim Van Sebroeck
Browse files

watchdog: Read device status through sysfs attributes



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: default avatarPratyush Anand <panand@redhat.com>
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
parent 906d7a5c
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
What:		/sys/class/watchdog/watchdogn/bootstatus
Date:		August 2015
Contact:	Wim Van Sebroeck <wim@iguana.be>
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 <wim@iguana.be>
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 <wim@iguana.be>
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 <wim@iguana.be>
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 <wim@iguana.be>
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 <wim@iguana.be>
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 <wim@iguana.be>
Description:
		It is a read only file. It is read to know about current
		value of timeout programmed.
+7 −0
Original line number Diff line number Diff line
@@ -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
#
+1 −1
Original line number Diff line number Diff line
@@ -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);
+114 −0
Original line number Diff line number Diff line
@@ -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
@@ -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,
};

/*