[PATCH] ie6xx_wdt: store and show whether system was rebooted by watchdog

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

 



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.

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

diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
index 8f541b9..16afe49 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
@@ -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);

@@ -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(rr1 & ~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;
 	}
--
1.7.5.4

--
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