fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / char / watchdog / softdog.c
index e9f4f22..4067e1f 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/miscdevice.h>
@@ -47,6 +46,8 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
+
 #include <asm/uaccess.h>
 
 #define PFX "SoftDog: "
@@ -56,12 +57,7 @@ static int soft_margin = TIMER_MARGIN;       /* in seconds */
 module_param(soft_margin, int, 0);
 MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
 
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int nowayout = 1;
-#else
-static int nowayout = 0;
-#endif
-
+static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
@@ -82,7 +78,7 @@ static void watchdog_fire(unsigned long);
 
 static struct timer_list watchdog_ticktock =
                TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static unsigned long timer_alive;
+static unsigned long driver_open, orphan_timer;
 static char expect_close;
 
 
@@ -92,12 +88,15 @@ static char expect_close;
 
 static void watchdog_fire(unsigned long data)
 {
+       if (test_and_clear_bit(0, &orphan_timer))
+               module_put(THIS_MODULE);
+
        if (soft_noboot)
                printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
        else
        {
                printk(KERN_CRIT PFX "Initiating system reboot.\n");
-               machine_restart(NULL);
+               emergency_restart();
                printk(KERN_CRIT PFX "Reboot didn't ?????\n");
        }
 }
@@ -133,15 +132,15 @@ static int softdog_set_heartbeat(int t)
 
 static int softdog_open(struct inode *inode, struct file *file)
 {
-       if(test_and_set_bit(0, &timer_alive))
+       if (test_and_set_bit(0, &driver_open))
                return -EBUSY;
-       if (nowayout)
+       if (!test_and_clear_bit(0, &orphan_timer))
                __module_get(THIS_MODULE);
        /*
         *      Activate timer
         */
        softdog_keepalive();
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static int softdog_release(struct inode *inode, struct file *file)
@@ -152,21 +151,19 @@ static int softdog_release(struct inode *inode, struct file *file)
         */
        if (expect_close == 42) {
                softdog_stop();
+               module_put(THIS_MODULE);
        } else {
                printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               set_bit(0, &orphan_timer);
                softdog_keepalive();
        }
-       clear_bit(0, &timer_alive);
+       clear_bit(0, &driver_open);
        expect_close = 0;
        return 0;
 }
 
-static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
 {
-       /*  Can't seek (pwrite) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
        /*
         *      Refresh the timer.
         */
@@ -194,6 +191,8 @@ static ssize_t softdog_write(struct file *file, const char *data, size_t len, lo
 static int softdog_ioctl(struct inode *inode, struct file *file,
        unsigned int cmd, unsigned long arg)
 {
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
        int new_margin;
        static struct watchdog_info ident = {
                .options =              WDIOF_SETTIMEOUT |
@@ -204,25 +203,25 @@ static int softdog_ioctl(struct inode *inode, struct file *file,
        };
        switch (cmd) {
                default:
-                       return -ENOIOCTLCMD;
+                       return -ENOTTY;
                case WDIOC_GETSUPPORT:
-                       return copy_to_user((struct watchdog_info *)arg, &ident,
+                       return copy_to_user(argp, &ident,
                                sizeof(ident)) ? -EFAULT : 0;
                case WDIOC_GETSTATUS:
                case WDIOC_GETBOOTSTATUS:
-                       return put_user(0,(int *)arg);
+                       return put_user(0, p);
                case WDIOC_KEEPALIVE:
                        softdog_keepalive();
                        return 0;
                case WDIOC_SETTIMEOUT:
-                       if (get_user(new_margin, (int *)arg))
+                       if (get_user(new_margin, p))
                                return -EFAULT;
                        if (softdog_set_heartbeat(new_margin))
                                return -EINVAL;
                        softdog_keepalive();
                        /* Fall */
                case WDIOC_GETTIMEOUT:
-                       return put_user(soft_margin, (int *)arg);
+                       return put_user(soft_margin, p);
        }
 }
 
@@ -244,7 +243,7 @@ static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
  *     Kernel Interfaces
  */
 
-static struct file_operations softdog_fops = {
+static const struct file_operations softdog_fops = {
        .owner          = THIS_MODULE,
        .llseek         = no_llseek,
        .write          = softdog_write,