static int ibwdt_is_open;
static spinlock_t ibwdt_lock;
+static int expect_close = 0;
/*
*
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;
+ }
+ }
ibwdt_ping();
return 1;
}
unsigned long arg)
{
static struct watchdog_info ident = {
- WDIOF_KEEPALIVEPING, 1, "IB700 WDT"
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = "IB700 WDT"
};
switch (cmd) {
static int
ibwdt_open(struct inode *inode, struct file *file)
{
- switch (minor(inode->i_rdev)) {
- case WATCHDOG_MINOR:
- spin_lock(&ibwdt_lock);
- if (ibwdt_is_open) {
- spin_unlock(&ibwdt_lock);
- return -EBUSY;
- }
- if (nowayout) {
- MOD_INC_USE_COUNT;
- }
- /*
- * Activate
- */
-
- ibwdt_is_open = 1;
- ibwdt_ping();
+ if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
+ spin_lock(&ibwdt_lock);
+ if (ibwdt_is_open) {
spin_unlock(&ibwdt_lock);
- return 0;
- default:
- return -ENODEV;
+ return -EBUSY;
+ }
+ if (nowayout)
+ MOD_INC_USE_COUNT;
+
+ /* Activate */
+ ibwdt_is_open = 1;
+ ibwdt_ping();
+ spin_unlock(&ibwdt_lock);
+ return 0;
+ } else {
+ return -ENODEV;
}
}
static int
ibwdt_close(struct inode *inode, struct file *file)
{
- lock_kernel();
if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&ibwdt_lock);
- if (!nowayout) {
+ if (expect_close)
outb_p(timeout_val, WDT_STOP);
- }
+ else
+ printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n");
+
ibwdt_is_open = 0;
spin_unlock(&ibwdt_lock);
}
- unlock_kernel();
return 0;
}