Commit 8561b089afbaed2651591e5a4574fdca451d82f2
Exists in
master
and in
7 other branches
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog: [WATCHDOG] constify function pointer tables [WATCHDOG] TXx9 watchdog driver [WATCHDOG] misc_register patch [WATCHDOG] wdt: fix locking
Showing 16 changed files Side-by-side Diff
- drivers/watchdog/Kconfig
- drivers/watchdog/Makefile
- drivers/watchdog/alim1535_wdt.c
- drivers/watchdog/alim7101_wdt.c
- drivers/watchdog/ar7_wdt.c
- drivers/watchdog/bfin_wdt.c
- drivers/watchdog/it8712f_wdt.c
- drivers/watchdog/mpc5200_wdt.c
- drivers/watchdog/mtx-1_wdt.c
- drivers/watchdog/sbc60xxwdt.c
- drivers/watchdog/scx200_wdt.c
- drivers/watchdog/txx9wdt.c
- drivers/watchdog/w83877f_wdt.c
- drivers/watchdog/w83977f_wdt.c
- drivers/watchdog/wdt.c
- drivers/watchdog/wdt977.c
drivers/watchdog/Kconfig
... | ... | @@ -639,6 +639,12 @@ |
639 | 639 | help |
640 | 640 | Hardware driver for the TI AR7 Watchdog Timer. |
641 | 641 | |
642 | +config TXX9_WDT | |
643 | + tristate "Toshiba TXx9 Watchdog Timer" | |
644 | + depends on CPU_TX39XX || CPU_TX49XX | |
645 | + help | |
646 | + Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. | |
647 | + | |
642 | 648 | # PARISC Architecture |
643 | 649 | |
644 | 650 | # POWERPC Architecture |
drivers/watchdog/Makefile
drivers/watchdog/alim1535_wdt.c
... | ... | @@ -413,18 +413,18 @@ |
413 | 413 | /* Calculate the watchdog's timeout */ |
414 | 414 | ali_settimer(timeout); |
415 | 415 | |
416 | - ret = misc_register(&ali_miscdev); | |
416 | + ret = register_reboot_notifier(&ali_notifier); | |
417 | 417 | if (ret != 0) { |
418 | - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
419 | - WATCHDOG_MINOR, ret); | |
418 | + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
419 | + ret); | |
420 | 420 | goto out; |
421 | 421 | } |
422 | 422 | |
423 | - ret = register_reboot_notifier(&ali_notifier); | |
423 | + ret = misc_register(&ali_miscdev); | |
424 | 424 | if (ret != 0) { |
425 | - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
426 | - ret); | |
427 | - goto unreg_miscdev; | |
425 | + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
426 | + WATCHDOG_MINOR, ret); | |
427 | + goto unreg_reboot; | |
428 | 428 | } |
429 | 429 | |
430 | 430 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", |
... | ... | @@ -432,8 +432,8 @@ |
432 | 432 | |
433 | 433 | out: |
434 | 434 | return ret; |
435 | -unreg_miscdev: | |
436 | - misc_deregister(&ali_miscdev); | |
435 | +unreg_reboot: | |
436 | + unregister_reboot_notifier(&ali_notifier); | |
437 | 437 | goto out; |
438 | 438 | } |
439 | 439 | |
440 | 440 | |
... | ... | @@ -449,8 +449,8 @@ |
449 | 449 | ali_stop(); |
450 | 450 | |
451 | 451 | /* Deregister */ |
452 | - unregister_reboot_notifier(&ali_notifier); | |
453 | 452 | misc_deregister(&ali_miscdev); |
453 | + unregister_reboot_notifier(&ali_notifier); | |
454 | 454 | pci_dev_put(ali_pci); |
455 | 455 | } |
456 | 456 |
drivers/watchdog/alim7101_wdt.c
... | ... | @@ -377,18 +377,18 @@ |
377 | 377 | timeout); |
378 | 378 | } |
379 | 379 | |
380 | - rc = misc_register(&wdt_miscdev); | |
380 | + rc = register_reboot_notifier(&wdt_notifier); | |
381 | 381 | if (rc) { |
382 | - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
383 | - wdt_miscdev.minor, rc); | |
382 | + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
383 | + rc); | |
384 | 384 | goto err_out; |
385 | 385 | } |
386 | 386 | |
387 | - rc = register_reboot_notifier(&wdt_notifier); | |
387 | + rc = misc_register(&wdt_miscdev); | |
388 | 388 | if (rc) { |
389 | - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
390 | - rc); | |
391 | - goto err_out_miscdev; | |
389 | + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
390 | + wdt_miscdev.minor, rc); | |
391 | + goto err_out_reboot; | |
392 | 392 | } |
393 | 393 | |
394 | 394 | if (nowayout) { |
... | ... | @@ -399,8 +399,8 @@ |
399 | 399 | timeout, nowayout); |
400 | 400 | return 0; |
401 | 401 | |
402 | -err_out_miscdev: | |
403 | - misc_deregister(&wdt_miscdev); | |
402 | +err_out_reboot: | |
403 | + unregister_reboot_notifier(&wdt_notifier); | |
404 | 404 | err_out: |
405 | 405 | pci_dev_put(alim7101_pmu); |
406 | 406 | return rc; |
drivers/watchdog/ar7_wdt.c
drivers/watchdog/bfin_wdt.c
drivers/watchdog/it8712f_wdt.c
drivers/watchdog/mpc5200_wdt.c
drivers/watchdog/mtx-1_wdt.c
drivers/watchdog/sbc60xxwdt.c
... | ... | @@ -359,20 +359,20 @@ |
359 | 359 | } |
360 | 360 | } |
361 | 361 | |
362 | - rc = misc_register(&wdt_miscdev); | |
362 | + rc = register_reboot_notifier(&wdt_notifier); | |
363 | 363 | if (rc) |
364 | 364 | { |
365 | - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
366 | - wdt_miscdev.minor, rc); | |
365 | + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
366 | + rc); | |
367 | 367 | goto err_out_region2; |
368 | 368 | } |
369 | 369 | |
370 | - rc = register_reboot_notifier(&wdt_notifier); | |
370 | + rc = misc_register(&wdt_miscdev); | |
371 | 371 | if (rc) |
372 | 372 | { |
373 | - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
374 | - rc); | |
375 | - goto err_out_miscdev; | |
373 | + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
374 | + wdt_miscdev.minor, rc); | |
375 | + goto err_out_reboot; | |
376 | 376 | } |
377 | 377 | |
378 | 378 | printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", |
... | ... | @@ -380,8 +380,8 @@ |
380 | 380 | |
381 | 381 | return 0; |
382 | 382 | |
383 | -err_out_miscdev: | |
384 | - misc_deregister(&wdt_miscdev); | |
383 | +err_out_reboot: | |
384 | + unregister_reboot_notifier(&wdt_notifier); | |
385 | 385 | err_out_region2: |
386 | 386 | if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) |
387 | 387 | release_region(wdt_stop,1); |
drivers/watchdog/scx200_wdt.c
... | ... | @@ -231,17 +231,17 @@ |
231 | 231 | |
232 | 232 | sema_init(&open_semaphore, 1); |
233 | 233 | |
234 | - r = misc_register(&scx200_wdt_miscdev); | |
234 | + r = register_reboot_notifier(&scx200_wdt_notifier); | |
235 | 235 | if (r) { |
236 | + printk(KERN_ERR NAME ": unable to register reboot notifier"); | |
236 | 237 | release_region(scx200_cb_base + SCx200_WDT_OFFSET, |
237 | 238 | SCx200_WDT_SIZE); |
238 | 239 | return r; |
239 | 240 | } |
240 | 241 | |
241 | - r = register_reboot_notifier(&scx200_wdt_notifier); | |
242 | + r = misc_register(&scx200_wdt_miscdev); | |
242 | 243 | if (r) { |
243 | - printk(KERN_ERR NAME ": unable to register reboot notifier"); | |
244 | - misc_deregister(&scx200_wdt_miscdev); | |
244 | + unregister_reboot_notifier(&scx200_wdt_notifier); | |
245 | 245 | release_region(scx200_cb_base + SCx200_WDT_OFFSET, |
246 | 246 | SCx200_WDT_SIZE); |
247 | 247 | return r; |
248 | 248 | |
... | ... | @@ -252,8 +252,8 @@ |
252 | 252 | |
253 | 253 | static void __exit scx200_wdt_cleanup(void) |
254 | 254 | { |
255 | - unregister_reboot_notifier(&scx200_wdt_notifier); | |
256 | 255 | misc_deregister(&scx200_wdt_miscdev); |
256 | + unregister_reboot_notifier(&scx200_wdt_notifier); | |
257 | 257 | release_region(scx200_cb_base + SCx200_WDT_OFFSET, |
258 | 258 | SCx200_WDT_SIZE); |
259 | 259 | } |
drivers/watchdog/txx9wdt.c
1 | +/* | |
2 | + * txx9wdt: A Hardware Watchdog Driver for TXx9 SoCs | |
3 | + * | |
4 | + * Copyright (C) 2007 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or modify | |
7 | + * it under the terms of the GNU General Public License version 2 as | |
8 | + * published by the Free Software Foundation. | |
9 | + */ | |
10 | +#include <linux/module.h> | |
11 | +#include <linux/moduleparam.h> | |
12 | +#include <linux/types.h> | |
13 | +#include <linux/miscdevice.h> | |
14 | +#include <linux/watchdog.h> | |
15 | +#include <linux/fs.h> | |
16 | +#include <linux/reboot.h> | |
17 | +#include <linux/init.h> | |
18 | +#include <linux/uaccess.h> | |
19 | +#include <linux/platform_device.h> | |
20 | +#include <linux/clk.h> | |
21 | +#include <linux/err.h> | |
22 | +#include <linux/io.h> | |
23 | +#include <asm/txx9tmr.h> | |
24 | + | |
25 | +#define TIMER_MARGIN 60 /* Default is 60 seconds */ | |
26 | + | |
27 | +static int timeout = TIMER_MARGIN; /* in seconds */ | |
28 | +module_param(timeout, int, 0); | |
29 | +MODULE_PARM_DESC(timeout, | |
30 | + "Watchdog timeout in seconds. " | |
31 | + "(0<timeout<((2^" __MODULE_STRING(TXX9_TIMER_BITS) ")/(IMCLK/256)), " | |
32 | + "default=" __MODULE_STRING(TIMER_MARGIN) ")"); | |
33 | + | |
34 | +static int nowayout = WATCHDOG_NOWAYOUT; | |
35 | +module_param(nowayout, int, 0); | |
36 | +MODULE_PARM_DESC(nowayout, | |
37 | + "Watchdog cannot be stopped once started " | |
38 | + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | |
39 | + | |
40 | +#define WD_TIMER_CCD 7 /* 1/256 */ | |
41 | +#define WD_TIMER_CLK (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD)) | |
42 | +#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK) | |
43 | + | |
44 | +static unsigned long txx9wdt_alive; | |
45 | +static int expect_close; | |
46 | +static struct txx9_tmr_reg __iomem *txx9wdt_reg; | |
47 | +static struct clk *txx9_imclk; | |
48 | + | |
49 | +static void txx9wdt_ping(void) | |
50 | +{ | |
51 | + __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); | |
52 | +} | |
53 | + | |
54 | +static void txx9wdt_start(void) | |
55 | +{ | |
56 | + __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra); | |
57 | + __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr); | |
58 | + __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */ | |
59 | + __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, | |
60 | + &txx9wdt_reg->tcr); | |
61 | + __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); | |
62 | +} | |
63 | + | |
64 | +static void txx9wdt_stop(void) | |
65 | +{ | |
66 | + __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr); | |
67 | + __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE, | |
68 | + &txx9wdt_reg->tcr); | |
69 | +} | |
70 | + | |
71 | +static int txx9wdt_open(struct inode *inode, struct file *file) | |
72 | +{ | |
73 | + if (test_and_set_bit(0, &txx9wdt_alive)) | |
74 | + return -EBUSY; | |
75 | + | |
76 | + if (__raw_readl(&txx9wdt_reg->tcr) & TXx9_TMTCR_TCE) { | |
77 | + clear_bit(0, &txx9wdt_alive); | |
78 | + return -EBUSY; | |
79 | + } | |
80 | + | |
81 | + if (nowayout) | |
82 | + __module_get(THIS_MODULE); | |
83 | + | |
84 | + txx9wdt_start(); | |
85 | + return nonseekable_open(inode, file); | |
86 | +} | |
87 | + | |
88 | +static int txx9wdt_release(struct inode *inode, struct file *file) | |
89 | +{ | |
90 | + if (expect_close) | |
91 | + txx9wdt_stop(); | |
92 | + else { | |
93 | + printk(KERN_CRIT "txx9wdt: " | |
94 | + "Unexpected close, not stopping watchdog!\n"); | |
95 | + txx9wdt_ping(); | |
96 | + } | |
97 | + clear_bit(0, &txx9wdt_alive); | |
98 | + expect_close = 0; | |
99 | + return 0; | |
100 | +} | |
101 | + | |
102 | +static ssize_t txx9wdt_write(struct file *file, const char __user *data, | |
103 | + size_t len, loff_t *ppos) | |
104 | +{ | |
105 | + if (len) { | |
106 | + if (!nowayout) { | |
107 | + size_t i; | |
108 | + | |
109 | + expect_close = 0; | |
110 | + for (i = 0; i != len; i++) { | |
111 | + char c; | |
112 | + if (get_user(c, data + i)) | |
113 | + return -EFAULT; | |
114 | + if (c == 'V') | |
115 | + expect_close = 1; | |
116 | + } | |
117 | + } | |
118 | + txx9wdt_ping(); | |
119 | + } | |
120 | + return len; | |
121 | +} | |
122 | + | |
123 | +static int txx9wdt_ioctl(struct inode *inode, struct file *file, | |
124 | + unsigned int cmd, unsigned long arg) | |
125 | +{ | |
126 | + void __user *argp = (void __user *)arg; | |
127 | + int __user *p = argp; | |
128 | + int new_timeout; | |
129 | + static struct watchdog_info ident = { | |
130 | + .options = WDIOF_SETTIMEOUT | | |
131 | + WDIOF_KEEPALIVEPING | | |
132 | + WDIOF_MAGICCLOSE, | |
133 | + .firmware_version = 0, | |
134 | + .identity = "Hardware Watchdog for TXx9", | |
135 | + }; | |
136 | + | |
137 | + switch (cmd) { | |
138 | + default: | |
139 | + return -ENOTTY; | |
140 | + case WDIOC_GETSUPPORT: | |
141 | + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | |
142 | + case WDIOC_GETSTATUS: | |
143 | + case WDIOC_GETBOOTSTATUS: | |
144 | + return put_user(0, p); | |
145 | + case WDIOC_KEEPALIVE: | |
146 | + txx9wdt_ping(); | |
147 | + return 0; | |
148 | + case WDIOC_SETTIMEOUT: | |
149 | + if (get_user(new_timeout, p)) | |
150 | + return -EFAULT; | |
151 | + if (new_timeout < 1 || new_timeout > WD_MAX_TIMEOUT) | |
152 | + return -EINVAL; | |
153 | + timeout = new_timeout; | |
154 | + txx9wdt_stop(); | |
155 | + txx9wdt_start(); | |
156 | + /* Fall */ | |
157 | + case WDIOC_GETTIMEOUT: | |
158 | + return put_user(timeout, p); | |
159 | + } | |
160 | +} | |
161 | + | |
162 | +static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code, | |
163 | + void *unused) | |
164 | +{ | |
165 | + if (code == SYS_DOWN || code == SYS_HALT) | |
166 | + txx9wdt_stop(); | |
167 | + return NOTIFY_DONE; | |
168 | +} | |
169 | + | |
170 | +static const struct file_operations txx9wdt_fops = { | |
171 | + .owner = THIS_MODULE, | |
172 | + .llseek = no_llseek, | |
173 | + .write = txx9wdt_write, | |
174 | + .ioctl = txx9wdt_ioctl, | |
175 | + .open = txx9wdt_open, | |
176 | + .release = txx9wdt_release, | |
177 | +}; | |
178 | + | |
179 | +static struct miscdevice txx9wdt_miscdev = { | |
180 | + .minor = WATCHDOG_MINOR, | |
181 | + .name = "watchdog", | |
182 | + .fops = &txx9wdt_fops, | |
183 | +}; | |
184 | + | |
185 | +static struct notifier_block txx9wdt_notifier = { | |
186 | + .notifier_call = txx9wdt_notify_sys | |
187 | +}; | |
188 | + | |
189 | +static int __init txx9wdt_probe(struct platform_device *dev) | |
190 | +{ | |
191 | + struct resource *res; | |
192 | + int ret; | |
193 | + | |
194 | + txx9_imclk = clk_get(NULL, "imbus_clk"); | |
195 | + if (IS_ERR(txx9_imclk)) { | |
196 | + ret = PTR_ERR(txx9_imclk); | |
197 | + txx9_imclk = NULL; | |
198 | + goto exit; | |
199 | + } | |
200 | + ret = clk_enable(txx9_imclk); | |
201 | + if (ret) { | |
202 | + clk_put(txx9_imclk); | |
203 | + txx9_imclk = NULL; | |
204 | + goto exit; | |
205 | + } | |
206 | + | |
207 | + res = platform_get_resource(dev, IORESOURCE_MEM, 0); | |
208 | + if (!res) | |
209 | + goto exit_busy; | |
210 | + if (!devm_request_mem_region(&dev->dev, | |
211 | + res->start, res->end - res->start + 1, | |
212 | + "txx9wdt")) | |
213 | + goto exit_busy; | |
214 | + txx9wdt_reg = devm_ioremap(&dev->dev, | |
215 | + res->start, res->end - res->start + 1); | |
216 | + if (!txx9wdt_reg) | |
217 | + goto exit_busy; | |
218 | + | |
219 | + ret = register_reboot_notifier(&txx9wdt_notifier); | |
220 | + if (ret) | |
221 | + goto exit; | |
222 | + | |
223 | + ret = misc_register(&txx9wdt_miscdev); | |
224 | + if (ret) { | |
225 | + unregister_reboot_notifier(&txx9wdt_notifier); | |
226 | + goto exit; | |
227 | + } | |
228 | + | |
229 | + printk(KERN_INFO "Hardware Watchdog Timer for TXx9: " | |
230 | + "timeout=%d sec (max %ld) (nowayout= %d)\n", | |
231 | + timeout, WD_MAX_TIMEOUT, nowayout); | |
232 | + | |
233 | + return 0; | |
234 | +exit_busy: | |
235 | + ret = -EBUSY; | |
236 | +exit: | |
237 | + if (txx9_imclk) { | |
238 | + clk_disable(txx9_imclk); | |
239 | + clk_put(txx9_imclk); | |
240 | + } | |
241 | + return ret; | |
242 | +} | |
243 | + | |
244 | +static int __exit txx9wdt_remove(struct platform_device *dev) | |
245 | +{ | |
246 | + misc_deregister(&txx9wdt_miscdev); | |
247 | + unregister_reboot_notifier(&txx9wdt_notifier); | |
248 | + clk_disable(txx9_imclk); | |
249 | + clk_put(txx9_imclk); | |
250 | + return 0; | |
251 | +} | |
252 | + | |
253 | +static struct platform_driver txx9wdt_driver = { | |
254 | + .remove = __exit_p(txx9wdt_remove), | |
255 | + .driver = { | |
256 | + .name = "txx9wdt", | |
257 | + .owner = THIS_MODULE, | |
258 | + }, | |
259 | +}; | |
260 | + | |
261 | +static int __init watchdog_init(void) | |
262 | +{ | |
263 | + return platform_driver_probe(&txx9wdt_driver, txx9wdt_probe); | |
264 | +} | |
265 | + | |
266 | +static void __exit watchdog_exit(void) | |
267 | +{ | |
268 | + platform_driver_unregister(&txx9wdt_driver); | |
269 | +} | |
270 | + | |
271 | +module_init(watchdog_init); | |
272 | +module_exit(watchdog_exit); | |
273 | + | |
274 | +MODULE_DESCRIPTION("TXx9 Watchdog Driver"); | |
275 | +MODULE_LICENSE("GPL"); | |
276 | +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
drivers/watchdog/w83877f_wdt.c
... | ... | @@ -373,20 +373,20 @@ |
373 | 373 | goto err_out_region1; |
374 | 374 | } |
375 | 375 | |
376 | - rc = misc_register(&wdt_miscdev); | |
376 | + rc = register_reboot_notifier(&wdt_notifier); | |
377 | 377 | if (rc) |
378 | 378 | { |
379 | - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
380 | - wdt_miscdev.minor, rc); | |
379 | + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
380 | + rc); | |
381 | 381 | goto err_out_region2; |
382 | 382 | } |
383 | 383 | |
384 | - rc = register_reboot_notifier(&wdt_notifier); | |
384 | + rc = misc_register(&wdt_miscdev); | |
385 | 385 | if (rc) |
386 | 386 | { |
387 | - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
388 | - rc); | |
389 | - goto err_out_miscdev; | |
387 | + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
388 | + wdt_miscdev.minor, rc); | |
389 | + goto err_out_reboot; | |
390 | 390 | } |
391 | 391 | |
392 | 392 | printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", |
... | ... | @@ -394,8 +394,8 @@ |
394 | 394 | |
395 | 395 | return 0; |
396 | 396 | |
397 | -err_out_miscdev: | |
398 | - misc_deregister(&wdt_miscdev); | |
397 | +err_out_reboot: | |
398 | + unregister_reboot_notifier(&wdt_notifier); | |
399 | 399 | err_out_region2: |
400 | 400 | release_region(WDT_PING,1); |
401 | 401 | err_out_region1: |
drivers/watchdog/w83977f_wdt.c
... | ... | @@ -494,20 +494,20 @@ |
494 | 494 | goto err_out; |
495 | 495 | } |
496 | 496 | |
497 | - rc = misc_register(&wdt_miscdev); | |
497 | + rc = register_reboot_notifier(&wdt_notifier); | |
498 | 498 | if (rc) |
499 | 499 | { |
500 | - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
501 | - wdt_miscdev.minor, rc); | |
500 | + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
501 | + rc); | |
502 | 502 | goto err_out_region; |
503 | 503 | } |
504 | 504 | |
505 | - rc = register_reboot_notifier(&wdt_notifier); | |
505 | + rc = misc_register(&wdt_miscdev); | |
506 | 506 | if (rc) |
507 | 507 | { |
508 | - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
509 | - rc); | |
510 | - goto err_out_miscdev; | |
508 | + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
509 | + wdt_miscdev.minor, rc); | |
510 | + goto err_out_reboot; | |
511 | 511 | } |
512 | 512 | |
513 | 513 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", |
... | ... | @@ -515,8 +515,8 @@ |
515 | 515 | |
516 | 516 | return 0; |
517 | 517 | |
518 | -err_out_miscdev: | |
519 | - misc_deregister(&wdt_miscdev); | |
518 | +err_out_reboot: | |
519 | + unregister_reboot_notifier(&wdt_notifier); | |
520 | 520 | err_out_region: |
521 | 521 | release_region(IO_INDEX_PORT,2); |
522 | 522 | err_out: |
drivers/watchdog/wdt.c
... | ... | @@ -70,6 +70,8 @@ |
70 | 70 | static int io=0x240; |
71 | 71 | static int irq=11; |
72 | 72 | |
73 | +static DEFINE_SPINLOCK(wdt_lock); | |
74 | + | |
73 | 75 | module_param(io, int, 0); |
74 | 76 | MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); |
75 | 77 | module_param(irq, int, 0); |
... | ... | @@ -109,6 +111,8 @@ |
109 | 111 | |
110 | 112 | static int wdt_start(void) |
111 | 113 | { |
114 | + unsigned long flags; | |
115 | + spin_lock_irqsave(&wdt_lock, flags); | |
112 | 116 | inb_p(WDT_DC); /* Disable watchdog */ |
113 | 117 | wdt_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ |
114 | 118 | wdt_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ |
... | ... | @@ -117,6 +121,7 @@ |
117 | 121 | wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ |
118 | 122 | wdt_ctr_load(2,65535); /* Length of reset pulse */ |
119 | 123 | outb_p(0, WDT_DC); /* Enable watchdog */ |
124 | + spin_unlock_irqrestore(&wdt_lock, flags); | |
120 | 125 | return 0; |
121 | 126 | } |
122 | 127 | |
123 | 128 | |
... | ... | @@ -128,9 +133,12 @@ |
128 | 133 | |
129 | 134 | static int wdt_stop (void) |
130 | 135 | { |
136 | + unsigned long flags; | |
137 | + spin_lock_irqsave(&wdt_lock, flags); | |
131 | 138 | /* Turn the card off */ |
132 | 139 | inb_p(WDT_DC); /* Disable watchdog */ |
133 | 140 | wdt_ctr_load(2,0); /* 0 length reset pulses now */ |
141 | + spin_unlock_irqrestore(&wdt_lock, flags); | |
134 | 142 | return 0; |
135 | 143 | } |
136 | 144 | |
137 | 145 | |
... | ... | @@ -143,11 +151,14 @@ |
143 | 151 | |
144 | 152 | static int wdt_ping(void) |
145 | 153 | { |
154 | + unsigned long flags; | |
155 | + spin_lock_irqsave(&wdt_lock, flags); | |
146 | 156 | /* Write a watchdog value */ |
147 | 157 | inb_p(WDT_DC); /* Disable watchdog */ |
148 | 158 | wdt_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ |
149 | 159 | wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ |
150 | 160 | outb_p(0, WDT_DC); /* Enable watchdog */ |
161 | + spin_unlock_irqrestore(&wdt_lock, flags); | |
151 | 162 | return 0; |
152 | 163 | } |
153 | 164 | |
154 | 165 | |
... | ... | @@ -182,8 +193,13 @@ |
182 | 193 | |
183 | 194 | static int wdt_get_status(int *status) |
184 | 195 | { |
185 | - unsigned char new_status=inb_p(WDT_SR); | |
196 | + unsigned char new_status; | |
197 | + unsigned long flags; | |
186 | 198 | |
199 | + spin_lock_irqsave(&wdt_lock, flags); | |
200 | + new_status = inb_p(WDT_SR); | |
201 | + spin_unlock_irqrestore(&wdt_lock, flags); | |
202 | + | |
187 | 203 | *status=0; |
188 | 204 | if (new_status & WDC_SR_ISOI0) |
189 | 205 | *status |= WDIOF_EXTERN1; |
190 | 206 | |
... | ... | @@ -214,8 +230,12 @@ |
214 | 230 | |
215 | 231 | static int wdt_get_temperature(int *temperature) |
216 | 232 | { |
217 | - unsigned short c=inb_p(WDT_RT); | |
233 | + unsigned short c; | |
234 | + unsigned long flags; | |
218 | 235 | |
236 | + spin_lock_irqsave(&wdt_lock, flags); | |
237 | + c = inb_p(WDT_RT); | |
238 | + spin_unlock_irqrestore(&wdt_lock, flags); | |
219 | 239 | *temperature = (c * 11 / 15) + 7; |
220 | 240 | return 0; |
221 | 241 | } |
222 | 242 | |
... | ... | @@ -237,8 +257,11 @@ |
237 | 257 | * Read the status register see what is up and |
238 | 258 | * then printk it. |
239 | 259 | */ |
240 | - unsigned char status=inb_p(WDT_SR); | |
260 | + unsigned char status; | |
241 | 261 | |
262 | + spin_lock(&wdt_lock); | |
263 | + status = inb_p(WDT_SR); | |
264 | + | |
242 | 265 | printk(KERN_CRIT "WDT status %d\n", status); |
243 | 266 | |
244 | 267 | #ifdef CONFIG_WDT_501 |
... | ... | @@ -265,6 +288,7 @@ |
265 | 288 | printk(KERN_CRIT "Reset in 5ms.\n"); |
266 | 289 | #endif |
267 | 290 | } |
291 | + spin_unlock(&wdt_lock); | |
268 | 292 | return IRQ_HANDLED; |
269 | 293 | } |
270 | 294 |
drivers/watchdog/wdt977.c
... | ... | @@ -470,20 +470,20 @@ |
470 | 470 | } |
471 | 471 | } |
472 | 472 | |
473 | - rc = misc_register(&wdt977_miscdev); | |
473 | + rc = register_reboot_notifier(&wdt977_notifier); | |
474 | 474 | if (rc) |
475 | 475 | { |
476 | - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
477 | - wdt977_miscdev.minor, rc); | |
476 | + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
477 | + rc); | |
478 | 478 | goto err_out_region; |
479 | 479 | } |
480 | 480 | |
481 | - rc = register_reboot_notifier(&wdt977_notifier); | |
481 | + rc = misc_register(&wdt977_miscdev); | |
482 | 482 | if (rc) |
483 | 483 | { |
484 | - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | |
485 | - rc); | |
486 | - goto err_out_miscdev; | |
484 | + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | |
485 | + wdt977_miscdev.minor, rc); | |
486 | + goto err_out_reboot; | |
487 | 487 | } |
488 | 488 | |
489 | 489 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n", |
... | ... | @@ -491,8 +491,8 @@ |
491 | 491 | |
492 | 492 | return 0; |
493 | 493 | |
494 | -err_out_miscdev: | |
495 | - misc_deregister(&wdt977_miscdev); | |
494 | +err_out_reboot: | |
495 | + unregister_reboot_notifier(&wdt977_notifier); | |
496 | 496 | err_out_region: |
497 | 497 | if (!machine_is_netwinder()) |
498 | 498 | release_region(IO_INDEX_PORT,2); |