patch-2.4.20 linux-2.4.20/drivers/char/wafer5823wdt.c

Next file: linux-2.4.20/drivers/char/wdt.c
Previous file: linux-2.4.20/drivers/char/w83877f_wdt.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/char/wafer5823wdt.c linux-2.4.20/drivers/char/wafer5823wdt.c
@@ -40,6 +40,7 @@
 
 static unsigned long wafwdt_is_open;
 static spinlock_t wafwdt_lock;
+static int expect_close = 0;
 
 /*
  *	You must set these - there is no sane way to probe for this board.
@@ -54,6 +55,16 @@
 #define WDT_STOP 0x843
 
 #define WD_TIMO 60		/* 1 minute */
+static int wd_margin = WD_TIMO;
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 static void wafwdt_ping(void)
 {
@@ -67,7 +78,7 @@
 static void wafwdt_start(void)
 {
 	/* start up watchdog */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(wd_margin, WDT_START);
 	inb_p(WDT_START);
 }
 
@@ -85,6 +96,20 @@
 		return -ESPIPE;
 
 	if (count) {
+		if (!nowayout) {
+			size_t i;
+
+			/* In case it was set long ago */
+			expect_close = 0;
+
+			for (i = 0; i != count; i++) {
+				char c;
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_close = 1;
+			}
+		}
 		wafwdt_ping();
 		return 1;
 	}
@@ -94,8 +119,12 @@
 static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	     unsigned long arg)
 {
+	int new_margin;
 	static struct watchdog_info ident = {
-		WDIOF_KEEPALIVEPING, 1, "Wafer 5823 WDT"
+		WDIOF_KEEPALIVEPING |
+		WDIOF_SETTIMEOUT |
+		WDIOF_MAGICCLOSE,
+		1, "Wafer 5823 WDT"
 	};
 	int one=1;
 
@@ -115,6 +144,18 @@
 		wafwdt_ping();
 		break;
 
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int *)arg))
+			return -EFAULT;
+		if ((new_margin < 1) || (new_margin > 255))
+			return -EINVAL;
+		wd_margin = new_margin;
+		wafwdt_stop();
+		wafwdt_start();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user(wd_margin, (int *)arg);
+
 	default:
 		return -ENOTTY;
 	}
@@ -133,9 +174,11 @@
 wafwdt_close(struct inode *inode, struct file *file)
 {
 	clear_bit(0, &wafwdt_is_open);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-        wafwdt_stop();
-#endif
+	if (expect_close) {
+        	wafwdt_stop();
+	} else {
+		printk(KERN_CRIT "WDT device closed unexpectedly.  WDT will not stop!\n");
+	}
 	return 0;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)