All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boris BREZILLON <b.brezillon@overkiz.com>
To: Wim Van Sebroeck <wim@iguana.be>
Cc: Fabio Porcedda <fabio.porcedda@gmail.com>,
	Nicolas Ferre <nicolas.ferre@atmel.com>,
	Guenter Roeck <groeck7@gmail.com>,
	Yang Wenyou <wenyou.yang@atmel.com>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-watchdog@vger.kernel.org,
	Boris BREZILLON <b.brezillon@overkiz.com>
Subject: [PATCH] watchdog: at91sam9_wdt: various fixes
Date: Tue, 29 Oct 2013 11:37:33 +0100	[thread overview]
Message-ID: <1383043053-3520-1-git-send-email-b.brezillon@overkiz.com> (raw)
In-Reply-To: <20131029075028.GF19704@spo001.leaseweb.com>

Fix the secs_to_ticks macro in case 0 is passed as an argument.

Rework the heartbeat calculation to increase the security margin of the
watchdog reset timer.

Use the min_heartbeat value instead of the calculated heartbeat value for
the first watchdog reset.

Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
 drivers/watchdog/at91sam9_wdt.c |   35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 9bd089e..f1b59f1 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -51,7 +51,7 @@
 #define ticks_to_hz_rounddown(t)	((((t) + 1) * HZ) >> 8)
 #define ticks_to_hz_roundup(t)		(((((t) + 1) * HZ) + 255) >> 8)
 #define ticks_to_secs(t)		(((t) + 1) >> 8)
-#define secs_to_ticks(s)		(((s) << 8) - 1)
+#define secs_to_ticks(s)		(s ? (((s) << 8) - 1) : 0)
 
 #define WDT_MR_RESET	0x3FFF2FFF
 
@@ -61,6 +61,11 @@
 /* Watchdog max delta/value in secs */
 #define WDT_COUNTER_MAX_SECS	ticks_to_secs(WDT_COUNTER_MAX_TICKS)
 
+/* Watchdog heartbeat shift used for security margin:
+ * we'll try to rshift the heartbeat value with this value to secure
+ * the watchdog reset. */
+#define WDT_HEARTBEAT_SHIFT	2
+
 /* Hardware timeout in seconds */
 #define WDT_HW_TIMEOUT 2
 
@@ -158,7 +163,9 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
 	int err;
 	u32 mask = wdt->mr_mask;
 	unsigned long min_heartbeat = 1;
+	unsigned long max_heartbeat;
 	struct device *dev = &pdev->dev;
+	int shift;
 
 	tmp = wdt_read(wdt, AT91_WDT_MR);
 	if ((tmp & mask) != (wdt->mr & mask)) {
@@ -181,23 +188,27 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
 	if (delta < value)
 		min_heartbeat = ticks_to_hz_roundup(value - delta);
 
-	wdt->heartbeat = ticks_to_hz_rounddown(value);
-	if (!wdt->heartbeat) {
+	max_heartbeat = ticks_to_hz_rounddown(value);
+	if (!max_heartbeat) {
 		dev_err(dev,
 			"heartbeat is too small for the system to handle it correctly\n");
 		return -EINVAL;
 	}
 
-	if (wdt->heartbeat < min_heartbeat + 4) {
+	for (shift = WDT_HEARTBEAT_SHIFT; shift > 0; shift--) {
+		if ((max_heartbeat >> shift) < min_heartbeat)
+			continue;
+
+		wdt->heartbeat = max_heartbeat >> shift;
+		break;
+	}
+
+	if (!shift)
 		wdt->heartbeat = min_heartbeat;
+
+	if (max_heartbeat < min_heartbeat + 4)
 		dev_warn(dev,
 			 "min heartbeat and max heartbeat might be too close for the system to handle it correctly\n");
-		if (wdt->heartbeat < 4)
-			dev_warn(dev,
-				 "heartbeat might be too small for the system to handle it correctly\n");
-	} else {
-		wdt->heartbeat -= 4;
-	}
 
 	if ((tmp & AT91_WDT_WDFIEN) && wdt->irq) {
 		err = request_irq(wdt->irq, wdt_interrupt,
@@ -213,7 +224,9 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
 			 tmp & wdt->mr_mask, wdt->mr & wdt->mr_mask);
 
 	setup_timer(&wdt->timer, at91_ping, (unsigned long)wdt);
-	mod_timer(&wdt->timer, jiffies + wdt->heartbeat);
+	/* Use min_heartbeat the first time because the watchdog timer might
+	 * be running for a long time when we reach this init function. */
+	mod_timer(&wdt->timer, jiffies + min_heartbeat);
 
 	/* Try to set timeout from device tree first */
 	if (watchdog_init_timeout(&wdt->wdd, 0, dev))
-- 
1.7.9.5


WARNING: multiple messages have this Message-ID (diff)
From: b.brezillon@overkiz.com (Boris BREZILLON)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] watchdog: at91sam9_wdt: various fixes
Date: Tue, 29 Oct 2013 11:37:33 +0100	[thread overview]
Message-ID: <1383043053-3520-1-git-send-email-b.brezillon@overkiz.com> (raw)
In-Reply-To: <20131029075028.GF19704@spo001.leaseweb.com>

Fix the secs_to_ticks macro in case 0 is passed as an argument.

Rework the heartbeat calculation to increase the security margin of the
watchdog reset timer.

Use the min_heartbeat value instead of the calculated heartbeat value for
the first watchdog reset.

Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
 drivers/watchdog/at91sam9_wdt.c |   35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 9bd089e..f1b59f1 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -51,7 +51,7 @@
 #define ticks_to_hz_rounddown(t)	((((t) + 1) * HZ) >> 8)
 #define ticks_to_hz_roundup(t)		(((((t) + 1) * HZ) + 255) >> 8)
 #define ticks_to_secs(t)		(((t) + 1) >> 8)
-#define secs_to_ticks(s)		(((s) << 8) - 1)
+#define secs_to_ticks(s)		(s ? (((s) << 8) - 1) : 0)
 
 #define WDT_MR_RESET	0x3FFF2FFF
 
@@ -61,6 +61,11 @@
 /* Watchdog max delta/value in secs */
 #define WDT_COUNTER_MAX_SECS	ticks_to_secs(WDT_COUNTER_MAX_TICKS)
 
+/* Watchdog heartbeat shift used for security margin:
+ * we'll try to rshift the heartbeat value with this value to secure
+ * the watchdog reset. */
+#define WDT_HEARTBEAT_SHIFT	2
+
 /* Hardware timeout in seconds */
 #define WDT_HW_TIMEOUT 2
 
@@ -158,7 +163,9 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
 	int err;
 	u32 mask = wdt->mr_mask;
 	unsigned long min_heartbeat = 1;
+	unsigned long max_heartbeat;
 	struct device *dev = &pdev->dev;
+	int shift;
 
 	tmp = wdt_read(wdt, AT91_WDT_MR);
 	if ((tmp & mask) != (wdt->mr & mask)) {
@@ -181,23 +188,27 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
 	if (delta < value)
 		min_heartbeat = ticks_to_hz_roundup(value - delta);
 
-	wdt->heartbeat = ticks_to_hz_rounddown(value);
-	if (!wdt->heartbeat) {
+	max_heartbeat = ticks_to_hz_rounddown(value);
+	if (!max_heartbeat) {
 		dev_err(dev,
 			"heartbeat is too small for the system to handle it correctly\n");
 		return -EINVAL;
 	}
 
-	if (wdt->heartbeat < min_heartbeat + 4) {
+	for (shift = WDT_HEARTBEAT_SHIFT; shift > 0; shift--) {
+		if ((max_heartbeat >> shift) < min_heartbeat)
+			continue;
+
+		wdt->heartbeat = max_heartbeat >> shift;
+		break;
+	}
+
+	if (!shift)
 		wdt->heartbeat = min_heartbeat;
+
+	if (max_heartbeat < min_heartbeat + 4)
 		dev_warn(dev,
 			 "min heartbeat and max heartbeat might be too close for the system to handle it correctly\n");
-		if (wdt->heartbeat < 4)
-			dev_warn(dev,
-				 "heartbeat might be too small for the system to handle it correctly\n");
-	} else {
-		wdt->heartbeat -= 4;
-	}
 
 	if ((tmp & AT91_WDT_WDFIEN) && wdt->irq) {
 		err = request_irq(wdt->irq, wdt_interrupt,
@@ -213,7 +224,9 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
 			 tmp & wdt->mr_mask, wdt->mr & wdt->mr_mask);
 
 	setup_timer(&wdt->timer, at91_ping, (unsigned long)wdt);
-	mod_timer(&wdt->timer, jiffies + wdt->heartbeat);
+	/* Use min_heartbeat the first time because the watchdog timer might
+	 * be running for a long time when we reach this init function. */
+	mod_timer(&wdt->timer, jiffies + min_heartbeat);
 
 	/* Try to set timeout from device tree first */
 	if (watchdog_init_timeout(&wdt->wdd, 0, dev))
-- 
1.7.9.5

  parent reply	other threads:[~2013-10-29 10:56 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-04  7:24 [PATCH v5 0/4] watchdog: at91sam9_wdt: handle already configured wdt Boris BREZILLON
2013-10-04  7:24 ` Boris BREZILLON
2013-10-04  7:24 ` [PATCH v5 1/4] watchdog: at91sam9_wdt: better watchdog support Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04 22:30   ` Guenter Roeck
2013-10-04 22:30     ` Guenter Roeck
2013-10-04 22:30     ` Guenter Roeck
2013-10-04  7:24 ` [PATCH v5 2/4] watchdog: at91sam9_wdt: update device tree doc Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04 22:30   ` Guenter Roeck
2013-10-04 22:30     ` Guenter Roeck
2013-10-04  7:24 ` [PATCH v5 3/4] ARM: at91/dt: add sam9 watchdog default options to SoCs Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04 22:31   ` Guenter Roeck
2013-10-04 22:31     ` Guenter Roeck
2013-10-04  7:24 ` [PATCH v5 4/4] ARM: at91/dt: add watchdog properties to kizbox board Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04  7:24   ` Boris BREZILLON
2013-10-04 22:32   ` Guenter Roeck
2013-10-04 22:32     ` Guenter Roeck
2013-10-04 22:32     ` Guenter Roeck
2013-10-29  7:50 ` [PATCH v5 0/4] watchdog: at91sam9_wdt: handle already configured wdt Wim Van Sebroeck
2013-10-29 10:31   ` boris brezillon
2013-10-29 10:31     ` boris brezillon
2013-10-29 12:58     ` Wim Van Sebroeck
2013-10-29 13:25       ` boris brezillon
2013-10-29 13:25         ` boris brezillon
2013-10-29 10:37   ` Boris BREZILLON [this message]
2013-10-29 10:37     ` [PATCH] watchdog: at91sam9_wdt: various fixes Boris BREZILLON
2013-10-29 15:45     ` Guenter Roeck
2013-10-29 15:45       ` Guenter Roeck
2013-10-29 16:22       ` boris brezillon
2013-10-29 16:22         ` boris brezillon
2013-10-29 16:43         ` Guenter Roeck
2013-10-29 16:43           ` Guenter Roeck
2013-10-29 17:22           ` boris brezillon
2013-10-29 17:22             ` boris brezillon
2013-10-29 21:27             ` Guenter Roeck
2013-10-29 21:27               ` Guenter Roeck
2013-10-30  6:01               ` b.brezillon
2013-10-30  6:01                 ` b.brezillon at overkiz.com
2013-10-31 10:13               ` Jean-Christophe PLAGNIOL-VILLARD
2013-10-31 10:13                 ` Jean-Christophe PLAGNIOL-VILLARD
2013-11-03 14:42             ` boris brezillon
2013-11-03 14:42               ` boris brezillon
2013-11-03 16:22               ` Guenter Roeck
2013-11-03 16:22                 ` Guenter Roeck
2013-11-03 17:55                 ` boris brezillon
2013-11-03 17:55                   ` boris brezillon

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=1383043053-3520-1-git-send-email-b.brezillon@overkiz.com \
    --to=b.brezillon@overkiz.com \
    --cc=fabio.porcedda@gmail.com \
    --cc=groeck7@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=nicolas.ferre@atmel.com \
    --cc=wenyou.yang@atmel.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 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.