public inbox for linux-watchdog@vger.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Philipp Zabel <p.zabel@pengutronix.de>, linux-watchdog@vger.kernel.org
Cc: Wim Van Sebroeck <wim@iguana.be>,
	support.opensource@diasemi.com, kernel@pengutronix.de
Subject: Re: [PATCH 1/2] watchdog: da9063: Ping watchdog only during allowed time window
Date: Fri, 07 Aug 2015 06:36:51 -0700	[thread overview]
Message-ID: <55C4B473.90307@roeck-us.net> (raw)
In-Reply-To: <1438879019-12978-1-git-send-email-p.zabel@pengutronix.de>

On 08/06/2015 09:36 AM, Philipp Zabel wrote:
> There is a cooldown period after watchdog timer setup, and also after each
> watchdog ping. If a ping is issued too early, the watchdog triggers the
> watchdog error condition and causes a system reset.
>
> The 256 ms period length is a best guess based on the same value being used
> for the DA9053 predecessor PMIC and experiments that have shown 200 ms are
> not enough to avoid the error.
>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

Hi Philipp,

instead of using this quite complex approach, would it be possible to use the
same approach as the da9062 driver ?

I understand the downside, which is that the caller may end up sleeping,
but this should not happen too often. Also, I plan to move the enforcement
of a minimal time between heartbeats into the infrastructure, so this would
not least forever.

Thanks,
Guneter

> ---
>   drivers/watchdog/da9063_wdt.c | 88 ++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 79 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
> index e2fe2eb..b2e9201 100644
> --- a/drivers/watchdog/da9063_wdt.c
> +++ b/drivers/watchdog/da9063_wdt.c
> @@ -35,11 +35,15 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
>   #define DA9063_WDT_MIN_TIMEOUT		wdt_timeout[DA9063_TWDSCALE_MIN]
>   #define DA9063_WDT_MAX_TIMEOUT		wdt_timeout[DA9063_TWDSCALE_MAX]
>   #define DA9063_WDG_TIMEOUT		wdt_timeout[3]
> +#define DA9063_TWDMIN			256
>
>   struct da9063_watchdog {
>   	struct da9063 *da9063;
>   	struct watchdog_device wdtdev;
>   	struct notifier_block restart_handler;
> +	struct delayed_work ping_work;
> +	struct mutex mutex;
> +	bool defer_ping;
>   };
>
>   static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
> @@ -54,10 +58,23 @@ static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
>   	return DA9063_TWDSCALE_MAX;
>   }
>
> -static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
> +static int _da9063_wdt_set_timeout(struct da9063_watchdog *wdt,
> +				   unsigned int regval)
>   {
> -	return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
> -				  DA9063_TWDSCALE_MASK, regval);
> +	struct da9063 *da9063 = wdt->da9063;
> +	int ret;
> +
> +	mutex_lock(&wdt->mutex);
> +
> +	ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
> +				 DA9063_TWDSCALE_MASK, regval);
> +
> +	wdt->defer_ping = false;
> +	schedule_delayed_work(&wdt->ping_work, msecs_to_jiffies(DA9063_TWDMIN));
> +
> +	mutex_unlock(&wdt->mutex);
> +
> +	return ret;
>   }
>
>   static int da9063_wdt_start(struct watchdog_device *wdd)
> @@ -67,12 +84,16 @@ static int da9063_wdt_start(struct watchdog_device *wdd)
>   	int ret;
>
>   	selector = da9063_wdt_timeout_to_sel(wdt->wdtdev.timeout);
> -	ret = _da9063_wdt_set_timeout(wdt->da9063, selector);
> -	if (ret)
> +	ret = _da9063_wdt_set_timeout(wdt, selector);
> +	if (ret) {
>   		dev_err(wdt->da9063->dev, "Watchdog failed to start (err = %d)\n",
>   			ret);
> +		return ret;
> +	}
>
> -	return ret;
> +	wdd->timeout = wdt_timeout[selector];
> +
> +	return 0;
>   }
>
>   static int da9063_wdt_stop(struct watchdog_device *wdd)
> @@ -80,6 +101,8 @@ static int da9063_wdt_stop(struct watchdog_device *wdd)
>   	struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
>   	int ret;
>
> +	cancel_delayed_work_sync(&wdt->ping_work);
> +
>   	ret = regmap_update_bits(wdt->da9063->regmap, DA9063_REG_CONTROL_D,
>   				 DA9063_TWDSCALE_MASK, DA9063_TWDSCALE_DISABLE);
>   	if (ret)
> @@ -89,9 +112,8 @@ static int da9063_wdt_stop(struct watchdog_device *wdd)
>   	return ret;
>   }
>
> -static int da9063_wdt_ping(struct watchdog_device *wdd)
> +static int da9063_wdt_issue_ping(struct da9063_watchdog *wdt)
>   {
> -	struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
>   	int ret;
>
>   	ret = regmap_write(wdt->da9063->regmap, DA9063_REG_CONTROL_F,
> @@ -100,9 +122,45 @@ static int da9063_wdt_ping(struct watchdog_device *wdd)
>   		dev_alert(wdt->da9063->dev, "Failed to ping the watchdog (err = %d)\n",
>   			  ret);
>
> +	wdt->defer_ping = false;
> +	schedule_delayed_work(&wdt->ping_work, msecs_to_jiffies(DA9063_TWDMIN));
> +
>   	return ret;
>   }
>
> +static int da9063_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
> +	int ret = 0;
> +
> +	mutex_lock(&wdt->mutex);
> +
> +	if (delayed_work_pending(&wdt->ping_work)) {
> +		wdt->defer_ping = true;
> +
> +		goto out;
> +	}
> +
> +	da9063_wdt_issue_ping(wdt);
> +out:
> +	mutex_unlock(&wdt->mutex);
> +
> +	return ret;
> +}
> +
> +static void da9063_wdt_ping_work(struct work_struct *work)
> +{
> +	struct da9063_watchdog *wdt = container_of(to_delayed_work(work),
> +					struct da9063_watchdog, ping_work);
> +
> +	mutex_lock(&wdt->mutex);
> +
> +	if (wdt->defer_ping)
> +		da9063_wdt_issue_ping(wdt);
> +
> +	mutex_unlock(&wdt->mutex);
> +}
> +
>   static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
>   				  unsigned int timeout)
>   {
> @@ -111,7 +169,7 @@ static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
>   	int ret;
>
>   	selector = da9063_wdt_timeout_to_sel(timeout);
> -	ret = _da9063_wdt_set_timeout(wdt->da9063, selector);
> +	ret = _da9063_wdt_set_timeout(wdt, selector);
>   	if (ret)
>   		dev_err(wdt->da9063->dev, "Failed to set watchdog timeout (err = %d)\n",
>   			ret);
> @@ -178,6 +236,9 @@ static int da9063_wdt_probe(struct platform_device *pdev)
>
>   	wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
>
> +	INIT_DELAYED_WORK(&wdt->ping_work, da9063_wdt_ping_work);
> +	mutex_init(&wdt->mutex);
> +
>   	watchdog_set_drvdata(&wdt->wdtdev, wdt);
>   	dev_set_drvdata(&pdev->dev, wdt);
>
> @@ -202,13 +263,22 @@ static int da9063_wdt_remove(struct platform_device *pdev)
>   	unregister_restart_handler(&wdt->restart_handler);
>
>   	watchdog_unregister_device(&wdt->wdtdev);
> +	cancel_delayed_work_sync(&wdt->ping_work);
>
>   	return 0;
>   }
>
> +static void da9063_wdt_shutdown(struct platform_device *pdev)
> +{
> +	struct da9063_watchdog *wdt = dev_get_drvdata(&pdev->dev);
> +
> +	cancel_delayed_work_sync(&wdt->ping_work);
> +}
> +
>   static struct platform_driver da9063_wdt_driver = {
>   	.probe = da9063_wdt_probe,
>   	.remove = da9063_wdt_remove,
> +	.shutdown = da9063_wdt_shutdown,
>   	.driver = {
>   		.name = DA9063_DRVNAME_WATCHDOG,
>   	},
>


  parent reply	other threads:[~2015-08-07 13:36 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-06 16:36 [PATCH 1/2] watchdog: da9063: Ping watchdog only during allowed time window Philipp Zabel
2015-08-06 16:36 ` [PATCH 2/2] watchdog: da9063: Disable and wait before changing timeout Philipp Zabel
2015-08-07 13:40   ` Guenter Roeck
2015-08-07 17:09     ` Philipp Zabel
2015-08-07 10:13 ` [PATCH 1/2] watchdog: da9063: Ping watchdog only during allowed time window Opensource [Adam Thomson]
2015-08-07 10:17   ` Philipp Zabel
2015-08-24 13:39     ` Opensource [Steve Twiss]
2015-08-07 13:36 ` Guenter Roeck [this message]
2015-08-07 17:08   ` Philipp Zabel
2015-08-07 17:33     ` Guenter Roeck

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=55C4B473.90307@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=kernel@pengutronix.de \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=support.opensource@diasemi.com \
    --cc=wim@iguana.be \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox