All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Yang, Wenyou" <wenyou.yang@atmel.com>
To: Timo Kokkonen <timo.kokkonen@offcode.fi>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-watchdog@vger.kernel.org>,
	<boris.brezillon@free-electrons.com>, <nicolas.ferre@atmel.com>,
	<alexandre.belloni@free-electrons.com>
Subject: Re: [PATCHv5 2/4] watchdog: Allow watchdog to reset device at early boot
Date: Mon, 13 Apr 2015 15:56:16 +0800	[thread overview]
Message-ID: <552B76A0.5050307@atmel.com> (raw)
In-Reply-To: <1428671199-5562-3-git-send-email-timo.kokkonen@offcode.fi>



On 2015/4/10 21:06, Timo Kokkonen wrote:
> Historically the watchdogs have always been stopped before user space
> opens and takes over the device. This is not good on many production
> systems where any crash, in kernel or user space, must always result
> in a device reset.
>
> Add a new early_timeout_sec parameter to the watchdog that gives user
> space certain amount of time to set up itself and take over the
> watchdog. Until this timeout has been reached the watchdog core takes
> care of petting the watchdog HW. If there is any crash in kernel or
> user space, reboot is guaranteed as watchdog hardware is never
> stopped.
>
> There is also mode of supplying zero seconds for the early_timeout_sec
> parameter. In this mode the worker is not scheduled, so the watchdog
> timer is not touched nor is the HW petted until user space takes over
> it.
>
> Signed-off-by: Timo Kokkonen <timo.kokkonen@offcode.fi>
> ---
>   drivers/watchdog/watchdog_core.c | 39 ++++++++++++++++++++++++++++++---------
>   include/linux/watchdog.h         |  1 +
>   2 files changed, 31 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index 8e7d08d..d6bedf7 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -111,12 +111,18 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
>    */
>   int watchdog_init_params(struct watchdog_device *wdd, struct device *dev)
>   {
> +	unsigned int t = 0;
>   	int ret = 0;
>   
>   	ret = watchdog_init_timeout(wdd, wdd->timeout, dev);
>   	if (ret < 0)
>   		return ret;
>   
> +	if (!of_property_read_u32(dev->of_node, "early-timeout-sec", &t))
> +		wdd->early_timeout_sec = t;
> +	else
> +		wdd->early_timeout_sec = -1;
> +
>   	/*
>   	 * Max HW timeout needs to be set so that core knows when to
>   	 * use a kernel worker to support longer watchdog timeouts
> @@ -139,6 +145,7 @@ static void watchdog_worker(struct work_struct *work)
>   	}
>   
>   	if ((!watchdog_active(wdd) && !watchdog_is_stoppable(wdd)) ||
> +		(!watchdog_active(wdd) && wdd->early_timeout_sec >= 0) ||
>   		(watchdog_active(wdd) &&
>   			wdd->hw_max_timeout < wdd->timeout * HZ)) {
>   		if (wdd->ops->ping)
> @@ -152,17 +159,31 @@ static void watchdog_worker(struct work_struct *work)
>   
>   static int prepare_watchdog(struct watchdog_device *wdd)
>   {
> -	/* Stop the watchdog now before user space opens the device */
> -	if (wdd->hw_features & WDOG_HW_IS_STOPPABLE &&
> -		wdd->hw_features & WDOG_HW_RUNNING_AT_BOOT) {
> -		wdd->ops->stop(wdd);
> -
> -	} else if (!(wdd->hw_features & WDOG_HW_IS_STOPPABLE)) {
> +	if (wdd->early_timeout_sec >= 0) {
>   		/*
> -		 * Can't stop it, use a kernel timer to tick
> -		 * it until it's open by user space
> +		 * early timeout, if set, ensures that watchdog will
> +		 * reset the device unless user space opens the
> +		 * watchdog device within the given interval.
>   		 */
> -		schedule_delayed_work(&wdd->work, wdd->hw_heartbeat);
> +		if (!(wdd->hw_features & WDOG_HW_RUNNING_AT_BOOT))
> +			wdd->ops->start(wdd);
> +
> +		if (wdd->early_timeout_sec > 0) {
> +			schedule_delayed_work(&wdd->work,  wdd->hw_heartbeat);
> +		}

This bracket is unnecessary.

> +	} else {
> +		/* Stop the watchdog now before user space opens the device */
> +		if (wdd->hw_features & WDOG_HW_IS_STOPPABLE &&
> +			wdd->hw_features & WDOG_HW_RUNNING_AT_BOOT) {
> +			wdd->ops->stop(wdd);
> +
> +		} else if (!(wdd->hw_features & WDOG_HW_IS_STOPPABLE)) {
> +			/*
> +			 * Can't stop it, use a kernel timer to tick
> +			 * it until it's open by user space
> +			 */
> +			schedule_delayed_work(&wdd->work, wdd->hw_heartbeat);
> +		}
>   	}
>   	return 0;
>   }
> diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
> index c16c921..6f868b6 100644
> --- a/include/linux/watchdog.h
> +++ b/include/linux/watchdog.h
> @@ -94,6 +94,7 @@ struct watchdog_device {
>   	unsigned int hw_max_timeout; /* in jiffies */
>   	unsigned int hw_heartbeat; /* in jiffies */
>   	unsigned long int expires; /* for soft timer */
> +	unsigned int early_timeout_sec;
>   	void *driver_data;
>   	struct mutex lock;
>   	struct delayed_work work;
Best Regards,
Wenyou Yang


WARNING: multiple messages have this Message-ID (diff)
From: wenyou.yang@atmel.com (Yang, Wenyou)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv5 2/4] watchdog: Allow watchdog to reset device at early boot
Date: Mon, 13 Apr 2015 15:56:16 +0800	[thread overview]
Message-ID: <552B76A0.5050307@atmel.com> (raw)
In-Reply-To: <1428671199-5562-3-git-send-email-timo.kokkonen@offcode.fi>



On 2015/4/10 21:06, Timo Kokkonen wrote:
> Historically the watchdogs have always been stopped before user space
> opens and takes over the device. This is not good on many production
> systems where any crash, in kernel or user space, must always result
> in a device reset.
>
> Add a new early_timeout_sec parameter to the watchdog that gives user
> space certain amount of time to set up itself and take over the
> watchdog. Until this timeout has been reached the watchdog core takes
> care of petting the watchdog HW. If there is any crash in kernel or
> user space, reboot is guaranteed as watchdog hardware is never
> stopped.
>
> There is also mode of supplying zero seconds for the early_timeout_sec
> parameter. In this mode the worker is not scheduled, so the watchdog
> timer is not touched nor is the HW petted until user space takes over
> it.
>
> Signed-off-by: Timo Kokkonen <timo.kokkonen@offcode.fi>
> ---
>   drivers/watchdog/watchdog_core.c | 39 ++++++++++++++++++++++++++++++---------
>   include/linux/watchdog.h         |  1 +
>   2 files changed, 31 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index 8e7d08d..d6bedf7 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -111,12 +111,18 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
>    */
>   int watchdog_init_params(struct watchdog_device *wdd, struct device *dev)
>   {
> +	unsigned int t = 0;
>   	int ret = 0;
>   
>   	ret = watchdog_init_timeout(wdd, wdd->timeout, dev);
>   	if (ret < 0)
>   		return ret;
>   
> +	if (!of_property_read_u32(dev->of_node, "early-timeout-sec", &t))
> +		wdd->early_timeout_sec = t;
> +	else
> +		wdd->early_timeout_sec = -1;
> +
>   	/*
>   	 * Max HW timeout needs to be set so that core knows when to
>   	 * use a kernel worker to support longer watchdog timeouts
> @@ -139,6 +145,7 @@ static void watchdog_worker(struct work_struct *work)
>   	}
>   
>   	if ((!watchdog_active(wdd) && !watchdog_is_stoppable(wdd)) ||
> +		(!watchdog_active(wdd) && wdd->early_timeout_sec >= 0) ||
>   		(watchdog_active(wdd) &&
>   			wdd->hw_max_timeout < wdd->timeout * HZ)) {
>   		if (wdd->ops->ping)
> @@ -152,17 +159,31 @@ static void watchdog_worker(struct work_struct *work)
>   
>   static int prepare_watchdog(struct watchdog_device *wdd)
>   {
> -	/* Stop the watchdog now before user space opens the device */
> -	if (wdd->hw_features & WDOG_HW_IS_STOPPABLE &&
> -		wdd->hw_features & WDOG_HW_RUNNING_AT_BOOT) {
> -		wdd->ops->stop(wdd);
> -
> -	} else if (!(wdd->hw_features & WDOG_HW_IS_STOPPABLE)) {
> +	if (wdd->early_timeout_sec >= 0) {
>   		/*
> -		 * Can't stop it, use a kernel timer to tick
> -		 * it until it's open by user space
> +		 * early timeout, if set, ensures that watchdog will
> +		 * reset the device unless user space opens the
> +		 * watchdog device within the given interval.
>   		 */
> -		schedule_delayed_work(&wdd->work, wdd->hw_heartbeat);
> +		if (!(wdd->hw_features & WDOG_HW_RUNNING_AT_BOOT))
> +			wdd->ops->start(wdd);
> +
> +		if (wdd->early_timeout_sec > 0) {
> +			schedule_delayed_work(&wdd->work,  wdd->hw_heartbeat);
> +		}

This bracket is unnecessary.

> +	} else {
> +		/* Stop the watchdog now before user space opens the device */
> +		if (wdd->hw_features & WDOG_HW_IS_STOPPABLE &&
> +			wdd->hw_features & WDOG_HW_RUNNING_AT_BOOT) {
> +			wdd->ops->stop(wdd);
> +
> +		} else if (!(wdd->hw_features & WDOG_HW_IS_STOPPABLE)) {
> +			/*
> +			 * Can't stop it, use a kernel timer to tick
> +			 * it until it's open by user space
> +			 */
> +			schedule_delayed_work(&wdd->work, wdd->hw_heartbeat);
> +		}
>   	}
>   	return 0;
>   }
> diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
> index c16c921..6f868b6 100644
> --- a/include/linux/watchdog.h
> +++ b/include/linux/watchdog.h
> @@ -94,6 +94,7 @@ struct watchdog_device {
>   	unsigned int hw_max_timeout; /* in jiffies */
>   	unsigned int hw_heartbeat; /* in jiffies */
>   	unsigned long int expires; /* for soft timer */
> +	unsigned int early_timeout_sec;
>   	void *driver_data;
>   	struct mutex lock;
>   	struct delayed_work work;
Best Regards,
Wenyou Yang

  reply	other threads:[~2015-04-13  7:56 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-10 13:06 [PATCHv5 0/4] watchdog: Extend kernel API and add early_timeout_sec feature Timo Kokkonen
2015-04-10 13:06 ` Timo Kokkonen
2015-04-10 13:06 ` [PATCHv5 1/4] watchdog: Extend kernel API to know about HW limitations Timo Kokkonen
2015-04-10 13:06   ` Timo Kokkonen
2015-04-13  7:56   ` Yang, Wenyou
2015-04-13  7:56     ` Yang, Wenyou
2015-04-13  9:29   ` Yang, Wenyou
2015-04-13  9:29     ` Yang, Wenyou
2015-04-13 11:00     ` Timo Kokkonen
2015-04-13 11:00       ` Timo Kokkonen
2015-04-14  2:39       ` Yang, Wenyou
2015-04-14  2:39         ` Yang, Wenyou
2015-04-14  5:31         ` Timo Kokkonen
2015-04-14  5:31           ` Timo Kokkonen
2015-04-14  5:44           ` Yang, Wenyou
2015-04-14  5:44             ` Yang, Wenyou
2015-04-10 13:06 ` [PATCHv5 2/4] watchdog: Allow watchdog to reset device at early boot Timo Kokkonen
2015-04-10 13:06   ` Timo Kokkonen
2015-04-13  7:56   ` Yang, Wenyou [this message]
2015-04-13  7:56     ` Yang, Wenyou
2015-04-10 13:06 ` [PATCHv5 3/4] devicetree: Document generic watchdog properties Timo Kokkonen
2015-04-10 13:06   ` Timo Kokkonen
2015-04-10 13:06 ` [PATCHv5 4/4] watchdog: at91sam9_wdt: Convert to use new watchdog core extensions Timo Kokkonen
2015-04-10 13:06   ` Timo Kokkonen
2015-04-13  7:55 ` [PATCHv5 0/4] watchdog: Extend kernel API and add early_timeout_sec feature Yang, Wenyou
2015-04-13  7:55   ` Yang, Wenyou
2015-04-13  8:19   ` Timo Kokkonen
2015-04-13  8:19     ` Timo Kokkonen

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=552B76A0.5050307@atmel.com \
    --to=wenyou.yang@atmel.com \
    --cc=alexandre.belloni@free-electrons.com \
    --cc=boris.brezillon@free-electrons.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=nicolas.ferre@atmel.com \
    --cc=timo.kokkonen@offcode.fi \
    /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.