Re: [PATCH 3/4] ie6xx_wdt: store and show whether system was rebooted by watchdog.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear sirs,

Do you have any feedback on either of my patches?

Cheers, Chris.

On Mon, 13 Aug 2012, Chris Wilson wrote:

The watchdog has a persistent bit which is set when it resets the host,
and can be reset by the host. The driver previously ignored this bit.
It was called WDT_TOUT by the driver, but WDT_TIMEOUT in the datasheet,
so I've renamed it for clarity.

If this bit is set when the driver is probed, I store it in the
watchdog_device bootstatus field, which can be read by
ioctl("/dev/watchdog", WDIOC_GETBOOTSTATUS). If debugfs is enabled,
the recorded value is also printed in the debugfs file
(/sys/kernel/debug/ie6xx_wdt). I used this to verify that that the
bit is not set when the system booted normally, but is set when it
was rebooted by the watchdog.

Please ignore the previous version of this patch, which was not sent
using git send-email, and did not reset the WDT_TIMEOUT bit properly
after the module was initialized.

Signed-off-by: Chris Wilson <chris+github@xxxxxxxxx>
---
drivers/watchdog/ie6xx_wdt.c |   30 +++++++++++++++++++++---------
1 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
index 8f541b9..6b7b520 100644
--- a/drivers/watchdog/ie6xx_wdt.c
+++ b/drivers/watchdog/ie6xx_wdt.c
@@ -42,7 +42,7 @@
#define RR0	0x0c
#define RR1	0x0d
#define WDT_RELOAD	0x01
-#define WDT_TOUT	0x02
+#define WDT_TIMEOUT	0x02

#define WDTCR	0x10
#define WDT_PRE_SEL	0x04
@@ -103,7 +103,7 @@ static int ie6xx_wdt_ping(struct watchdog_device *wdd)
{
	spin_lock(&ie6xx_wdt_data.unlock_sequence);
	ie6xx_wdt_unlock_registers();
-	outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1);
+	outb(WDT_RELOAD | WDT_TIMEOUT, ie6xx_wdt_data.sch_wdtba + RR1);
	spin_unlock(&ie6xx_wdt_data.unlock_sequence);
	return 0;
}
@@ -137,7 +137,7 @@ static int ie6xx_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
	outl(preload, ie6xx_wdt_data.sch_wdtba + PV2);

	ie6xx_wdt_unlock_registers();
-	outb(WDT_RELOAD | WDT_TOUT, ie6xx_wdt_data.sch_wdtba + RR1);
+	outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1);

	spin_unlock(&ie6xx_wdt_data.unlock_sequence);

@@ -160,7 +160,7 @@ static int ie6xx_wdt_start(struct watchdog_device *wdd)
static int ie6xx_wdt_stop(struct watchdog_device *wdd)
{
	if (inb(ie6xx_wdt_data.sch_wdtba + WDTLR) & WDT_LOCK)
-		return -1;
+		return -EACCES; // close not allowed?!

	/* Disable the watchdog timer */
	spin_lock(&ie6xx_wdt_data.unlock_sequence);
@@ -208,8 +208,8 @@ static int ie6xx_wdt_dbg_show(struct seq_file *s, void *unused)
		inl(ie6xx_wdt_data.sch_wdtba + DCR));
	seq_printf(s, "WDTLR = 0x%08x\n",
		inw(ie6xx_wdt_data.sch_wdtba + WDTLR));
-
-	seq_printf(s, "\n");
+	seq_printf(s, "Rebooted = %s\n",
+		ie6xx_wdt_dev.bootstatus & WDIOF_CARDRESET ? "Yes" : "No");
	return 0;
}

@@ -250,12 +250,14 @@ static void ie6xx_wdt_debugfs_exit(void)
static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)
{
	struct resource *res;
-	u8 wdtlr;
+	u8 wdtlr, rr1;
	int ret;

	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!res)
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get resources\n");
		return -ENODEV;
+	}

	if (!request_region(res->start, resource_size(res), pdev->name)) {
		dev_err(&pdev->dev, "Watchdog region 0x%llx already in use!\n",
@@ -266,6 +268,15 @@ static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)
	ie6xx_wdt_data.sch_wdtba = res->start;
	dev_dbg(&pdev->dev, "WDT = 0x%X\n", ie6xx_wdt_data.sch_wdtba);

+	rr1 = inb(ie6xx_wdt_data.sch_wdtba + RR1);
+	if (rr1 & WDT_TIMEOUT) {
+		dev_warn(&pdev->dev, "Previous reboot was caused by the card\n");
+		ie6xx_wdt_dev.bootstatus |= WDIOF_CARDRESET;
+		// reset the flag
+		ie6xx_wdt_unlock_registers();
+		outb(WDT_TIMEOUT, ie6xx_wdt_data.sch_wdtba + RR1);
+	}
+
	ie6xx_wdt_dev.timeout = timeout;
	watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout);

@@ -280,8 +291,9 @@ static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)

	ret = watchdog_register_device(&ie6xx_wdt_dev);
	if (ret) {
+		printk(KERN_INFO "ie6xx_wdt_probe: can't register device\n");
		dev_err(&pdev->dev,
-			"Watchdog timer: cannot register device (err =%d)\n",
+			"Watchdog timer: cannot register device (err=%d)\n",
									ret);
		goto misc_register_error;
	}


--
_____ __     _
\  __/ / ,__(_)_  | Chris Wilson <chris+sig@xxxxxxxxx> Cambs UK |
/ (_/ ,\/ _/ /_ \ | Security/C/C++/Java/Ruby/Perl/SQL Developer |
\__/_/_/_//_/___/ | We are GNU : free your mind & your software |
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux