Commit 8561b089afbaed2651591e5a4574fdca451d82f2

Authored by Linus Torvalds

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
... ... @@ -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
... ... @@ -93,6 +93,7 @@
93 93 obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
94 94 obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
95 95 obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
  96 +obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
96 97  
97 98 # PARISC Architecture
98 99  
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
... ... @@ -279,7 +279,7 @@
279 279 }
280 280 }
281 281  
282   -static struct file_operations ar7_wdt_fops = {
  282 +static const struct file_operations ar7_wdt_fops = {
283 283 .owner = THIS_MODULE,
284 284 .write = ar7_wdt_write,
285 285 .ioctl = ar7_wdt_ioctl,
drivers/watchdog/bfin_wdt.c
... ... @@ -390,7 +390,7 @@
390 390 .resume = bfin_wdt_resume,
391 391 };
392 392  
393   -static struct file_operations bfin_wdt_fops = {
  393 +static const struct file_operations bfin_wdt_fops = {
394 394 .owner = THIS_MODULE,
395 395 .llseek = no_llseek,
396 396 .write = bfin_wdt_write,
drivers/watchdog/it8712f_wdt.c
... ... @@ -296,7 +296,7 @@
296 296 return 0;
297 297 }
298 298  
299   -static struct file_operations it8712f_wdt_fops = {
  299 +static const struct file_operations it8712f_wdt_fops = {
300 300 .owner = THIS_MODULE,
301 301 .llseek = no_llseek,
302 302 .write = it8712f_wdt_write,
drivers/watchdog/mpc5200_wdt.c
... ... @@ -158,7 +158,7 @@
158 158 return 0;
159 159 }
160 160  
161   -static struct file_operations mpc5200_wdt_fops = {
  161 +static const struct file_operations mpc5200_wdt_fops = {
162 162 .owner = THIS_MODULE,
163 163 .write = mpc5200_wdt_write,
164 164 .ioctl = mpc5200_wdt_ioctl,
drivers/watchdog/mtx-1_wdt.c
... ... @@ -180,7 +180,7 @@
180 180 return count;
181 181 }
182 182  
183   -static struct file_operations mtx1_wdt_fops = {
  183 +static const struct file_operations mtx1_wdt_fops = {
184 184 .owner = THIS_MODULE,
185 185 .llseek = no_llseek,
186 186 .ioctl = mtx1_wdt_ioctl,
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);