OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [softdog.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      SoftDog 0.05:   A Software Watchdog Device
3
 *
4
 *      (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
5
 *                              http://www.redhat.com
6
 *
7
 *      This program is free software; you can redistribute it and/or
8
 *      modify it under the terms of the GNU General Public License
9
 *      as published by the Free Software Foundation; either version
10
 *      2 of the License, or (at your option) any later version.
11
 *
12
 *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
13
 *      warranty for any of this software. This material is provided
14
 *      "AS-IS" and at no charge.
15
 *
16
 *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
17
 *
18
 *      Software only watchdog driver. Unlike its big brother the WDT501P
19
 *      driver this won't always recover a failed machine.
20
 *
21
 *  03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
22
 *      Modularised.
23
 *      Added soft_margin; use upon insmod to change the timer delay.
24
 *      NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
25
 *          minors.
26
 *
27
 *  19980911 Alan Cox
28
 *      Made SMP safe for 2.3.x
29
 *
30
 *  20011127 Joel Becker (jlbec@evilplan.org>
31
 *      Added soft_noboot; Allows testing the softdog trigger without
32
 *      requiring a recompile.
33
 *      Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
34
 *
35
 *  20020530 Joel Becker <joel.becker@oracle.com>
36
 *      Added Matt Domsch's nowayout module option.
37
 */
38
 
39
#include <linux/module.h>
40
#include <linux/config.h>
41
#include <linux/types.h>
42
#include <linux/kernel.h>
43
#include <linux/fs.h>
44
#include <linux/mm.h>
45
#include <linux/miscdevice.h>
46
#include <linux/watchdog.h>
47
#include <linux/reboot.h>
48
#include <linux/smp_lock.h>
49
#include <linux/init.h>
50
#include <asm/uaccess.h>
51
 
52
#define TIMER_MARGIN    60              /* (secs) Default is 1 minute */
53
 
54
static int expect_close = 0;
55
static int soft_margin = TIMER_MARGIN;  /* in seconds */
56
#ifdef ONLY_TESTING
57
static int soft_noboot = 1;
58
#else
59
static int soft_noboot = 0;
60
#endif  /* ONLY_TESTING */
61
 
62
MODULE_PARM(soft_margin,"i");
63
MODULE_PARM(soft_noboot,"i");
64
MODULE_LICENSE("GPL");
65
 
66
#ifdef CONFIG_WATCHDOG_NOWAYOUT
67
static int nowayout = 1;
68
#else
69
static int nowayout = 0;
70
#endif
71
 
72
MODULE_PARM(nowayout,"i");
73
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
74
 
75
/*
76
 *      Our timer
77
 */
78
 
79
static void watchdog_fire(unsigned long);
80
 
81
static struct timer_list watchdog_ticktock = {
82
        function:       watchdog_fire,
83
};
84
static unsigned long timer_alive;
85
 
86
 
87
/*
88
 *      If the timer expires..
89
 */
90
 
91
static void watchdog_fire(unsigned long data)
92
{
93
        if (soft_noboot)
94
                printk(KERN_CRIT "SOFTDOG: Triggered - Reboot ignored.\n");
95
        else
96
        {
97
                printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n");
98
                machine_restart(NULL);
99
                printk("SOFTDOG: Reboot didn't ?????\n");
100
        }
101
}
102
 
103
/*
104
 *      Allow only one person to hold it open
105
 */
106
 
107
static int softdog_open(struct inode *inode, struct file *file)
108
{
109
        if(test_and_set_bit(0, &timer_alive))
110
                return -EBUSY;
111
        if (nowayout) {
112
                MOD_INC_USE_COUNT;
113
        }
114
        /*
115
         *      Activate timer
116
         */
117
        mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
118
        return 0;
119
}
120
 
121
static int softdog_release(struct inode *inode, struct file *file)
122
{
123
        /*
124
         *      Shut off the timer.
125
         *      Lock it in if it's a module and we set nowayout
126
         */
127
        if (expect_close || nowayout == 0) {
128
                del_timer(&watchdog_ticktock);
129
        } else {
130
                printk(KERN_CRIT "SOFTDOG: WDT device closed unexpectedly.  WDT will not stop!\n");
131
        }
132
        clear_bit(0, &timer_alive);
133
        return 0;
134
}
135
 
136
static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
137
{
138
        /*  Can't seek (pwrite) on this device  */
139
        if (ppos != &file->f_pos)
140
                return -ESPIPE;
141
 
142
        /*
143
         *      Refresh the timer.
144
         */
145
        if(len) {
146
                if (!nowayout) {
147
                        size_t i;
148
 
149
                        /* In case it was set long ago */
150
                        expect_close = 0;
151
 
152
                        for (i = 0; i != len; i++) {
153
                                char c;
154
                                if (get_user(c, data + i))
155
                                        return -EFAULT;
156
                                if (c == 'V')
157
                                        expect_close = 1;
158
                        }
159
                }
160
                mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
161
                return 1;
162
        }
163
        return 0;
164
}
165
 
166
static int softdog_ioctl(struct inode *inode, struct file *file,
167
        unsigned int cmd, unsigned long arg)
168
{
169
        int new_margin;
170
        static struct watchdog_info ident = {
171
                WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
172
                0,
173
                "Software Watchdog"
174
        };
175
        switch (cmd) {
176
                default:
177
                        return -ENOTTY;
178
                case WDIOC_GETSUPPORT:
179
                        if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
180
                                return -EFAULT;
181
                        return 0;
182
                case WDIOC_GETSTATUS:
183
                case WDIOC_GETBOOTSTATUS:
184
                        return put_user(0,(int *)arg);
185
                case WDIOC_KEEPALIVE:
186
                        mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
187
                        return 0;
188
                case WDIOC_SETTIMEOUT:
189
                        if (get_user(new_margin, (int *)arg))
190
                                return -EFAULT;
191
                        if (new_margin < 1)
192
                                return -EINVAL;
193
                        soft_margin = new_margin;
194
                        mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
195
                        /* Fall */
196
                case WDIOC_GETTIMEOUT:
197
                        return put_user(soft_margin, (int *)arg);
198
        }
199
}
200
 
201
static struct file_operations softdog_fops = {
202
        owner:          THIS_MODULE,
203
        write:          softdog_write,
204
        ioctl:          softdog_ioctl,
205
        open:           softdog_open,
206
        release:        softdog_release,
207
};
208
 
209
static struct miscdevice softdog_miscdev = {
210
        minor:          WATCHDOG_MINOR,
211
        name:           "watchdog",
212
        fops:           &softdog_fops,
213
};
214
 
215
static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n";
216
 
217
static int __init watchdog_init(void)
218
{
219
        int ret;
220
 
221
        ret = misc_register(&softdog_miscdev);
222
 
223
        if (ret)
224
                return ret;
225
 
226
        printk(banner, soft_margin);
227
 
228
        return 0;
229
}
230
 
231
static void __exit watchdog_exit(void)
232
{
233
        misc_deregister(&softdog_miscdev);
234
}
235
 
236
module_init(watchdog_init);
237
module_exit(watchdog_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.