Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
[WATCHDOG] at91_wdt.c - Atmel AT91RM9200 watchdog driver
[WATCHDOG] pcwd_usb.c: fix a NULL pointer dereference
[WATCHDOG] pcwd.c sprintf/strcpy fix
[WATCHDOG] pcwd.c general clean-up after patches
[WATCHDOG] pcwd.c add debug info
[WATCHDOG] pcwd.c pcwd_cleanup_module patch
[WATCHDOG] pcwd.c firmware-info patch
[WATCHDOG] pcwd.c control status patch

+340 -36
+7
drivers/char/watchdog/Kconfig
··· 60 61 # ARM Architecture 62 63 config 21285_WATCHDOG 64 tristate "DC21285 watchdog" 65 depends on WATCHDOG && FOOTBRIDGE
··· 60 61 # ARM Architecture 62 63 + config AT91_WATCHDOG 64 + tristate "AT91RM9200 watchdog" 65 + depends on WATCHDOG && ARCH_AT91RM9200 66 + help 67 + Watchdog timer embedded into AT91RM9200 chips. This will reboot your 68 + system when the timeout is reached. 69 + 70 config 21285_WATCHDOG 71 tristate "DC21285 watchdog" 72 depends on WATCHDOG && FOOTBRIDGE
+1
drivers/char/watchdog/Makefile
··· 23 obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o 24 25 # ARM Architecture 26 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o 27 obj-$(CONFIG_977_WATCHDOG) += wdt977.o 28 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
··· 23 obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o 24 25 # ARM Architecture 26 + obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o 27 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o 28 obj-$(CONFIG_977_WATCHDOG) += wdt977.o 29 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+228
drivers/char/watchdog/at91_wdt.c
···
··· 1 + /* 2 + * Watchdog driver for Atmel AT91RM9200 (Thunder) 3 + * 4 + * Copyright (C) 2003 SAN People (Pty) Ltd 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the License, or (at your option) any later version. 10 + */ 11 + 12 + #include <linux/config.h> 13 + #include <linux/errno.h> 14 + #include <linux/fs.h> 15 + #include <linux/init.h> 16 + #include <linux/kernel.h> 17 + #include <linux/miscdevice.h> 18 + #include <linux/module.h> 19 + #include <linux/moduleparam.h> 20 + #include <linux/types.h> 21 + #include <linux/watchdog.h> 22 + #include <asm/bitops.h> 23 + #include <asm/uaccess.h> 24 + 25 + 26 + #define WDT_DEFAULT_TIME 5 /* 5 seconds */ 27 + #define WDT_MAX_TIME 256 /* 256 seconds */ 28 + 29 + static int wdt_time = WDT_DEFAULT_TIME; 30 + static int nowayout = WATCHDOG_NOWAYOUT; 31 + 32 + module_param(wdt_time, int, 0); 33 + MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); 34 + 35 + module_param(nowayout, int, 0); 36 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 37 + 38 + 39 + static unsigned long at91wdt_busy; 40 + 41 + /* ......................................................................... */ 42 + 43 + /* 44 + * Disable the watchdog. 45 + */ 46 + static void inline at91_wdt_stop(void) 47 + { 48 + at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); 49 + } 50 + 51 + /* 52 + * Enable and reset the watchdog. 53 + */ 54 + static void inline at91_wdt_start(void) 55 + { 56 + at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); 57 + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); 58 + } 59 + 60 + /* 61 + * Reload the watchdog timer. (ie, pat the watchdog) 62 + */ 63 + static void inline at91_wdt_reload(void) 64 + { 65 + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); 66 + } 67 + 68 + /* ......................................................................... */ 69 + 70 + /* 71 + * Watchdog device is opened, and watchdog starts running. 72 + */ 73 + static int at91_wdt_open(struct inode *inode, struct file *file) 74 + { 75 + if (test_and_set_bit(0, &at91wdt_busy)) 76 + return -EBUSY; 77 + 78 + at91_wdt_start(); 79 + return nonseekable_open(inode, file); 80 + } 81 + 82 + /* 83 + * Close the watchdog device. 84 + * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also 85 + * disabled. 86 + */ 87 + static int at91_wdt_close(struct inode *inode, struct file *file) 88 + { 89 + if (!nowayout) 90 + at91_wdt_stop(); /* Disable the watchdog when file is closed */ 91 + 92 + clear_bit(0, &at91wdt_busy); 93 + return 0; 94 + } 95 + 96 + /* 97 + * Change the watchdog time interval. 98 + */ 99 + static int at91_wdt_settimeout(int new_time) 100 + { 101 + /* 102 + * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz 103 + * 104 + * Since WDV is a 16-bit counter, the maximum period is 105 + * 65536 / 0.256 = 256 seconds. 106 + */ 107 + if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) 108 + return -EINVAL; 109 + 110 + /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ 111 + wdt_time = new_time; 112 + return 0; 113 + } 114 + 115 + static struct watchdog_info at91_wdt_info = { 116 + .identity = "at91 watchdog", 117 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 118 + }; 119 + 120 + /* 121 + * Handle commands from user-space. 122 + */ 123 + static int at91_wdt_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_value; 129 + 130 + switch(cmd) { 131 + case WDIOC_KEEPALIVE: 132 + at91_wdt_reload(); /* pat the watchdog */ 133 + return 0; 134 + 135 + case WDIOC_GETSUPPORT: 136 + return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; 137 + 138 + case WDIOC_SETTIMEOUT: 139 + if (get_user(new_value, p)) 140 + return -EFAULT; 141 + 142 + if (at91_wdt_settimeout(new_value)) 143 + return -EINVAL; 144 + 145 + /* Enable new time value */ 146 + at91_wdt_start(); 147 + 148 + /* Return current value */ 149 + return put_user(wdt_time, p); 150 + 151 + case WDIOC_GETTIMEOUT: 152 + return put_user(wdt_time, p); 153 + 154 + case WDIOC_GETSTATUS: 155 + case WDIOC_GETBOOTSTATUS: 156 + return put_user(0, p); 157 + 158 + case WDIOC_SETOPTIONS: 159 + if (get_user(new_value, p)) 160 + return -EFAULT; 161 + 162 + if (new_value & WDIOS_DISABLECARD) 163 + at91_wdt_stop(); 164 + if (new_value & WDIOS_ENABLECARD) 165 + at91_wdt_start(); 166 + return 0; 167 + 168 + default: 169 + return -ENOIOCTLCMD; 170 + } 171 + } 172 + 173 + /* 174 + * Pat the watchdog whenever device is written to. 175 + */ 176 + static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) 177 + { 178 + at91_wdt_reload(); /* pat the watchdog */ 179 + return len; 180 + } 181 + 182 + /* ......................................................................... */ 183 + 184 + static struct file_operations at91wdt_fops = { 185 + .owner = THIS_MODULE, 186 + .llseek = no_llseek, 187 + .ioctl = at91_wdt_ioctl, 188 + .open = at91_wdt_open, 189 + .release = at91_wdt_close, 190 + .write = at91_wdt_write, 191 + }; 192 + 193 + static struct miscdevice at91wdt_miscdev = { 194 + .minor = WATCHDOG_MINOR, 195 + .name = "watchdog", 196 + .fops = &at91wdt_fops, 197 + }; 198 + 199 + static int __init at91_wdt_init(void) 200 + { 201 + int res; 202 + 203 + /* Check that the heartbeat value is within range; if not reset to the default */ 204 + if (at91_wdt_settimeout(wdt_time)) { 205 + at91_wdt_settimeout(WDT_DEFAULT_TIME); 206 + printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); 207 + } 208 + 209 + res = misc_register(&at91wdt_miscdev); 210 + if (res) 211 + return res; 212 + 213 + printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout); 214 + return 0; 215 + } 216 + 217 + static void __exit at91_wdt_exit(void) 218 + { 219 + misc_deregister(&at91wdt_miscdev); 220 + } 221 + 222 + module_init(at91_wdt_init); 223 + module_exit(at91_wdt_exit); 224 + 225 + MODULE_AUTHOR("Andrew Victor"); 226 + MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); 227 + MODULE_LICENSE("GPL"); 228 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+102 -35
drivers/char/watchdog/pcwd.c
··· 66 #include <linux/fs.h> /* For file operations */ 67 #include <linux/ioport.h> /* For io-port access */ 68 #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 69 - #include <linux/sched.h> /* TASK_INTERRUPTIBLE, set_current_state() and friends */ 70 - #include <linux/slab.h> /* For kmalloc */ 71 72 #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 73 #include <asm/io.h> /* For inb/outb/... */ 74 75 /* Module and version information */ 76 - #define WATCHDOG_VERSION "1.16" 77 - #define WATCHDOG_DATE "03 Jan 2006" 78 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" 79 #define WATCHDOG_NAME "pcwd" 80 #define PFX WATCHDOG_NAME ": " ··· 94 * PCI-PC Watchdog card. 95 */ 96 /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ 97 - #define WD_WDRST 0x01 /* Previously reset state */ 98 - #define WD_T110 0x02 /* Temperature overheat sense */ 99 - #define WD_HRTBT 0x04 /* Heartbeat sense */ 100 - #define WD_RLY2 0x08 /* External relay triggered */ 101 - #define WD_SRLY2 0x80 /* Software external relay triggered */ 102 /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ 103 - #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ 104 - #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ 105 - #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ 106 /* Port 2 : Control Status #2 */ 107 #define WD_WDIS 0x10 /* Watchdog Disabled */ 108 #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ ··· 124 #define CMD_ISA_VERSION_HUNDRETH 0x03 125 #define CMD_ISA_VERSION_MINOR 0x04 126 #define CMD_ISA_SWITCH_SETTINGS 0x05 127 #define CMD_ISA_DELAY_TIME_2SECS 0x0A 128 #define CMD_ISA_DELAY_TIME_4SECS 0x0B 129 #define CMD_ISA_DELAY_TIME_8SECS 0x0C 130 131 /* 132 * We are using an kernel timer to do the pinging of the watchdog ··· 149 static char expect_close; 150 static int temp_panic; 151 static struct { /* this is private data for each ISA-PC watchdog card */ 152 int revision; /* The card's revision */ 153 int supports_temp; /* Wether or not the card has a temperature device */ 154 int command_mode; /* Wether or not the card is in command mode */ ··· 161 } pcwd_private; 162 163 /* module parameters */ 164 #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ 165 static int heartbeat = WATCHDOG_HEARTBEAT; 166 module_param(heartbeat, int, 0); ··· 187 int control_status; 188 int port0, last_port0; /* Double read for stabilising */ 189 190 /* The WCMD bit must be 1 and the command is only 4 bits in size */ 191 control_status = (cmd & 0x0F) | WD_WCMD; 192 outb_p(control_status, pcwd_private.io_addr + 2); ··· 206 207 udelay (250); 208 } 209 210 return port0; 211 } ··· 237 spin_unlock(&pcwd_private.io_lock); 238 pcwd_private.command_mode = found; 239 240 return(found); 241 } 242 ··· 253 spin_unlock(&pcwd_private.io_lock); 254 255 pcwd_private.command_mode = 0; 256 } 257 258 static inline void pcwd_check_temperature_support(void) ··· 265 pcwd_private.supports_temp = 1; 266 } 267 268 - static inline char *get_firmware(void) 269 { 270 int one, ten, hund, minor; 271 - char *ret; 272 273 - ret = kmalloc(6, GFP_KERNEL); 274 - if(ret == NULL) 275 - return NULL; 276 277 if (set_command_mode()) { 278 one = send_isa_command(CMD_ISA_VERSION_INTEGER); 279 ten = send_isa_command(CMD_ISA_VERSION_TENTH); 280 hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); 281 minor = send_isa_command(CMD_ISA_VERSION_MINOR); 282 - sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); 283 } 284 - else 285 - sprintf(ret, "ERROR"); 286 - 287 unset_command_mode(); 288 - return(ret); 289 } 290 291 static inline int pcwd_get_option_switches(void) ··· 298 299 static void pcwd_show_card_info(void) 300 { 301 - char *firmware; 302 int option_switches; 303 304 /* Get some extra info from the hardware (in command/debug/diag mode) */ 305 if (pcwd_private.revision == PCWD_REVISION_A) 306 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); 307 else if (pcwd_private.revision == PCWD_REVISION_C) { 308 - firmware = get_firmware(); 309 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", 310 - pcwd_private.io_addr, firmware); 311 - kfree(firmware); 312 option_switches = pcwd_get_option_switches(); 313 printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", 314 option_switches, ··· 386 return -EIO; 387 } 388 } 389 return 0; 390 } 391 ··· 414 return -EIO; 415 } 416 } 417 return 0; 418 } 419 ··· 425 { 426 /* user land ping */ 427 pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); 428 return 0; 429 } 430 ··· 438 return -EINVAL; 439 440 heartbeat = t; 441 return 0; 442 } 443 444 static int pcwd_get_status(int *status) 445 { 446 - int card_status; 447 448 *status=0; 449 spin_lock(&pcwd_private.io_lock); ··· 456 /* Rev A cards return status information from 457 * the base register, which is used for the 458 * temperature in other cards. */ 459 - card_status = inb(pcwd_private.io_addr); 460 else { 461 /* Rev C cards return card status in the base 462 * address + 1 register. And use different bits 463 * to indicate a card initiated reset, and an 464 * over-temperature condition. And the reboot 465 * status can be reset. */ 466 - card_status = inb(pcwd_private.io_addr + 1); 467 } 468 spin_unlock(&pcwd_private.io_lock); 469 470 if (pcwd_private.revision == PCWD_REVISION_A) { 471 - if (card_status & WD_WDRST) 472 *status |= WDIOF_CARDRESET; 473 474 - if (card_status & WD_T110) { 475 *status |= WDIOF_OVERHEAT; 476 if (temp_panic) { 477 printk (KERN_INFO PFX "Temperature overheat trip!\n"); 478 kernel_power_off(); 479 } 480 } 481 } else { 482 - if (card_status & WD_REVC_WTRP) 483 *status |= WDIOF_CARDRESET; 484 485 - if (card_status & WD_REVC_TTRP) { 486 *status |= WDIOF_OVERHEAT; 487 if (temp_panic) { 488 printk (KERN_INFO PFX "Temperature overheat trip!\n"); 489 kernel_power_off(); 490 } 491 } 492 } ··· 498 499 static int pcwd_clear_status(void) 500 { 501 if (pcwd_private.revision == PCWD_REVISION_C) { 502 spin_lock(&pcwd_private.io_lock); 503 - outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */ 504 spin_unlock(&pcwd_private.io_lock); 505 } 506 return 0; ··· 539 spin_lock(&pcwd_private.io_lock); 540 *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; 541 spin_unlock(&pcwd_private.io_lock); 542 543 return 0; 544 } ··· 663 static int pcwd_open(struct inode *inode, struct file *file) 664 { 665 if (!atomic_dec_and_test(&open_allowed) ) { 666 atomic_inc( &open_allowed ); 667 return -EBUSY; 668 } ··· 988 { 989 if (pcwd_private.io_addr) 990 pcwatchdog_exit(); 991 - return; 992 } 993 994 module_init(pcwd_init_module);
··· 66 #include <linux/fs.h> /* For file operations */ 67 #include <linux/ioport.h> /* For io-port access */ 68 #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 69 70 #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ 71 #include <asm/io.h> /* For inb/outb/... */ 72 73 /* Module and version information */ 74 + #define WATCHDOG_VERSION "1.17" 75 + #define WATCHDOG_DATE "12 Feb 2006" 76 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" 77 #define WATCHDOG_NAME "pcwd" 78 #define PFX WATCHDOG_NAME ": " ··· 96 * PCI-PC Watchdog card. 97 */ 98 /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ 99 + #define WD_WDRST 0x01 /* Previously reset state */ 100 + #define WD_T110 0x02 /* Temperature overheat sense */ 101 + #define WD_HRTBT 0x04 /* Heartbeat sense */ 102 + #define WD_RLY2 0x08 /* External relay triggered */ 103 + #define WD_SRLY2 0x80 /* Software external relay triggered */ 104 /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ 105 + #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ 106 + #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ 107 + #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ 108 + #define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */ 109 + #define WD_REVC_RL1A 0x10 /* Relay 1 active */ 110 + #define WD_REVC_R2DS 0x40 /* Relay 2 disable */ 111 + #define WD_REVC_RLY2 0x80 /* Relay 2 activated? */ 112 /* Port 2 : Control Status #2 */ 113 #define WD_WDIS 0x10 /* Watchdog Disabled */ 114 #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ ··· 122 #define CMD_ISA_VERSION_HUNDRETH 0x03 123 #define CMD_ISA_VERSION_MINOR 0x04 124 #define CMD_ISA_SWITCH_SETTINGS 0x05 125 + #define CMD_ISA_RESET_PC 0x06 126 + #define CMD_ISA_ARM_0 0x07 127 + #define CMD_ISA_ARM_30 0x08 128 + #define CMD_ISA_ARM_60 0x09 129 #define CMD_ISA_DELAY_TIME_2SECS 0x0A 130 #define CMD_ISA_DELAY_TIME_4SECS 0x0B 131 #define CMD_ISA_DELAY_TIME_8SECS 0x0C 132 + #define CMD_ISA_RESET_RELAYS 0x0D 133 134 /* 135 * We are using an kernel timer to do the pinging of the watchdog ··· 142 static char expect_close; 143 static int temp_panic; 144 static struct { /* this is private data for each ISA-PC watchdog card */ 145 + char fw_ver_str[6]; /* The cards firmware version */ 146 int revision; /* The card's revision */ 147 int supports_temp; /* Wether or not the card has a temperature device */ 148 int command_mode; /* Wether or not the card is in command mode */ ··· 153 } pcwd_private; 154 155 /* module parameters */ 156 + #define QUIET 0 /* Default */ 157 + #define VERBOSE 1 /* Verbose */ 158 + #define DEBUG 2 /* print fancy stuff too */ 159 + static int debug = QUIET; 160 + module_param(debug, int, 0); 161 + MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); 162 + 163 #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ 164 static int heartbeat = WATCHDOG_HEARTBEAT; 165 module_param(heartbeat, int, 0); ··· 172 int control_status; 173 int port0, last_port0; /* Double read for stabilising */ 174 175 + if (debug >= DEBUG) 176 + printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n", 177 + cmd); 178 + 179 /* The WCMD bit must be 1 and the command is only 4 bits in size */ 180 control_status = (cmd & 0x0F) | WD_WCMD; 181 outb_p(control_status, pcwd_private.io_addr + 2); ··· 187 188 udelay (250); 189 } 190 + 191 + if (debug >= DEBUG) 192 + printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n", 193 + cmd, port0, last_port0); 194 195 return port0; 196 } ··· 214 spin_unlock(&pcwd_private.io_lock); 215 pcwd_private.command_mode = found; 216 217 + if (debug >= DEBUG) 218 + printk(KERN_DEBUG PFX "command_mode=%d\n", 219 + pcwd_private.command_mode); 220 + 221 return(found); 222 } 223 ··· 226 spin_unlock(&pcwd_private.io_lock); 227 228 pcwd_private.command_mode = 0; 229 + 230 + if (debug >= DEBUG) 231 + printk(KERN_DEBUG PFX "command_mode=%d\n", 232 + pcwd_private.command_mode); 233 } 234 235 static inline void pcwd_check_temperature_support(void) ··· 234 pcwd_private.supports_temp = 1; 235 } 236 237 + static inline void pcwd_get_firmware(void) 238 { 239 int one, ten, hund, minor; 240 241 + strcpy(pcwd_private.fw_ver_str, "ERROR"); 242 243 if (set_command_mode()) { 244 one = send_isa_command(CMD_ISA_VERSION_INTEGER); 245 ten = send_isa_command(CMD_ISA_VERSION_TENTH); 246 hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); 247 minor = send_isa_command(CMD_ISA_VERSION_MINOR); 248 + sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor); 249 } 250 unset_command_mode(); 251 + 252 + return; 253 } 254 255 static inline int pcwd_get_option_switches(void) ··· 272 273 static void pcwd_show_card_info(void) 274 { 275 int option_switches; 276 277 /* Get some extra info from the hardware (in command/debug/diag mode) */ 278 if (pcwd_private.revision == PCWD_REVISION_A) 279 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); 280 else if (pcwd_private.revision == PCWD_REVISION_C) { 281 + pcwd_get_firmware(); 282 printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", 283 + pcwd_private.io_addr, pcwd_private.fw_ver_str); 284 option_switches = pcwd_get_option_switches(); 285 printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", 286 option_switches, ··· 362 return -EIO; 363 } 364 } 365 + 366 + if (debug >= VERBOSE) 367 + printk(KERN_DEBUG PFX "Watchdog started\n"); 368 + 369 return 0; 370 } 371 ··· 386 return -EIO; 387 } 388 } 389 + 390 + if (debug >= VERBOSE) 391 + printk(KERN_DEBUG PFX "Watchdog stopped\n"); 392 + 393 return 0; 394 } 395 ··· 393 { 394 /* user land ping */ 395 pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); 396 + 397 + if (debug >= DEBUG) 398 + printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); 399 + 400 return 0; 401 } 402 ··· 402 return -EINVAL; 403 404 heartbeat = t; 405 + 406 + if (debug >= VERBOSE) 407 + printk(KERN_DEBUG PFX "New heartbeat: %d\n", 408 + heartbeat); 409 + 410 return 0; 411 } 412 413 static int pcwd_get_status(int *status) 414 { 415 + int control_status; 416 417 *status=0; 418 spin_lock(&pcwd_private.io_lock); ··· 415 /* Rev A cards return status information from 416 * the base register, which is used for the 417 * temperature in other cards. */ 418 + control_status = inb(pcwd_private.io_addr); 419 else { 420 /* Rev C cards return card status in the base 421 * address + 1 register. And use different bits 422 * to indicate a card initiated reset, and an 423 * over-temperature condition. And the reboot 424 * status can be reset. */ 425 + control_status = inb(pcwd_private.io_addr + 1); 426 } 427 spin_unlock(&pcwd_private.io_lock); 428 429 if (pcwd_private.revision == PCWD_REVISION_A) { 430 + if (control_status & WD_WDRST) 431 *status |= WDIOF_CARDRESET; 432 433 + if (control_status & WD_T110) { 434 *status |= WDIOF_OVERHEAT; 435 if (temp_panic) { 436 printk (KERN_INFO PFX "Temperature overheat trip!\n"); 437 kernel_power_off(); 438 + /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ 439 } 440 } 441 } else { 442 + if (control_status & WD_REVC_WTRP) 443 *status |= WDIOF_CARDRESET; 444 445 + if (control_status & WD_REVC_TTRP) { 446 *status |= WDIOF_OVERHEAT; 447 if (temp_panic) { 448 printk (KERN_INFO PFX "Temperature overheat trip!\n"); 449 kernel_power_off(); 450 + /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ 451 } 452 } 453 } ··· 455 456 static int pcwd_clear_status(void) 457 { 458 + int control_status; 459 + 460 if (pcwd_private.revision == PCWD_REVISION_C) { 461 spin_lock(&pcwd_private.io_lock); 462 + 463 + if (debug >= VERBOSE) 464 + printk(KERN_INFO PFX "clearing watchdog trip status\n"); 465 + 466 + control_status = inb_p(pcwd_private.io_addr + 1); 467 + 468 + if (debug >= DEBUG) { 469 + printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); 470 + printk(KERN_DEBUG PFX "sending: 0x%02x\n", 471 + (control_status & WD_REVC_R2DS)); 472 + } 473 + 474 + /* clear reset status & Keep Relay 2 disable state as it is */ 475 + outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1); 476 + 477 spin_unlock(&pcwd_private.io_lock); 478 } 479 return 0; ··· 480 spin_lock(&pcwd_private.io_lock); 481 *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; 482 spin_unlock(&pcwd_private.io_lock); 483 + 484 + if (debug >= DEBUG) { 485 + printk(KERN_DEBUG PFX "temperature is: %d F\n", 486 + *temperature); 487 + } 488 489 return 0; 490 } ··· 599 static int pcwd_open(struct inode *inode, struct file *file) 600 { 601 if (!atomic_dec_and_test(&open_allowed) ) { 602 + if (debug >= VERBOSE) 603 + printk(KERN_ERR PFX "Attempt to open already opened device.\n"); 604 atomic_inc( &open_allowed ); 605 return -EBUSY; 606 } ··· 922 { 923 if (pcwd_private.io_addr) 924 pcwatchdog_exit(); 925 + 926 + printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); 927 } 928 929 module_init(pcwd_init_module);
+2 -1
drivers/char/watchdog/pcwd_usb.c
··· 705 err_out_unregister_reboot: 706 unregister_reboot_notifier(&usb_pcwd_notifier); 707 error: 708 - usb_pcwd_delete (usb_pcwd); 709 usb_pcwd_device = NULL; 710 return retval; 711 }
··· 705 err_out_unregister_reboot: 706 unregister_reboot_notifier(&usb_pcwd_notifier); 707 error: 708 + if (usb_pcwd) 709 + usb_pcwd_delete(usb_pcwd); 710 usb_pcwd_device = NULL; 711 return retval; 712 }