diff options
Diffstat (limited to 'drivers/watchdog/machzwd.c')
-rw-r--r-- | drivers/watchdog/machzwd.c | 108 |
1 files changed, 40 insertions, 68 deletions
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 6905135a776c..2dfc27559bf7 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c | |||
@@ -40,9 +40,9 @@ | |||
40 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
41 | #include <linux/reboot.h> | 41 | #include <linux/reboot.h> |
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/io.h> | ||
44 | #include <linux/uaccess.h> | ||
43 | 45 | ||
44 | #include <asm/io.h> | ||
45 | #include <asm/uaccess.h> | ||
46 | #include <asm/system.h> | 46 | #include <asm/system.h> |
47 | 47 | ||
48 | /* ports */ | 48 | /* ports */ |
@@ -95,7 +95,9 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | |||
95 | 95 | ||
96 | static int nowayout = WATCHDOG_NOWAYOUT; | 96 | static int nowayout = WATCHDOG_NOWAYOUT; |
97 | module_param(nowayout, int, 0); | 97 | module_param(nowayout, int, 0); |
98 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 98 | MODULE_PARM_DESC(nowayout, |
99 | "Watchdog cannot be stopped once started (default=" | ||
100 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
99 | 101 | ||
100 | #define PFX "machzwd" | 102 | #define PFX "machzwd" |
101 | 103 | ||
@@ -114,7 +116,7 @@ static struct watchdog_info zf_info = { | |||
114 | * 3 = GEN_SCI | 116 | * 3 = GEN_SCI |
115 | * defaults to GEN_RESET (0) | 117 | * defaults to GEN_RESET (0) |
116 | */ | 118 | */ |
117 | static int action = 0; | 119 | static int action; |
118 | module_param(action, int, 0); | 120 | module_param(action, int, 0); |
119 | MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); | 121 | MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); |
120 | 122 | ||
@@ -123,10 +125,9 @@ static void zf_ping(unsigned long data); | |||
123 | static int zf_action = GEN_RESET; | 125 | static int zf_action = GEN_RESET; |
124 | static unsigned long zf_is_open; | 126 | static unsigned long zf_is_open; |
125 | static char zf_expect_close; | 127 | static char zf_expect_close; |
126 | static DEFINE_SPINLOCK(zf_lock); | ||
127 | static DEFINE_SPINLOCK(zf_port_lock); | 128 | static DEFINE_SPINLOCK(zf_port_lock); |
128 | static DEFINE_TIMER(zf_timer, zf_ping, 0, 0); | 129 | static DEFINE_TIMER(zf_timer, zf_ping, 0, 0); |
129 | static unsigned long next_heartbeat = 0; | 130 | static unsigned long next_heartbeat; |
130 | 131 | ||
131 | 132 | ||
132 | /* timeout for user land heart beat (10 seconds) */ | 133 | /* timeout for user land heart beat (10 seconds) */ |
@@ -171,13 +172,13 @@ static inline void zf_set_control(unsigned short new) | |||
171 | 172 | ||
172 | static inline void zf_set_timer(unsigned short new, unsigned char n) | 173 | static inline void zf_set_timer(unsigned short new, unsigned char n) |
173 | { | 174 | { |
174 | switch(n){ | 175 | switch (n) { |
175 | case WD1: | 176 | case WD1: |
176 | zf_writew(COUNTER_1, new); | 177 | zf_writew(COUNTER_1, new); |
177 | case WD2: | 178 | case WD2: |
178 | zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); | 179 | zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); |
179 | default: | 180 | default: |
180 | return; | 181 | return; |
181 | } | 182 | } |
182 | } | 183 | } |
183 | 184 | ||
@@ -241,10 +242,8 @@ static void zf_ping(unsigned long data) | |||
241 | 242 | ||
242 | zf_writeb(COUNTER_2, 0xff); | 243 | zf_writeb(COUNTER_2, 0xff); |
243 | 244 | ||
244 | if(time_before(jiffies, next_heartbeat)){ | 245 | if (time_before(jiffies, next_heartbeat)) { |
245 | |||
246 | dprintk("time_before: %ld\n", next_heartbeat - jiffies); | 246 | dprintk("time_before: %ld\n", next_heartbeat - jiffies); |
247 | |||
248 | /* | 247 | /* |
249 | * reset event is activated by transition from 0 to 1 on | 248 | * reset event is activated by transition from 0 to 1 on |
250 | * RESET_WD1 bit and we assume that it is already zero... | 249 | * RESET_WD1 bit and we assume that it is already zero... |
@@ -261,24 +260,21 @@ static void zf_ping(unsigned long data) | |||
261 | spin_unlock_irqrestore(&zf_port_lock, flags); | 260 | spin_unlock_irqrestore(&zf_port_lock, flags); |
262 | 261 | ||
263 | mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO); | 262 | mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO); |
264 | }else{ | 263 | } else |
265 | printk(KERN_CRIT PFX ": I will reset your machine\n"); | 264 | printk(KERN_CRIT PFX ": I will reset your machine\n"); |
266 | } | ||
267 | } | 265 | } |
268 | 266 | ||
269 | static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, | 267 | static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, |
270 | loff_t *ppos) | 268 | loff_t *ppos) |
271 | { | 269 | { |
272 | /* See if we got the magic character */ | 270 | /* See if we got the magic character */ |
273 | if(count){ | 271 | if (count) { |
274 | |||
275 | /* | 272 | /* |
276 | * no need to check for close confirmation | 273 | * no need to check for close confirmation |
277 | * no way to disable watchdog ;) | 274 | * no way to disable watchdog ;) |
278 | */ | 275 | */ |
279 | if (!nowayout) { | 276 | if (!nowayout) { |
280 | size_t ofs; | 277 | size_t ofs; |
281 | |||
282 | /* | 278 | /* |
283 | * note: just in case someone wrote the magic character | 279 | * note: just in case someone wrote the magic character |
284 | * five months ago... | 280 | * five months ago... |
@@ -286,11 +282,11 @@ static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, | |||
286 | zf_expect_close = 0; | 282 | zf_expect_close = 0; |
287 | 283 | ||
288 | /* now scan */ | 284 | /* now scan */ |
289 | for (ofs = 0; ofs != count; ofs++){ | 285 | for (ofs = 0; ofs != count; ofs++) { |
290 | char c; | 286 | char c; |
291 | if (get_user(c, buf + ofs)) | 287 | if (get_user(c, buf + ofs)) |
292 | return -EFAULT; | 288 | return -EFAULT; |
293 | if (c == 'V'){ | 289 | if (c == 'V') { |
294 | zf_expect_close = 42; | 290 | zf_expect_close = 42; |
295 | dprintk("zf_expect_close = 42\n"); | 291 | dprintk("zf_expect_close = 42\n"); |
296 | } | 292 | } |
@@ -303,14 +299,11 @@ static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, | |||
303 | */ | 299 | */ |
304 | next_heartbeat = jiffies + ZF_USER_TIMEO; | 300 | next_heartbeat = jiffies + ZF_USER_TIMEO; |
305 | dprintk("user ping at %ld\n", jiffies); | 301 | dprintk("user ping at %ld\n", jiffies); |
306 | |||
307 | } | 302 | } |
308 | |||
309 | return count; | 303 | return count; |
310 | } | 304 | } |
311 | 305 | ||
312 | static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 306 | static long zf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
313 | unsigned long arg) | ||
314 | { | 307 | { |
315 | void __user *argp = (void __user *)arg; | 308 | void __user *argp = (void __user *)arg; |
316 | int __user *p = argp; | 309 | int __user *p = argp; |
@@ -319,55 +312,38 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
319 | if (copy_to_user(argp, &zf_info, sizeof(zf_info))) | 312 | if (copy_to_user(argp, &zf_info, sizeof(zf_info))) |
320 | return -EFAULT; | 313 | return -EFAULT; |
321 | break; | 314 | break; |
322 | |||
323 | case WDIOC_GETSTATUS: | 315 | case WDIOC_GETSTATUS: |
324 | case WDIOC_GETBOOTSTATUS: | 316 | case WDIOC_GETBOOTSTATUS: |
325 | return put_user(0, p); | 317 | return put_user(0, p); |
326 | |||
327 | case WDIOC_KEEPALIVE: | 318 | case WDIOC_KEEPALIVE: |
328 | zf_ping(0); | 319 | zf_ping(0); |
329 | break; | 320 | break; |
330 | |||
331 | default: | 321 | default: |
332 | return -ENOTTY; | 322 | return -ENOTTY; |
333 | } | 323 | } |
334 | |||
335 | return 0; | 324 | return 0; |
336 | } | 325 | } |
337 | 326 | ||
338 | static int zf_open(struct inode *inode, struct file *file) | 327 | static int zf_open(struct inode *inode, struct file *file) |
339 | { | 328 | { |
340 | spin_lock(&zf_lock); | 329 | if (test_and_set_bit(0, &zf_is_open)) |
341 | if(test_and_set_bit(0, &zf_is_open)) { | ||
342 | spin_unlock(&zf_lock); | ||
343 | return -EBUSY; | 330 | return -EBUSY; |
344 | } | ||
345 | |||
346 | if (nowayout) | 331 | if (nowayout) |
347 | __module_get(THIS_MODULE); | 332 | __module_get(THIS_MODULE); |
348 | |||
349 | spin_unlock(&zf_lock); | ||
350 | |||
351 | zf_timer_on(); | 333 | zf_timer_on(); |
352 | |||
353 | return nonseekable_open(inode, file); | 334 | return nonseekable_open(inode, file); |
354 | } | 335 | } |
355 | 336 | ||
356 | static int zf_close(struct inode *inode, struct file *file) | 337 | static int zf_close(struct inode *inode, struct file *file) |
357 | { | 338 | { |
358 | if(zf_expect_close == 42){ | 339 | if (zf_expect_close == 42) |
359 | zf_timer_off(); | 340 | zf_timer_off(); |
360 | } else { | 341 | else { |
361 | del_timer(&zf_timer); | 342 | del_timer(&zf_timer); |
362 | printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); | 343 | printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); |
363 | } | 344 | } |
364 | |||
365 | spin_lock(&zf_lock); | ||
366 | clear_bit(0, &zf_is_open); | 345 | clear_bit(0, &zf_is_open); |
367 | spin_unlock(&zf_lock); | ||
368 | |||
369 | zf_expect_close = 0; | 346 | zf_expect_close = 0; |
370 | |||
371 | return 0; | 347 | return 0; |
372 | } | 348 | } |
373 | 349 | ||
@@ -378,23 +354,18 @@ static int zf_close(struct inode *inode, struct file *file) | |||
378 | static int zf_notify_sys(struct notifier_block *this, unsigned long code, | 354 | static int zf_notify_sys(struct notifier_block *this, unsigned long code, |
379 | void *unused) | 355 | void *unused) |
380 | { | 356 | { |
381 | if(code == SYS_DOWN || code == SYS_HALT){ | 357 | if (code == SYS_DOWN || code == SYS_HALT) |
382 | zf_timer_off(); | 358 | zf_timer_off(); |
383 | } | ||
384 | |||
385 | return NOTIFY_DONE; | 359 | return NOTIFY_DONE; |
386 | } | 360 | } |
387 | 361 | ||
388 | |||
389 | |||
390 | |||
391 | static const struct file_operations zf_fops = { | 362 | static const struct file_operations zf_fops = { |
392 | .owner = THIS_MODULE, | 363 | .owner = THIS_MODULE, |
393 | .llseek = no_llseek, | 364 | .llseek = no_llseek, |
394 | .write = zf_write, | 365 | .write = zf_write, |
395 | .ioctl = zf_ioctl, | 366 | .unlocked_ioctl = zf_ioctl, |
396 | .open = zf_open, | 367 | .open = zf_open, |
397 | .release = zf_close, | 368 | .release = zf_close, |
398 | }; | 369 | }; |
399 | 370 | ||
400 | static struct miscdevice zf_miscdev = { | 371 | static struct miscdevice zf_miscdev = { |
@@ -402,7 +373,7 @@ static struct miscdevice zf_miscdev = { | |||
402 | .name = "watchdog", | 373 | .name = "watchdog", |
403 | .fops = &zf_fops, | 374 | .fops = &zf_fops, |
404 | }; | 375 | }; |
405 | 376 | ||
406 | 377 | ||
407 | /* | 378 | /* |
408 | * The device needs to learn about soft shutdowns in order to | 379 | * The device needs to learn about soft shutdowns in order to |
@@ -423,22 +394,23 @@ static int __init zf_init(void) | |||
423 | { | 394 | { |
424 | int ret; | 395 | int ret; |
425 | 396 | ||
426 | printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n"); | 397 | printk(KERN_INFO PFX |
398 | ": MachZ ZF-Logic Watchdog driver initializing.\n"); | ||
427 | 399 | ||
428 | ret = zf_get_ZFL_version(); | 400 | ret = zf_get_ZFL_version(); |
429 | if ((!ret) || (ret == 0xffff)) { | 401 | if (!ret || ret == 0xffff) { |
430 | printk(KERN_WARNING PFX ": no ZF-Logic found\n"); | 402 | printk(KERN_WARNING PFX ": no ZF-Logic found\n"); |
431 | return -ENODEV; | 403 | return -ENODEV; |
432 | } | 404 | } |
433 | 405 | ||
434 | if((action <= 3) && (action >= 0)){ | 406 | if (action <= 3 && action >= 0) |
435 | zf_action = zf_action>>action; | 407 | zf_action = zf_action >> action; |
436 | } else | 408 | else |
437 | action = 0; | 409 | action = 0; |
438 | 410 | ||
439 | zf_show_action(action); | 411 | zf_show_action(action); |
440 | 412 | ||
441 | if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ | 413 | if (!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")) { |
442 | printk(KERN_ERR "cannot reserve I/O ports at %d\n", | 414 | printk(KERN_ERR "cannot reserve I/O ports at %d\n", |
443 | ZF_IOBASE); | 415 | ZF_IOBASE); |
444 | ret = -EBUSY; | 416 | ret = -EBUSY; |
@@ -446,14 +418,14 @@ static int __init zf_init(void) | |||
446 | } | 418 | } |
447 | 419 | ||
448 | ret = register_reboot_notifier(&zf_notifier); | 420 | ret = register_reboot_notifier(&zf_notifier); |
449 | if(ret){ | 421 | if (ret) { |
450 | printk(KERN_ERR "can't register reboot notifier (err=%d)\n", | 422 | printk(KERN_ERR "can't register reboot notifier (err=%d)\n", |
451 | ret); | 423 | ret); |
452 | goto no_reboot; | 424 | goto no_reboot; |
453 | } | 425 | } |
454 | 426 | ||
455 | ret = misc_register(&zf_miscdev); | 427 | ret = misc_register(&zf_miscdev); |
456 | if (ret){ | 428 | if (ret) { |
457 | printk(KERN_ERR "can't misc_register on minor=%d\n", | 429 | printk(KERN_ERR "can't misc_register on minor=%d\n", |
458 | WATCHDOG_MINOR); | 430 | WATCHDOG_MINOR); |
459 | goto no_misc; | 431 | goto no_misc; |