diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a50d82dc33e74af3378d7d58126a250f11faf749..d5b1aec5cc127fab07fab3e8a47f692b8afa294a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1370,6 +1370,16 @@ config ASCEND_CHARGE_MIGRATE_HUGEPAGES This option enable the feature to charge migrate hugepages to memory cgroup. +config ASCEND_WATCHDOG_SYSFS_CONFIGURE + bool "Configure watchdog timeout and pretimeout via sysfs" + depends on WATCHDOG_SYSFS + help + Add interface for user to configure timeout and pretimeout through + sysfs. Enable this config carefully since a user could change the + timeout value without notifying the userspace process that pings the + watchdog. The kernel thread could be notified so it's ok to make that + change when the watchdog is pinged by kernel thread. + endif endmenu diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 10b2090f3e5e751eb7392fc39dc2e8c1eb82fa7b..6c7c5f4abeae08934c5373592552d9b4ef0ec6a8 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -485,7 +485,41 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", wdd->timeout); } + +#ifdef CONFIG_ASCEND_WATCHDOG_SYSFS_CONFIGURE +static int sysfs_write; +module_param(sysfs_write, int, 0); +MODULE_PARM_DESC(sysfs_write, + "enable configuring timeout and pretimeout via sysfs"); + +static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct watchdog_core_data *wd_data = wdd->wd_data; + + if (!sysfs_write) + return -EOPNOTSUPP; + + ret = kstrtouint(buf, 0, &val); + if (ret) + return ret; + + mutex_lock(&wd_data->lock); + ret = watchdog_set_timeout(wdd, val); + mutex_unlock(&wd_data->lock); + + if (!ret) + ret = count; + + return ret; +} +static DEVICE_ATTR_RW(timeout); +#else static DEVICE_ATTR_RO(timeout); +#endif static ssize_t pretimeout_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -494,7 +528,36 @@ static ssize_t pretimeout_show(struct device *dev, return sprintf(buf, "%u\n", wdd->pretimeout); } + +#ifdef CONFIG_ASCEND_WATCHDOG_SYSFS_CONFIGURE +static ssize_t pretimeout_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + struct watchdog_device *wdd = dev_get_drvdata(dev); + struct watchdog_core_data *wd_data = wdd->wd_data; + + if (!sysfs_write) + return -EOPNOTSUPP; + + ret = kstrtouint(buf, 0, &val); + if (ret) + return ret; + + mutex_lock(&wd_data->lock); + ret = watchdog_set_pretimeout(wdd, val); + mutex_unlock(&wd_data->lock); + + if (!ret) + ret = count; + + return ret; +} +static DEVICE_ATTR_RW(pretimeout); +#else static DEVICE_ATTR_RO(pretimeout); +#endif static ssize_t identity_show(struct device *dev, struct device_attribute *attr, char *buf)