All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Campion Kang <campion.kang@advantech.com.tw>
Cc: Lee Jones <lee.jones@linaro.org>,
	Rob Herring <robh+dt@kernel.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Mark Gross <mgross@linux.intel.com>,
	Wim Van Sebroeck <wim@linux-watchdog.org>,
	Jean Delvare <jdelvare@suse.com>,
	Jonathan Corbet <corbet@lwn.net>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-watchdog@vger.kernel.org, linux-hwmon@vger.kernel.org,
	linux-doc@vger.kernel.org, platform-driver-x86@vger.kernel.org,
	AceLan Kao <chia-lin.kao@canonical.com>
Subject: Re: [PATCH v7 6/7] Watchdog: ahc1ec0-wdt: Add sub-device Watchdog for Advantech embedded controller
Date: Thu, 6 May 2021 06:17:34 -0700	[thread overview]
Message-ID: <20210506131734.GB2252703@roeck-us.net> (raw)
In-Reply-To: <20210506081619.2443-6-campion.kang@advantech.com.tw>

On Thu, May 06, 2021 at 04:16:18PM +0800, Campion Kang wrote:
> This is one of sub-device driver for Advantech embedded controller
> AHC1EC0. This driver provide Watchdog functionality for Advantech
> related applications to restart the system.
> 
> Changed in V7:
> 	Fix the patch according to reviewer's comment:
> 	- remove unnecessary variables and fix error checks
> 	- remove error messages that avoid clogging the kernel log
> 	- remove advwdt_notify_sys(), use watchdog subsystem to process
> 	  reboot or shutdown
> 	- delete mutex lock, the watchdog core has processed it
> 
> Changed in V6:
> 	- remove unnecessary header files
> 	- bug fixed: reboot halt if watchdog enabled
> 	- Kconfig: add "AHC1EC0" string to clearly define the EC name
> 
> Signed-off-by: Campion Kang <campion.kang@advantech.com.tw>
> ---
>  drivers/watchdog/Kconfig       |  11 +++
>  drivers/watchdog/Makefile      |   1 +
>  drivers/watchdog/ahc1ec0-wdt.c | 171 +++++++++++++++++++++++++++++++++
>  3 files changed, 183 insertions(+)
>  create mode 100644 drivers/watchdog/ahc1ec0-wdt.c
> 
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 355100dad60a..5fe9add0a12d 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -1005,6 +1005,17 @@ config ADVANTECH_WDT
>  	  feature. More information can be found at
>  	  <https://www.advantech.com.tw/products/>
>  
> +config AHC1EC0_WDT
> +	tristate "Advantech AHC1EC0 Watchdog Function"
> +	depends on MFD_AHC1EC0
> +	help
> +	  This is sub-device for Advantech AHC1EC0 embedded controller.
> +
> +	  This driver provide watchdog functionality for Advantech related
> +	  applications to restart the system.
> +	  To compile this driver as a module, choose M here: the module will be
> +	  called ahc1ec0-wdt.
> +
>  config ALIM1535_WDT
>  	tristate "ALi M1535 PMU Watchdog Timer"
>  	depends on X86 && PCI
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index a7eade8b4d45..0d78211e1412 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -142,6 +142,7 @@ obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o
>  obj-$(CONFIG_NIC7018_WDT) += nic7018_wdt.o
>  obj-$(CONFIG_MLX_WDT) += mlx_wdt.o
>  obj-$(CONFIG_KEEMBAY_WATCHDOG) += keembay_wdt.o
> +obj-$(CONFIG_AHC1EC0_WDT) += ahc1ec0-wdt.o
>  
>  # M68K Architecture
>  obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o
> diff --git a/drivers/watchdog/ahc1ec0-wdt.c b/drivers/watchdog/ahc1ec0-wdt.c
> new file mode 100644
> index 000000000000..efa955c41a81
> --- /dev/null
> +++ b/drivers/watchdog/ahc1ec0-wdt.c
> @@ -0,0 +1,171 @@
> +// SPDX-License-Identifier: GPL-2.0-only

GPL or GPLv2 ?

> +/*
> + * Watchdog Driver for Advantech AHC1EC0 Embedded Controller
> + *
> + * Copyright 2021, Advantech IIoT Group
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/notifier.h>

Unnecessary.

> +#include <linux/platform_data/ahc1ec0.h>
> +#include <linux/platform_device.h>
> +#include <linux/reboot.h>

Unnecessary.

> +#include <linux/types.h>
> +#include <linux/watchdog.h>
> +
> +struct ec_wdt_data {
> +	struct watchdog_device wdtdev;
> +	struct adv_ec_ddata *ddata;
> +	unsigned short timeout_in_ds; /* a decisecond */

This variable is unnecessary.

> +};
> +
> +#define EC_WDT_MIN_TIMEOUT	1   /* The watchdog devices minimum timeout value (in seconds). */
> +#define EC_WDT_MAX_TIMEOUT	600 /* The watchdog devices maximum timeout value (in seconds) */

Please use constant alignment, and "The watchdog devices " is really
unnecessary.

> +#define EC_WDT_DEFAULT_TIMEOUT	45
> +
> +static int set_delay(struct adv_ec_ddata *ddata, unsigned short delay_timeout_in_ms)
> +{
> +	if (ahc1ec_write_hw_ram(ddata, EC_RESET_DELAY_TIME_L,
> +				delay_timeout_in_ms & 0x00FF))
> +		return -EINVAL;
> +
> +	if (ahc1ec_write_hw_ram(ddata, EC_RESET_DELAY_TIME_H,
> +				(delay_timeout_in_ms & 0xFF00) >> 8))

Those functions presumably return a valid error code which should be passed
on and not replaced.

> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int ec_wdt_start(struct watchdog_device *wdd)
> +{
> +	int ret;
> +	struct ec_wdt_data *ec_wdt_data = watchdog_get_drvdata(wdd);
> +	struct adv_ec_ddata *ddata;
> +
> +	ddata = ec_wdt_data->ddata;
> +

Might as well be written as
	struct adv_ec_ddata *ddata = ec_wdt_data->ddata;

> +	/*
> +	 * Because an unit of ahc1ec0_wdt is 0.1 seconds, timeout 100 is 10 seconds
> +	 */
> +	ec_wdt_data->timeout_in_ds = wdd->timeout * 10;

timeout_in_ds can be a local variable (if not omitted entirely).

> +
> +	ret = set_delay(ddata, (ec_wdt_data->timeout_in_ds - 1));

Unnecessary ( ) around second parameter.

> +	if (ret)
> +		goto exit;

	if (ret)
		return ret;

> +
> +	ahc1ec_write_hwram_command(ddata, EC_WDT_STOP);
> +	ret = ahc1ec_write_hwram_command(ddata, EC_WDT_START);
> +	if (ret)
> +		goto exit;

Unnecessary.

> +
> +exit:

Unnecessary label.

> +	return ret;
> +}
> +
> +static int ec_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct ec_wdt_data *ec_wdt_data = watchdog_get_drvdata(wdd);
> +	struct adv_ec_ddata *ddata;
> +
> +	ddata = ec_wdt_data->ddata;
> +
> +	return ahc1ec_write_hwram_command(ddata, EC_WDT_STOP);
> +}
> +
> +static int ec_wdt_ping(struct watchdog_device *wdd)
> +{
> +	int ret;
> +	struct ec_wdt_data *ec_wdt_data = watchdog_get_drvdata(wdd);
> +	struct adv_ec_ddata *ddata;
> +
> +	ddata = ec_wdt_data->ddata;
> +
> +	ret = ahc1ec_write_hwram_command(ddata, EC_WDT_RESET);
> +	if (ret)
> +		return -EINVAL;

	return ret;

but then above you have
	return ahc1ec_write_hwram_command(ddata, EC_WDT_STOP);

Please be consistent.

> +
> +	return 0;
> +}
> +
> +static int ec_wdt_set_timeout(struct watchdog_device *wdd,
> +			      unsigned int timeout)
> +{
> +	wdd->timeout = timeout;
> +
> +	if (watchdog_active(wdd))
> +		return ec_wdt_start(wdd);
> +
> +	return 0;
> +}
> +
> +static const struct watchdog_info ec_watchdog_info = {
> +	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> +	.identity = "AHC1EC0 Watchdog",
> +};
> +
> +static const struct watchdog_ops ec_watchdog_ops = {
> +	.owner = THIS_MODULE,
> +	.start = ec_wdt_start,
> +	.stop = ec_wdt_stop,
> +	.ping = ec_wdt_ping,
> +	.set_timeout = ec_wdt_set_timeout,
> +};
> +
> +static int adv_ec_wdt_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct device *dev = &pdev->dev;
> +	struct adv_ec_ddata *ddata;
> +	struct ec_wdt_data *ec_wdt_data;
> +	struct watchdog_device *wdd;
> +
> +	ddata = dev_get_drvdata(dev->parent);
> +	if (!ddata)
> +		return -EINVAL;
> +
> +	ec_wdt_data = devm_kzalloc(dev, sizeof(*ec_wdt_data), GFP_KERNEL);
> +	if (!ec_wdt_data)
> +		return -ENOMEM;
> +
> +	ec_wdt_data->ddata = ddata;
> +	wdd = &ec_wdt_data->wdtdev;
> +
> +	watchdog_init_timeout(&ec_wdt_data->wdtdev, 0, dev);
> +

This should be after wdd->timeout is set, and please use wdd.

> +	/* watchdog_set_nowayout(&ec_wdt_data->wdtdev, WATCHDOG_NOWAYOUT); */
> +	watchdog_set_drvdata(&ec_wdt_data->wdtdev, ec_wdt_data);

Please use wdd.

> +	platform_set_drvdata(pdev, ec_wdt_data);

Is this used anywhere ?

> +
> +	wdd->info = &ec_watchdog_info;
> +	wdd->ops = &ec_watchdog_ops;
> +	wdd->min_timeout = EC_WDT_MIN_TIMEOUT;
> +	wdd->max_timeout = EC_WDT_MAX_TIMEOUT;
> +	wdd->parent = dev;
> +
> +	ec_wdt_data->wdtdev.timeout = EC_WDT_DEFAULT_TIMEOUT;

	wdd->timeout = EC_WDT_DEFAULT_TIMEOUT;

> +
> +	watchdog_stop_on_reboot(wdd);
> +	watchdog_stop_on_unregister(wdd);
> +
> +	ret = devm_watchdog_register_device(dev, wdd);
> +	if (ret == 0)
> +		dev_info(dev, "ahc1ec0 watchdog register success\n");

This is noise.

> +
> +	return ret;
> +}
> +
> +static struct platform_driver adv_wdt_drv = {
> +	.driver = {
> +		.name = "ahc1ec0-wdt",
> +	},
> +	.probe = adv_ec_wdt_probe,
> +};
> +module_platform_driver(adv_wdt_drv);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:ahc1ec0-wdt");
> +MODULE_DESCRIPTION("Advantech Embedded Controller Watchdog Driver.");
> +MODULE_AUTHOR("Campion Kang <campion.kang@advantech.com.tw>");
> +MODULE_VERSION("1.0");
> -- 
> 2.17.1
> 

  reply	other threads:[~2021-05-06 13:17 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-06  8:16 [PATCH v7 1/7] MAINTAINERS: Add Advantech AHC1EC0 embedded controller entry Campion Kang
2021-05-06  8:16 ` [PATCH v7 2/7] mfd: ahc1ec0: Add Advantech EC include file used by dt-bindings Campion Kang
2021-05-06  8:16 ` [PATCH v7 3/7] dt-bindings: mfd: ahc1ec0.yaml: Add Advantech embedded controller - AHC1EC0 Campion Kang
2021-05-06  8:16 ` [PATCH v7 4/7] platform: x86: ahc1ec0-core: Add support for Advantech embedded controller Campion Kang
2021-05-06  8:16 ` [PATCH v7 5/7] mfd: ahc1ec0: " Campion Kang
2021-05-06  8:16 ` [PATCH v7 6/7] Watchdog: ahc1ec0-wdt: Add sub-device Watchdog " Campion Kang
2021-05-06 13:17   ` Guenter Roeck [this message]
2021-05-06  8:16 ` [PATCH v7 7/7] hwmon: ahc1ec0-hwmon: Add sub-device HWMON " Campion Kang
2021-05-06 13:04   ` Guenter Roeck
2021-05-06  8:47 ` [PATCH v7 1/7] MAINTAINERS: Add Advantech AHC1EC0 embedded controller entry Hans de Goede
2021-05-06  9:23   ` Andy Shevchenko
2021-05-06  9:38     ` Hans de Goede
2021-05-06  9:42       ` Andy Shevchenko
2021-05-07 11:53       ` Campion Kang
2021-05-11 11:48         ` Hans de Goede
2021-05-07  0:50   ` Rob Herring
2021-05-07 12:03     ` Campion Kang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210506131734.GB2252703@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=campion.kang@advantech.com.tw \
    --cc=chia-lin.kao@canonical.com \
    --cc=corbet@lwn.net \
    --cc=devicetree@vger.kernel.org \
    --cc=hdegoede@redhat.com \
    --cc=jdelvare@suse.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=mgross@linux.intel.com \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=wim@linux-watchdog.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.