From: Ralf Baechle Forward port of the 2.4 driver with changes required for 2.6. Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/watchdog/indydog.c | 117 ++++++++++++-------------------- 1 files changed, 45 insertions(+), 72 deletions(-) diff -puN drivers/char/watchdog/indydog.c~indydog-update drivers/char/watchdog/indydog.c --- 25/drivers/char/watchdog/indydog.c~indydog-update 2004-06-22 11:09:03.408424560 -0700 +++ 25-akpm/drivers/char/watchdog/indydog.c 2004-06-22 11:09:03.413423800 -0700 @@ -22,16 +22,11 @@ #include #include #include -#include #include -#include +#include #define PFX "indydog: " -#define WATCHDOG_HEARTBEAT 60 - -static unsigned long indydog_alive; -static struct sgimc_misc_ctrl *mcmisc_regs; -static char expect_close; +static int indydog_alive; #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -39,96 +34,78 @@ static int nowayout = 1; static int nowayout = 0; #endif +#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ + module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); static void indydog_start(void) { - u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; + u32 mc_ctrl0 = sgimc->cpuctrl0; - mc_ctrl0 |= SGIMC_CCTRL0_WDOG; - mcmisc_regs->cpuctrl0 = mc_ctrl0; - - printk(KERN_INFO PFX "Started watchdog timer.\n"); + mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG; + sgimc->cpuctrl0 = mc_ctrl0; } static void indydog_stop(void) { - u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; + u32 mc_ctrl0 = sgimc->cpuctrl0; mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; - mcmisc_regs->cpuctrl0 = mc_ctrl0; + sgimc->cpuctrl0 = mc_ctrl0; printk(KERN_INFO PFX "Stopped watchdog timer.\n"); } static void indydog_ping(void) { - mcmisc_regs->watchdogt = 0; + sgimc->watchdogt = 0; } /* * Allow only one person to hold it open */ - static int indydog_open(struct inode *inode, struct file *file) { - if( test_and_set_bit(0,&indydog_alive) ) + if (indydog_alive) return -EBUSY; if (nowayout) __module_get(THIS_MODULE); - /* - * Activate timer - */ + /* Activate timer */ indydog_start(); indydog_ping(); + indydog_alive = 1; + printk(KERN_INFO "Started watchdog timer.\n"); + return 0; } static int indydog_release(struct inode *inode, struct file *file) { - /* - * Shut off the timer. - * Lock it in if it's a module and we set nowayout - */ - - if (expect_close == 42) { - indydog_stop(); - } else { - printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); - indydog_ping(); + /* Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT */ + if (!nowayout) { + u32 mc_ctrl0 = sgimc->cpuctrl0; + mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; + sgimc->cpuctrl0 = mc_ctrl0; + printk(KERN_INFO "Stopped watchdog timer.\n"); } - clear_bit(0,&indydog_alive); - expect_close = 0; + indydog_alive = 0; + return 0; } static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - /* Can't seek (pwrite) on this device */ + /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; /* Refresh the timer. */ if (len) { - if (!nowayout) { - size_t i; - - /* In case it was set long ago */ - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = 42; - } - } indydog_ping(); } return len; @@ -139,17 +116,18 @@ static int indydog_ioctl(struct inode *i { int options, retval = -EINVAL; static struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 0, - .identity = "Hardware Watchdog for SGI IP22", + .options = WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = "Hardware Watchdog for SGI IP22", }; switch (cmd) { default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: - if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + if (copy_to_user((struct watchdog_info *)arg, + &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: @@ -165,14 +143,12 @@ static int indydog_ioctl(struct inode *i if (get_user(options, (int *)arg)) return -EFAULT; - if (options & WDIOS_DISABLECARD) - { + if (options & WDIOS_DISABLECARD) { indydog_stop(); retval = 0; } - if (options & WDIOS_ENABLECARD) - { + if (options & WDIOS_ENABLECARD) { indydog_start(); retval = 0; } @@ -184,40 +160,37 @@ static int indydog_ioctl(struct inode *i static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { - if (code==SYS_DOWN || code==SYS_HALT) { - /* Turn the WDT off */ - indydog_stop(); - } + if (code == SYS_DOWN || code == SYS_HALT) + indydog_stop(); /* Turn the WDT off */ return NOTIFY_DONE; } static struct file_operations indydog_fops = { - .owner = THIS_MODULE, - .write = indydog_write, - .ioctl = indydog_ioctl, - .open = indydog_open, - .release= indydog_release, + .owner = THIS_MODULE, + .write = indydog_write, + .ioctl = indydog_ioctl, + .open = indydog_open, + .release = indydog_release, }; static struct miscdevice indydog_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &indydog_fops, + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &indydog_fops, }; static struct notifier_block indydog_notifier = { .notifier_call = indydog_notify_sys, }; -static char banner[] __initdata = KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n"; +static char banner[] __initdata = + KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n"; static int __init watchdog_init(void) { int ret; - mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); - ret = register_reboot_notifier(&indydog_notifier); if (ret) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", _