diff options
author | Pratyush Anand <panand@redhat.com> | 2015-12-17 15:23:59 +0300 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2015-12-27 18:55:57 +0300 |
commit | 33b711269ade3f6bc9d9d15e4343e6fa922d999b (patch) | |
tree | 24858dcb710a0dbcd3c992e136c5dc3ca8a5e744 /drivers/watchdog | |
parent | 906d7a5cfeda508e7361f021605579a00cd82815 (diff) | |
download | linux-33b711269ade3f6bc9d9d15e4343e6fa922d999b.tar.xz |
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: Pratyush Anand <panand@redhat.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 7 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_core.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/watchdog_dev.c | 114 |
3 files changed, 122 insertions, 1 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1c427beffadd..71e47dde7d4a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -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 # diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 357d23c79545..551af042867c 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -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); diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 055a4e1b4c13..f06fbcf0bea2 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -247,6 +247,119 @@ out_timeleft: 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, }; /* |