[PATCH linux dev-4.10] drivers/watchdog: Add user space access to aspeed ext signal and reset

Andrew Jeffery andrew at aj.id.au
Wed May 24 08:49:13 AEST 2017


On Tue, 2017-05-23 at 16:28 -0500, Christopher Bostic wrote:
> Add sysfs files for 'ext signal' mode and 'system reset' mode within
> the aspeed watchdog device driver for wdt1 and wdt2

This commit message explains what the patch does, not why we need it.
The code change already describes what it does, so can you please
instead outline in the commit message what the motivation is (or
potential motivations are). Ultimately what I'm interested in is
whether this should be a platform design decision (and so should be
managed via devicetree), or userspace policy, which is what we have
here.

Separately, given it's fairly generic and assuming the motivation is
reasonable, I'd suggest also sending it upstream.

Andrew

> 
> > Signed-off-by: Christopher Bostic <cbostic at linux.vnet.ibm.com>
> ---
>  .../ABI/testing/sysfs-platform-aspeed-wdt          | 40 ++++++++++
>  drivers/watchdog/aspeed_wdt.c                      | 89 +++++++++++++++++++++-
>  2 files changed, 128 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-platform-aspeed-wdt
> 
> diff --git a/Documentation/ABI/testing/sysfs-platform-aspeed-wdt b/Documentation/ABI/testing/sysfs-platform-aspeed-wdt
> new file mode 100644
> index 0000000..a582176
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-platform-aspeed-wdt
> @@ -0,0 +1,40 @@
> +What:           /sys/bus/platform/devices/1e785000.wdt/watchdog/watchdog0/
> > +		reset_system
> +Date:           May 2017
> +KernelVersion:  4.12
> > +Contact:        Christopher Bostic <cbostic at linux.vnet.ibm.com>
> +Description:
> +                Value indicates if a watchdog time out results in a reset of
> > +		system.  'off': no system reset on timeout.  'on' there will
> > +		be a system reset on timeout.
> +
> +                Default: off
> +
> +                - Enable 'reset system' on watchdog timeout:
> +                echo on > /sys/bus/platform/devices/1e785000.wdt/watchdog/
> > +			watchdog0/reset_system;
> +
> +                - Disable 'reset system' on watchdog timeout:
> +                echo off > /sys/bus/platform/devices/1e785000.wdt/watchdog/
> > +			watchdog0/reset_system;
> +
> +What:           /sys/bus/platform/devices/1e785000.wdt/watchdog/watchdog0/
> > +		ext_signal
> +Date:           May 2017
> +KernelVersion:  4.12
> > +Contact:        Christopher Bostic <cbostic at linux.vnet.ibm.com>
> +Description:
> +                Value indicates if a watchdog time out results in an active
> > +		high pulse sent out an output pin.  'off': No output pulse
> > +		generated on watchdog time out.  'on': output pulse
> > +		generated on watchdog time out.
> +
> +                Default: off
> +
> +                - Enable 'external signal' on watchdog timeout:
> +                echo on > /sys/bus/platform/devices/1e785000.wdt/watchdog/
> > +			watchdog0/ext_signal;
> +
> +                - Disable 'external signal' on watchdog timeout:
> +                echo off > /sys/bus/platform/devices/1e785000.wdt/watchdog/
> > +			watchdog0/ext_signal;
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> index f5ad802..277948b 100644
> --- a/drivers/watchdog/aspeed_wdt.c
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -145,6 +145,93 @@ static int aspeed_wdt_remove(struct platform_device *pdev)
> >  	return 0;
>  }
>  
> +static ssize_t aspeed_wdt_reset_system_store(struct device *dev,
> > +					     struct device_attribute *attr,
> > +					     const char *buf, size_t count)
> +{
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> +
> > +	if (!strncmp(buf, "on", strlen("on"))) {
> > +		wdt->ctrl |= WDT_CTRL_RESET_SYSTEM;
> > +		writel(wdt->ctrl, wdt->base + WDT_CTRL);
> > +	} else if (!strncmp(buf, "off", strlen("off"))) {
> > +		wdt->ctrl &= ~WDT_CTRL_RESET_SYSTEM;
> > +		writel(wdt->ctrl, wdt->base + WDT_CTRL);
> > +	} else {
> > +		dev_warn(dev, "Unknown reset system mode command: [%s]\n", buf);
> > +		return -EINVAL;
> > +	}
> +
> > +	return count;
> +}
> +
> +static ssize_t aspeed_wdt_reset_system_show(struct device *dev,
> > +					    struct device_attribute *attr,
> > +					    char *buf)
> +{
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> > +	int ret;
> +
> > +	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_RESET_SYSTEM)
> > +		ret = sprintf(buf, "on\n");
> > +	else
> > +		ret = sprintf(buf, "off\n");
> +
> > +	return ret;
> +}
> +
> +static DEVICE_ATTR(reset_system, 0644,
> > +		   aspeed_wdt_reset_system_show, aspeed_wdt_reset_system_store);
> +
> +static ssize_t aspeed_wdt_ext_signal_store(struct device *dev,
> > +					   struct device_attribute *attr,
> > +					   const char *buf, size_t count)
> +{
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> +
> > +	if (!strncmp(buf, "on", strlen("on"))) {
> > +		wdt->ctrl |= WDT_CTRL_WDT_EXT;
> > +		writel(wdt->ctrl, wdt->base + WDT_CTRL);
> > +	} else if (!strncmp(buf, "off", strlen("off"))) {
> > +		wdt->ctrl &= ~WDT_CTRL_WDT_EXT;
> > +		writel(wdt->ctrl, wdt->base + WDT_CTRL);
> > +	} else {
> > +		dev_warn(dev, "Unknown reset system mode command: %s\n", buf);
> > +		return -EINVAL;
> > +	}
> +
> > +	return count;
> +}
> +
> +static ssize_t aspeed_wdt_ext_signal_show(struct device *dev,
> > +					  struct device_attribute *attr,
> > +					  char *buf)
> +{
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> > +	int ret;
> +
> > +	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_WDT_EXT)
> > +		ret = sprintf(buf, "on\n");
> > +	else
> > +		ret = sprintf(buf, "off\n");
> +
> > +	return ret;
> +}
> +
> +static DEVICE_ATTR(ext_signal, 0644,
> +		   aspeed_wdt_ext_signal_show, aspeed_wdt_ext_signal_store);

The on/off implementations for show/store callbacks are very similar,
only differentiated by the bit that we're flipping. We could almost cut
the code in half by parameterising a function with the bit of interest
and invoking it appropriately in the callback handlers. Thoughts?

Andrew

> +
> +static struct attribute *aspeed_wdt_attrs[] = {
> > +	&dev_attr_reset_system.attr,
> > +	&dev_attr_ext_signal.attr,
> > +	NULL
> +};
> +ATTRIBUTE_GROUPS(aspeed_wdt);
> +
>  static int aspeed_wdt_probe(struct platform_device *pdev)
>  {
> >  	struct aspeed_wdt *wdt;
> @@ -169,7 +256,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
> >  	wdt->wdd.ops = &aspeed_wdt_ops;
> >  	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
> >  	wdt->wdd.parent = &pdev->dev;
> -
> > +	wdt->wdd.groups = aspeed_wdt_groups;
> >  	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
> >  	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
>  
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/openbmc/attachments/20170524/ec971d17/attachment-0001.sig>


More information about the openbmc mailing list