linux/arch/um/drivers/harddog_kern.c
<<
>>
Prefs
   1/* UML hardware watchdog, shamelessly stolen from:
   2 *
   3 *      SoftDog 0.05:   A Software Watchdog Device
   4 *
   5 *      (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
   6 *                              http://www.redhat.com
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 *
  13 *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
  14 *      warranty for any of this software. This material is provided
  15 *      "AS-IS" and at no charge.
  16 *
  17 *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  18 *
  19 *      Software only watchdog driver. Unlike its big brother the WDT501P
  20 *      driver this won't always recover a failed machine.
  21 *
  22 *  03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
  23 *      Modularised.
  24 *      Added soft_margin; use upon insmod to change the timer delay.
  25 *      NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
  26 *          minors.
  27 *
  28 *  19980911 Alan Cox
  29 *      Made SMP safe for 2.3.x
  30 *
  31 *  20011127 Joel Becker (jlbec@evilplan.org>
  32 *      Added soft_noboot; Allows testing the softdog trigger without
  33 *      requiring a recompile.
  34 *      Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
  35 */
  36
  37#include <linux/module.h>
  38#include <linux/types.h>
  39#include <linux/kernel.h>
  40#include <linux/fs.h>
  41#include <linux/mm.h>
  42#include <linux/miscdevice.h>
  43#include <linux/watchdog.h>
  44#include <linux/reboot.h>
  45#include <linux/mutex.h>
  46#include <linux/init.h>
  47#include <linux/spinlock.h>
  48#include <linux/uaccess.h>
  49#include "mconsole.h"
  50
  51MODULE_LICENSE("GPL");
  52
  53static DEFINE_MUTEX(harddog_mutex);
  54static DEFINE_SPINLOCK(lock);
  55static int timer_alive;
  56static int harddog_in_fd = -1;
  57static int harddog_out_fd = -1;
  58
  59/*
  60 *      Allow only one person to hold it open
  61 */
  62
  63extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
  64
  65static int harddog_open(struct inode *inode, struct file *file)
  66{
  67        int err = -EBUSY;
  68        char *sock = NULL;
  69
  70        mutex_lock(&harddog_mutex);
  71        spin_lock(&lock);
  72        if(timer_alive)
  73                goto err;
  74#ifdef CONFIG_WATCHDOG_NOWAYOUT
  75        __module_get(THIS_MODULE);
  76#endif
  77
  78#ifdef CONFIG_MCONSOLE
  79        sock = mconsole_notify_socket();
  80#endif
  81        err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock);
  82        if(err)
  83                goto err;
  84
  85        timer_alive = 1;
  86        spin_unlock(&lock);
  87        mutex_unlock(&harddog_mutex);
  88        return stream_open(inode, file);
  89err:
  90        spin_unlock(&lock);
  91        mutex_unlock(&harddog_mutex);
  92        return err;
  93}
  94
  95extern void stop_watchdog(int in_fd, int out_fd);
  96
  97static int harddog_release(struct inode *inode, struct file *file)
  98{
  99        /*
 100         *      Shut off the timer.
 101         */
 102
 103        spin_lock(&lock);
 104
 105        stop_watchdog(harddog_in_fd, harddog_out_fd);
 106        harddog_in_fd = -1;
 107        harddog_out_fd = -1;
 108
 109        timer_alive=0;
 110        spin_unlock(&lock);
 111
 112        return 0;
 113}
 114
 115extern int ping_watchdog(int fd);
 116
 117static ssize_t harddog_write(struct file *file, const char __user *data, size_t len,
 118                             loff_t *ppos)
 119{
 120        /*
 121         *      Refresh the timer.
 122         */
 123        if(len)
 124                return ping_watchdog(harddog_out_fd);
 125        return 0;
 126}
 127
 128static int harddog_ioctl_unlocked(struct file *file,
 129                                  unsigned int cmd, unsigned long arg)
 130{
 131        void __user *argp= (void __user *)arg;
 132        static struct watchdog_info ident = {
 133                WDIOC_SETTIMEOUT,
 134                0,
 135                "UML Hardware Watchdog"
 136        };
 137        switch (cmd) {
 138                default:
 139                        return -ENOTTY;
 140                case WDIOC_GETSUPPORT:
 141                        if(copy_to_user(argp, &ident, sizeof(ident)))
 142                                return -EFAULT;
 143                        return 0;
 144                case WDIOC_GETSTATUS:
 145                case WDIOC_GETBOOTSTATUS:
 146                        return put_user(0,(int __user *)argp);
 147                case WDIOC_KEEPALIVE:
 148                        return ping_watchdog(harddog_out_fd);
 149        }
 150}
 151
 152static long harddog_ioctl(struct file *file,
 153                          unsigned int cmd, unsigned long arg)
 154{
 155        long ret;
 156
 157        mutex_lock(&harddog_mutex);
 158        ret = harddog_ioctl_unlocked(file, cmd, arg);
 159        mutex_unlock(&harddog_mutex);
 160
 161        return ret;
 162}
 163
 164static const struct file_operations harddog_fops = {
 165        .owner          = THIS_MODULE,
 166        .write          = harddog_write,
 167        .unlocked_ioctl = harddog_ioctl,
 168        .compat_ioctl   = compat_ptr_ioctl,
 169        .open           = harddog_open,
 170        .release        = harddog_release,
 171        .llseek         = no_llseek,
 172};
 173
 174static struct miscdevice harddog_miscdev = {
 175        .minor          = WATCHDOG_MINOR,
 176        .name           = "watchdog",
 177        .fops           = &harddog_fops,
 178};
 179module_misc_device(harddog_miscdev);
 180