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] Add ICH9DO into the iTCO_wdt.c driver
[WATCHDOG] Fix booke_wdt.c on MPC85xx SMP system's
[WATCHDOG] Add a watchdog driver based on the CS5535/CS5536 MFGPT timers
[WATCHDOG] hpwdt: Fix NMI handling.
[WATCHDOG] Blackfin Watchdog Driver: split platform device/driver
[WATCHDOG] Add w83697h_wdt early_disable option
[WATCHDOG] Make w83697h_wdt timeout option string similar to others
[WATCHDOG] Make w83697h_wdt void-like functions void

+485 -116
+13
drivers/watchdog/Kconfig
··· 295 295 296 296 Most people will say N. 297 297 298 + config GEODE_WDT 299 + tristate "AMD Geode CS5535/CS5536 Watchdog" 300 + depends on MGEODE_LX 301 + help 302 + This driver enables a watchdog capability built into the 303 + CS5535/CS5536 companion chips for the AMD Geode GX and LX 304 + processors. This watchdog watches your kernel to make sure 305 + it doesn't freeze, and if it does, it reboots your computer after 306 + a certain amount of time. 307 + 308 + You can compile this driver directly into the kernel, or use 309 + it as a module. The module will be called geodewdt. 310 + 298 311 config SC520_WDT 299 312 tristate "AMD Elan SC520 processor Watchdog" 300 313 depends on X86
+1
drivers/watchdog/Makefile
··· 59 59 obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o 60 60 obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o 61 61 obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o 62 + obj-$(CONFIG_GEODE_WDT) += geodewdt.o 62 63 obj-$(CONFIG_SC520_WDT) += sc520_wdt.o 63 64 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o 64 65 obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+71 -40
drivers/watchdog/bfin_wdt.c
··· 29 29 30 30 #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) 31 31 #define stampit() stamp("here i am") 32 - #define pr_init(fmt, args...) ({ static const __initdata char __fmt[] = fmt; printk(__fmt, ## args); }) 32 + #define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) 33 + #define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) 33 34 34 35 #define WATCHDOG_NAME "bfin-wdt" 35 36 #define PFX WATCHDOG_NAME ": " ··· 378 377 # define bfin_wdt_resume NULL 379 378 #endif 380 379 381 - static struct platform_device bfin_wdt_device = { 382 - .name = WATCHDOG_NAME, 383 - .id = -1, 384 - }; 385 - 386 - static struct platform_driver bfin_wdt_driver = { 387 - .driver = { 388 - .name = WATCHDOG_NAME, 389 - .owner = THIS_MODULE, 390 - }, 391 - .suspend = bfin_wdt_suspend, 392 - .resume = bfin_wdt_resume, 393 - }; 394 - 395 380 static const struct file_operations bfin_wdt_fops = { 396 381 .owner = THIS_MODULE, 397 382 .llseek = no_llseek, ··· 405 418 }; 406 419 407 420 /** 421 + * bfin_wdt_probe - Initialize module 422 + * 423 + * Registers the misc device and notifier handler. Actual device 424 + * initialization is handled by bfin_wdt_open(). 425 + */ 426 + static int __devinit bfin_wdt_probe(struct platform_device *pdev) 427 + { 428 + int ret; 429 + 430 + ret = register_reboot_notifier(&bfin_wdt_notifier); 431 + if (ret) { 432 + pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); 433 + return ret; 434 + } 435 + 436 + ret = misc_register(&bfin_wdt_miscdev); 437 + if (ret) { 438 + pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 439 + WATCHDOG_MINOR, ret); 440 + unregister_reboot_notifier(&bfin_wdt_notifier); 441 + return ret; 442 + } 443 + 444 + pr_devinit(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", 445 + timeout, nowayout); 446 + 447 + return 0; 448 + } 449 + 450 + /** 451 + * bfin_wdt_remove - Initialize module 452 + * 453 + * Unregisters the misc device and notifier handler. Actual device 454 + * deinitialization is handled by bfin_wdt_close(). 455 + */ 456 + static int __devexit bfin_wdt_remove(struct platform_device *pdev) 457 + { 458 + misc_deregister(&bfin_wdt_miscdev); 459 + unregister_reboot_notifier(&bfin_wdt_notifier); 460 + return 0; 461 + } 462 + 463 + static struct platform_device *bfin_wdt_device; 464 + 465 + static struct platform_driver bfin_wdt_driver = { 466 + .probe = bfin_wdt_probe, 467 + .remove = __devexit_p(bfin_wdt_remove), 468 + .suspend = bfin_wdt_suspend, 469 + .resume = bfin_wdt_resume, 470 + .driver = { 471 + .name = WATCHDOG_NAME, 472 + .owner = THIS_MODULE, 473 + }, 474 + }; 475 + 476 + /** 408 477 * bfin_wdt_init - Initialize module 409 478 * 410 - * Registers the device and notifier handler. Actual device 411 - * initialization is handled by bfin_wdt_open(). 479 + * Checks the module params and registers the platform device & driver. 480 + * Real work is in the platform probe function. 412 481 */ 413 482 static int __init bfin_wdt_init(void) 414 483 { ··· 479 436 /* Since this is an on-chip device and needs no board-specific 480 437 * resources, we'll handle all the platform device stuff here. 481 438 */ 482 - ret = platform_device_register(&bfin_wdt_device); 483 - if (ret) 484 - return ret; 485 - 486 - ret = platform_driver_probe(&bfin_wdt_driver, NULL); 487 - if (ret) 488 - return ret; 489 - 490 - ret = register_reboot_notifier(&bfin_wdt_notifier); 439 + ret = platform_driver_register(&bfin_wdt_driver); 491 440 if (ret) { 492 - pr_init(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); 441 + pr_init(KERN_ERR PFX "unable to register driver\n"); 493 442 return ret; 494 443 } 495 444 496 - ret = misc_register(&bfin_wdt_miscdev); 497 - if (ret) { 498 - pr_init(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 499 - WATCHDOG_MINOR, ret); 500 - unregister_reboot_notifier(&bfin_wdt_notifier); 501 - return ret; 445 + bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0); 446 + if (IS_ERR(bfin_wdt_device)) { 447 + pr_init(KERN_ERR PFX "unable to register device\n"); 448 + platform_driver_unregister(&bfin_wdt_driver); 449 + return PTR_ERR(bfin_wdt_device); 502 450 } 503 - 504 - pr_init(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", 505 - timeout, nowayout); 506 451 507 452 return 0; 508 453 } ··· 498 467 /** 499 468 * bfin_wdt_exit - Deinitialize module 500 469 * 501 - * Unregisters the device and notifier handler. Actual device 502 - * deinitialization is handled by bfin_wdt_close(). 470 + * Back out the platform device & driver steps. Real work is in the 471 + * platform remove function. 503 472 */ 504 473 static void __exit bfin_wdt_exit(void) 505 474 { 506 - misc_deregister(&bfin_wdt_miscdev); 507 - unregister_reboot_notifier(&bfin_wdt_notifier); 475 + platform_device_unregister(bfin_wdt_device); 476 + platform_driver_unregister(&bfin_wdt_driver); 508 477 } 509 478 510 479 module_init(bfin_wdt_init);
+40 -48
drivers/watchdog/booke_wdt.c
··· 1 1 /* 2 - * drivers/char/watchdog/booke_wdt.c 3 - * 4 2 * Watchdog timer for PowerPC Book-E systems 5 3 * 6 4 * Author: Matthew McClintock 7 5 * Maintainer: Kumar Gala <galak@kernel.crashing.org> 8 6 * 9 - * Copyright 2005 Freescale Semiconductor Inc. 7 + * Copyright 2005, 2008 Freescale Semiconductor Inc. 10 8 * 11 9 * This program is free software; you can redistribute it and/or modify it 12 10 * under the terms of the GNU General Public License as published by the ··· 14 16 15 17 #include <linux/module.h> 16 18 #include <linux/fs.h> 19 + #include <linux/smp.h> 17 20 #include <linux/miscdevice.h> 18 21 #include <linux/notifier.h> 19 22 #include <linux/watchdog.h> ··· 37 38 #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ 38 39 #endif /* for timing information */ 39 40 40 - u32 booke_wdt_enabled = 0; 41 + u32 booke_wdt_enabled; 41 42 u32 booke_wdt_period = WDT_PERIOD_DEFAULT; 42 43 43 44 #ifdef CONFIG_FSL_BOOKE ··· 46 47 #define WDTP(x) (TCR_WP(x)) 47 48 #endif 48 49 49 - /* 50 - * booke_wdt_ping: 51 - */ 52 - static __inline__ void booke_wdt_ping(void) 50 + static DEFINE_SPINLOCK(booke_wdt_lock); 51 + 52 + static void __booke_wdt_ping(void *data) 53 53 { 54 54 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); 55 55 } 56 56 57 - /* 58 - * booke_wdt_enable: 59 - */ 60 - static __inline__ void booke_wdt_enable(void) 57 + static void booke_wdt_ping(void) 58 + { 59 + on_each_cpu(__booke_wdt_ping, NULL, 0, 0); 60 + } 61 + 62 + static void __booke_wdt_enable(void *data) 61 63 { 62 64 u32 val; 63 65 64 66 /* clear status before enabling watchdog */ 65 - booke_wdt_ping(); 67 + __booke_wdt_ping(NULL); 66 68 val = mfspr(SPRN_TCR); 67 69 val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); 68 70 69 71 mtspr(SPRN_TCR, val); 70 72 } 71 73 72 - /* 73 - * booke_wdt_write: 74 - */ 75 - static ssize_t booke_wdt_write (struct file *file, const char __user *buf, 74 + static ssize_t booke_wdt_write(struct file *file, const char __user *buf, 76 75 size_t count, loff_t *ppos) 77 76 { 78 77 booke_wdt_ping(); ··· 78 81 } 79 82 80 83 static struct watchdog_info ident = { 81 - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 82 - .firmware_version = 0, 83 - .identity = "PowerPC Book-E Watchdog", 84 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 85 + .identity = "PowerPC Book-E Watchdog", 84 86 }; 85 87 86 - /* 87 - * booke_wdt_ioctl: 88 - */ 89 - static int booke_wdt_ioctl (struct inode *inode, struct file *file, 88 + static int booke_wdt_ioctl(struct inode *inode, struct file *file, 90 89 unsigned int cmd, unsigned long arg) 91 90 { 92 91 u32 tmp = 0; ··· 90 97 91 98 switch (cmd) { 92 99 case WDIOC_GETSUPPORT: 93 - if (copy_to_user ((struct watchdog_info __user *) arg, &ident, 100 + if (copy_to_user((struct watchdog_info __user *)arg, &ident, 94 101 sizeof(struct watchdog_info))) 95 102 return -EFAULT; 96 103 case WDIOC_GETSTATUS: ··· 125 132 126 133 return 0; 127 134 } 128 - /* 129 - * booke_wdt_open: 130 - */ 131 - static int booke_wdt_open (struct inode *inode, struct file *file) 135 + 136 + static int booke_wdt_open(struct inode *inode, struct file *file) 132 137 { 138 + spin_lock(&booke_wdt_lock); 133 139 if (booke_wdt_enabled == 0) { 134 140 booke_wdt_enabled = 1; 135 - booke_wdt_enable(); 136 - printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", 137 - booke_wdt_period); 141 + on_each_cpu(__booke_wdt_enable, NULL, 0, 0); 142 + printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " 143 + "(wdt_period=%d)\n", booke_wdt_period); 138 144 } 145 + spin_unlock(&booke_wdt_lock); 139 146 140 147 return nonseekable_open(inode, file); 141 148 } 142 149 143 150 static const struct file_operations booke_wdt_fops = { 144 - .owner = THIS_MODULE, 145 - .llseek = no_llseek, 146 - .write = booke_wdt_write, 147 - .ioctl = booke_wdt_ioctl, 148 - .open = booke_wdt_open, 151 + .owner = THIS_MODULE, 152 + .llseek = no_llseek, 153 + .write = booke_wdt_write, 154 + .ioctl = booke_wdt_ioctl, 155 + .open = booke_wdt_open, 149 156 }; 150 157 151 158 static struct miscdevice booke_wdt_miscdev = { 152 - .minor = WATCHDOG_MINOR, 153 - .name = "watchdog", 154 - .fops = &booke_wdt_fops, 159 + .minor = WATCHDOG_MINOR, 160 + .name = "watchdog", 161 + .fops = &booke_wdt_fops, 155 162 }; 156 163 157 164 static void __exit booke_wdt_exit(void) ··· 159 166 misc_deregister(&booke_wdt_miscdev); 160 167 } 161 168 162 - /* 163 - * booke_wdt_init: 164 - */ 165 169 static int __init booke_wdt_init(void) 166 170 { 167 171 int ret = 0; 168 172 169 - printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); 173 + printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); 170 174 ident.firmware_version = cur_cpu_spec->pvr_value; 171 175 172 176 ret = misc_register(&booke_wdt_miscdev); 173 177 if (ret) { 174 - printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n", 178 + printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n", 175 179 WATCHDOG_MINOR, ret); 176 180 return ret; 177 181 } 178 182 183 + spin_lock(&booke_wdt_lock); 179 184 if (booke_wdt_enabled == 1) { 180 - printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", 181 - booke_wdt_period); 182 - booke_wdt_enable(); 185 + printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " 186 + "(wdt_period=%d)\n", booke_wdt_period); 187 + on_each_cpu(__booke_wdt_enable, NULL, 0, 0); 183 188 } 189 + spin_unlock(&booke_wdt_lock); 184 190 185 191 return ret; 186 192 }
+309
drivers/watchdog/geodewdt.c
··· 1 + /* Watchdog timer for the Geode GX/LX with the CS5535/CS5536 companion chip 2 + * 3 + * Copyright (C) 2006-2007, Advanced Micro Devices, Inc. 4 + * 5 + * This program is free software; you can redistribute it and/or 6 + * modify it under the terms of the GNU General Public License 7 + * as published by the Free Software Foundation; either version 8 + * 2 of the License, or (at your option) any later version. 9 + */ 10 + 11 + 12 + #include <linux/module.h> 13 + #include <linux/moduleparam.h> 14 + #include <linux/types.h> 15 + #include <linux/miscdevice.h> 16 + #include <linux/watchdog.h> 17 + #include <linux/fs.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/reboot.h> 20 + 21 + #include <asm/uaccess.h> 22 + #include <asm/geode.h> 23 + 24 + #define GEODEWDT_HZ 500 25 + #define GEODEWDT_SCALE 6 26 + #define GEODEWDT_MAX_SECONDS 131 27 + 28 + #define WDT_FLAGS_OPEN 1 29 + #define WDT_FLAGS_ORPHAN 2 30 + 31 + #define DRV_NAME "geodewdt" 32 + #define WATCHDOG_NAME "Geode GX/LX WDT" 33 + #define WATCHDOG_TIMEOUT 60 34 + 35 + static int timeout = WATCHDOG_TIMEOUT; 36 + module_param(timeout, int, 0); 37 + MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=131, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 38 + 39 + static int nowayout = WATCHDOG_NOWAYOUT; 40 + module_param(nowayout, int, 0); 41 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 42 + 43 + static struct platform_device *geodewdt_platform_device; 44 + static unsigned long wdt_flags; 45 + static int wdt_timer; 46 + static int safe_close; 47 + 48 + static void geodewdt_ping(void) 49 + { 50 + /* Stop the counter */ 51 + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0); 52 + 53 + /* Reset the counter */ 54 + geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0); 55 + 56 + /* Enable the counter */ 57 + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN); 58 + } 59 + 60 + static void geodewdt_disable(void) 61 + { 62 + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0); 63 + geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0); 64 + } 65 + 66 + static int geodewdt_set_heartbeat(int val) 67 + { 68 + if (val < 1 || val > GEODEWDT_MAX_SECONDS) 69 + return -EINVAL; 70 + 71 + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0); 72 + geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ); 73 + geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0); 74 + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN); 75 + 76 + timeout = val; 77 + return 0; 78 + } 79 + 80 + static int 81 + geodewdt_open(struct inode *inode, struct file *file) 82 + { 83 + if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) 84 + return -EBUSY; 85 + 86 + if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) 87 + __module_get(THIS_MODULE); 88 + 89 + geodewdt_ping(); 90 + return nonseekable_open(inode, file); 91 + } 92 + 93 + static int 94 + geodewdt_release(struct inode *inode, struct file *file) 95 + { 96 + if (safe_close) { 97 + geodewdt_disable(); 98 + module_put(THIS_MODULE); 99 + } 100 + else { 101 + printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n"); 102 + geodewdt_ping(); 103 + 104 + set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); 105 + } 106 + 107 + clear_bit(WDT_FLAGS_OPEN, &wdt_flags); 108 + safe_close = 0; 109 + return 0; 110 + } 111 + 112 + static ssize_t 113 + geodewdt_write(struct file *file, const char __user *data, size_t len, 114 + loff_t *ppos) 115 + { 116 + if(len) { 117 + if (!nowayout) { 118 + size_t i; 119 + safe_close = 0; 120 + 121 + for (i = 0; i != len; i++) { 122 + char c; 123 + 124 + if (get_user(c, data + i)) 125 + return -EFAULT; 126 + 127 + if (c == 'V') 128 + safe_close = 1; 129 + } 130 + } 131 + 132 + geodewdt_ping(); 133 + } 134 + return len; 135 + } 136 + 137 + static int 138 + geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 139 + unsigned long arg) 140 + { 141 + void __user *argp = (void __user *)arg; 142 + int __user *p = argp; 143 + int interval; 144 + 145 + static struct watchdog_info ident = { 146 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING 147 + | WDIOF_MAGICCLOSE, 148 + .firmware_version = 1, 149 + .identity = WATCHDOG_NAME, 150 + }; 151 + 152 + switch(cmd) { 153 + case WDIOC_GETSUPPORT: 154 + return copy_to_user(argp, &ident, 155 + sizeof(ident)) ? -EFAULT : 0; 156 + break; 157 + 158 + case WDIOC_GETSTATUS: 159 + case WDIOC_GETBOOTSTATUS: 160 + return put_user(0, p); 161 + 162 + case WDIOC_KEEPALIVE: 163 + geodewdt_ping(); 164 + return 0; 165 + 166 + case WDIOC_SETTIMEOUT: 167 + if (get_user(interval, p)) 168 + return -EFAULT; 169 + 170 + if (geodewdt_set_heartbeat(interval)) 171 + return -EINVAL; 172 + 173 + /* Fall through */ 174 + 175 + case WDIOC_GETTIMEOUT: 176 + return put_user(timeout, p); 177 + 178 + case WDIOC_SETOPTIONS: 179 + { 180 + int options, ret = -EINVAL; 181 + 182 + if (get_user(options, p)) 183 + return -EFAULT; 184 + 185 + if (options & WDIOS_DISABLECARD) { 186 + geodewdt_disable(); 187 + ret = 0; 188 + } 189 + 190 + if (options & WDIOS_ENABLECARD) { 191 + geodewdt_ping(); 192 + ret = 0; 193 + } 194 + 195 + return ret; 196 + } 197 + default: 198 + return -ENOTTY; 199 + } 200 + 201 + return 0; 202 + } 203 + 204 + static const struct file_operations geodewdt_fops = { 205 + .owner = THIS_MODULE, 206 + .llseek = no_llseek, 207 + .write = geodewdt_write, 208 + .ioctl = geodewdt_ioctl, 209 + .open = geodewdt_open, 210 + .release = geodewdt_release, 211 + }; 212 + 213 + static struct miscdevice geodewdt_miscdev = { 214 + .minor = WATCHDOG_MINOR, 215 + .name = "watchdog", 216 + .fops = &geodewdt_fops 217 + }; 218 + 219 + static int __devinit 220 + geodewdt_probe(struct platform_device *dev) 221 + { 222 + int ret, timer; 223 + 224 + timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, 225 + MFGPT_DOMAIN_WORKING, THIS_MODULE); 226 + 227 + if (timer == -1) { 228 + printk(KERN_ERR "geodewdt: No timers were available\n"); 229 + return -ENODEV; 230 + } 231 + 232 + wdt_timer = timer; 233 + 234 + /* Set up the timer */ 235 + 236 + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 237 + GEODEWDT_SCALE | (3 << 8)); 238 + 239 + /* Set up comparator 2 to reset when the event fires */ 240 + geode_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1); 241 + 242 + /* Set up the initial timeout */ 243 + 244 + geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, 245 + timeout * GEODEWDT_HZ); 246 + 247 + ret = misc_register(&geodewdt_miscdev); 248 + 249 + return ret; 250 + } 251 + 252 + static int __devexit 253 + geodewdt_remove(struct platform_device *dev) 254 + { 255 + misc_deregister(&geodewdt_miscdev); 256 + return 0; 257 + } 258 + 259 + static void 260 + geodewdt_shutdown(struct platform_device *dev) 261 + { 262 + geodewdt_disable(); 263 + } 264 + 265 + static struct platform_driver geodewdt_driver = { 266 + .probe = geodewdt_probe, 267 + .remove = __devexit_p(geodewdt_remove), 268 + .shutdown = geodewdt_shutdown, 269 + .driver = { 270 + .owner = THIS_MODULE, 271 + .name = DRV_NAME, 272 + }, 273 + }; 274 + 275 + static int __init 276 + geodewdt_init(void) 277 + { 278 + int ret; 279 + 280 + ret = platform_driver_register(&geodewdt_driver); 281 + if (ret) 282 + return ret; 283 + 284 + geodewdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); 285 + if (IS_ERR(geodewdt_platform_device)) { 286 + ret = PTR_ERR(geodewdt_platform_device); 287 + goto err; 288 + } 289 + 290 + return 0; 291 + err: 292 + platform_driver_unregister(&geodewdt_driver); 293 + return ret; 294 + } 295 + 296 + static void __exit 297 + geodewdt_exit(void) 298 + { 299 + platform_device_unregister(geodewdt_platform_device); 300 + platform_driver_unregister(&geodewdt_driver); 301 + } 302 + 303 + module_init(geodewdt_init); 304 + module_exit(geodewdt_exit); 305 + 306 + MODULE_AUTHOR("Advanced Micro Devices, Inc"); 307 + MODULE_DESCRIPTION("Geode GX/LX Watchdog Driver"); 308 + MODULE_LICENSE("GPL"); 309 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+12 -15
drivers/watchdog/hpwdt.c
··· 418 418 static unsigned long rom_pl; 419 419 static int die_nmi_called; 420 420 421 - if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) 422 - return NOTIFY_OK; 423 - 424 - spin_lock_irqsave(&rom_lock, rom_pl); 425 - if (!die_nmi_called) 426 - asminline_call(&cmn_regs, cru_rom_addr); 427 - die_nmi_called = 1; 428 - spin_unlock_irqrestore(&rom_lock, rom_pl); 429 - if (cmn_regs.u1.ral == 0) { 430 - printk(KERN_WARNING "hpwdt: An NMI occurred, " 431 - "but unable to determine source.\n"); 432 - } else { 433 - panic("An NMI occurred, please see the Integrated " 434 - "Management Log for details.\n"); 421 + if (ulReason == DIE_NMI || ulReason == DIE_NMI_IPI) { 422 + spin_lock_irqsave(&rom_lock, rom_pl); 423 + if (!die_nmi_called) 424 + asminline_call(&cmn_regs, cru_rom_addr); 425 + die_nmi_called = 1; 426 + spin_unlock_irqrestore(&rom_lock, rom_pl); 427 + if (cmn_regs.u1.ral != 0) { 428 + panic("An NMI occurred, please see the Integrated " 429 + "Management Log for details.\n"); 430 + } 435 431 } 436 432 437 - return NOTIFY_STOP; 433 + die_nmi_called = 0; 434 + return NOTIFY_DONE; 438 435 } 439 436 440 437 /*
+9 -5
drivers/watchdog/iTCO_wdt.c
··· 41 41 * 82801HH (ICH8DH) : document number 313056-003, 313057-009, 42 42 * 82801HO (ICH8DO) : document number 313056-003, 313057-009, 43 43 * 82801HEM (ICH8M-E) : document number 313056-003, 313057-009, 44 - * 82801IB (ICH9) : document number 316972-001, 316973-001, 45 - * 82801IR (ICH9R) : document number 316972-001, 316973-001, 46 - * 82801IH (ICH9DH) : document number 316972-001, 316973-001, 44 + * 82801IB (ICH9) : document number 316972-001, 316973-006, 45 + * 82801IR (ICH9R) : document number 316972-001, 316973-006, 46 + * 82801IH (ICH9DH) : document number 316972-001, 316973-006, 47 + * 82801IO (ICH9DO) : document number 316972-001, 316973-006, 47 48 * 6300ESB (6300ESB) : document number 300641-003, 300884-010, 48 49 * 631xESB (631xESB) : document number 313082-001, 313075-005, 49 50 * 632xESB (632xESB) : document number 313082-001, 313075-005 ··· 56 55 57 56 /* Module and version information */ 58 57 #define DRV_NAME "iTCO_wdt" 59 - #define DRV_VERSION "1.02" 60 - #define DRV_RELDATE "26-Jul-2007" 58 + #define DRV_VERSION "1.03" 59 + #define DRV_RELDATE "30-Apr-2008" 61 60 #define PFX DRV_NAME ": " 62 61 63 62 /* Includes */ ··· 105 104 TCO_ICH9, /* ICH9 */ 106 105 TCO_ICH9R, /* ICH9R */ 107 106 TCO_ICH9DH, /* ICH9DH */ 107 + TCO_ICH9DO, /* ICH9DO */ 108 108 TCO_631XESB, /* 631xESB/632xESB */ 109 109 }; 110 110 ··· 138 136 {"ICH9", 2}, 139 137 {"ICH9R", 2}, 140 138 {"ICH9DH", 2}, 139 + {"ICH9DO", 2}, 141 140 {"631xESB/632xESB", 2}, 142 141 {NULL,0} 143 142 }; ··· 184 181 { ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )}, 185 182 { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )}, 186 183 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )}, 184 + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO )}, 187 185 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, 188 186 { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, 189 187 { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)},
+30 -8
drivers/watchdog/w83697hf_wdt.c
··· 44 44 #define WATCHDOG_NAME "w83697hf/hg WDT" 45 45 #define PFX WATCHDOG_NAME ": " 46 46 #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ 47 + #define WATCHDOG_EARLY_DISABLE 1 /* Disable until userland kicks in */ 47 48 48 49 static unsigned long wdt_is_open; 49 50 static char expect_close; ··· 57 56 58 57 static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ 59 58 module_param(timeout, int, 0); 60 - MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 59 + MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255 (default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 61 60 62 61 static int nowayout = WATCHDOG_NOWAYOUT; 63 62 module_param(nowayout, int, 0); 64 63 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 64 + 65 + static int early_disable = WATCHDOG_EARLY_DISABLE; 66 + module_param(early_disable, int, 0); 67 + MODULE_PARM_DESC(early_disable, "Watchdog gets disabled at boot time (default=" __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")"); 65 68 66 69 /* 67 70 * Kernel methods. ··· 145 140 w83697hf_deselect_wdt(); 146 141 } 147 142 148 - static int 143 + static void 149 144 wdt_ping(void) 150 145 { 151 146 spin_lock(&io_lock); ··· 155 150 156 151 w83697hf_deselect_wdt(); 157 152 spin_unlock(&io_lock); 158 - return 0; 159 153 } 160 154 161 - static int 155 + static void 162 156 wdt_enable(void) 163 157 { 164 158 spin_lock(&io_lock); ··· 168 164 169 165 w83697hf_deselect_wdt(); 170 166 spin_unlock(&io_lock); 171 - return 0; 172 167 } 173 168 174 - static int 169 + static void 175 170 wdt_disable(void) 176 171 { 177 172 spin_lock(&io_lock); ··· 181 178 182 179 w83697hf_deselect_wdt(); 183 180 spin_unlock(&io_lock); 184 - return 0; 181 + } 182 + 183 + static unsigned char 184 + wdt_running(void) 185 + { 186 + unsigned char t; 187 + 188 + spin_lock(&io_lock); 189 + w83697hf_select_wdt(); 190 + 191 + t = w83697hf_get_reg(0xF4); /* Read timer */ 192 + 193 + w83697hf_deselect_wdt(); 194 + spin_unlock(&io_lock); 195 + 196 + return t; 185 197 } 186 198 187 199 static int ··· 415 397 } 416 398 417 399 w83697hf_init(); 418 - wdt_disable(); /* Disable watchdog until first use */ 400 + if (early_disable) { 401 + if (wdt_running()) 402 + printk (KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n"); 403 + wdt_disable(); 404 + } 419 405 420 406 if (wdt_set_heartbeat(timeout)) { 421 407 wdt_set_heartbeat(WATCHDOG_TIMEOUT);