aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2010-04-19 08:38:25 -0400
committerWim Van Sebroeck <wim@iguana.be>2010-05-25 05:05:56 -0400
commit7e6811daa662fc4eb87ddfb3ea0ea9d782044157 (patch)
treee6fbeb872b81bd2ed5e808535b6d3e216efa22ac /drivers/watchdog
parentbb6f36070cf53ebf08383a026e1d3a437cb310d1 (diff)
iTCO_wdt: fix TCO V1 timeout values and limits
For TCO V1 devices the programmed timeout was twice too long because the fact that the TCO V1 timer needs to count down twice before triggering the watchdog, wasn't accounted for. Also the timeout values in the module description and error message were clarified. And the _STS registers are 16 bit instead of 8 bit. Signed-off-by: Pádraig Brady <P@draigBrady.com> Tested-by: Simon Kagstrom <simon.kagstrom@netinsight.se> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c11
-rw-r--r--drivers/watchdog/iTCO_wdt.c29
2 files changed, 21 insertions, 19 deletions
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index 5133bca5ccbe..481d1ad43464 100644
--- a/drivers/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -101,13 +101,6 @@ static void supermicro_old_pre_stop(unsigned long acpibase)
101 outl(val32, SMI_EN); /* Needed to deactivate watchdog */ 101 outl(val32, SMI_EN); /* Needed to deactivate watchdog */
102} 102}
103 103
104static void supermicro_old_pre_keepalive(unsigned long acpibase)
105{
106 /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
107 /* Clear "Expire Flag" (Bit 3 of TC01_STS register) */
108 outb(0x08, TCO1_STS);
109}
110
111/* 104/*
112 * Vendor Support: 2 105 * Vendor Support: 2
113 * Board: Super Micro Computer Inc. P4SBx, P4DPx 106 * Board: Super Micro Computer Inc. P4SBx, P4DPx
@@ -337,9 +330,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_stop);
337 330
338void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat) 331void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat)
339{ 332{
340 if (vendorsupport == SUPERMICRO_OLD_BOARD) 333 if (vendorsupport == SUPERMICRO_NEW_BOARD)
341 supermicro_old_pre_keepalive(acpibase);
342 else if (vendorsupport == SUPERMICRO_NEW_BOARD)
343 supermicro_new_pre_set_heartbeat(heartbeat); 334 supermicro_new_pre_set_heartbeat(heartbeat);
344} 335}
345EXPORT_SYMBOL(iTCO_vendor_pre_keepalive); 336EXPORT_SYMBOL(iTCO_vendor_pre_keepalive);
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 8da886035374..69de8713b8e4 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -40,7 +40,7 @@
40 40
41/* Module and version information */ 41/* Module and version information */
42#define DRV_NAME "iTCO_wdt" 42#define DRV_NAME "iTCO_wdt"
43#define DRV_VERSION "1.05" 43#define DRV_VERSION "1.06"
44#define PFX DRV_NAME ": " 44#define PFX DRV_NAME ": "
45 45
46/* Includes */ 46/* Includes */
@@ -391,8 +391,8 @@ static struct platform_device *iTCO_wdt_platform_device;
391#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 391#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
392static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 392static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
393module_param(heartbeat, int, 0); 393module_param(heartbeat, int, 0);
394MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " 394MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
395 "(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" 395 "5..76 (TCO v1) or 3..614 (TCO v2), default="
396 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 396 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
397 397
398static int nowayout = WATCHDOG_NOWAYOUT; 398static int nowayout = WATCHDOG_NOWAYOUT;
@@ -523,8 +523,13 @@ static int iTCO_wdt_keepalive(void)
523 /* Reload the timer by writing to the TCO Timer Counter register */ 523 /* Reload the timer by writing to the TCO Timer Counter register */
524 if (iTCO_wdt_private.iTCO_version == 2) 524 if (iTCO_wdt_private.iTCO_version == 2)
525 outw(0x01, TCO_RLD); 525 outw(0x01, TCO_RLD);
526 else if (iTCO_wdt_private.iTCO_version == 1) 526 else if (iTCO_wdt_private.iTCO_version == 1) {
527 /* Reset the timeout status bit so that the timer
528 * needs to count down twice again before rebooting */
529 outw(0x0008, TCO1_STS); /* write 1 to clear bit */
530
527 outb(0x01, TCO_RLD); 531 outb(0x01, TCO_RLD);
532 }
528 533
529 spin_unlock(&iTCO_wdt_private.io_lock); 534 spin_unlock(&iTCO_wdt_private.io_lock);
530 return 0; 535 return 0;
@@ -537,6 +542,11 @@ static int iTCO_wdt_set_heartbeat(int t)
537 unsigned int tmrval; 542 unsigned int tmrval;
538 543
539 tmrval = seconds_to_ticks(t); 544 tmrval = seconds_to_ticks(t);
545
546 /* For TCO v1 the timer counts down twice before rebooting */
547 if (iTCO_wdt_private.iTCO_version == 1)
548 tmrval /= 2;
549
540 /* from the specs: */ 550 /* from the specs: */
541 /* "Values of 0h-3h are ignored and should not be attempted" */ 551 /* "Values of 0h-3h are ignored and should not be attempted" */
542 if (tmrval < 0x04) 552 if (tmrval < 0x04)
@@ -593,6 +603,8 @@ static int iTCO_wdt_get_timeleft(int *time_left)
593 spin_lock(&iTCO_wdt_private.io_lock); 603 spin_lock(&iTCO_wdt_private.io_lock);
594 val8 = inb(TCO_RLD); 604 val8 = inb(TCO_RLD);
595 val8 &= 0x3f; 605 val8 &= 0x3f;
606 if (!(inw(TCO1_STS) & 0x0008))
607 val8 += (inb(TCOv1_TMR) & 0x3f);
596 spin_unlock(&iTCO_wdt_private.io_lock); 608 spin_unlock(&iTCO_wdt_private.io_lock);
597 609
598 *time_left = (val8 * 6) / 10; 610 *time_left = (val8 * 6) / 10;
@@ -832,9 +844,9 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
832 TCOBASE); 844 TCOBASE);
833 845
834 /* Clear out the (probably old) status */ 846 /* Clear out the (probably old) status */
835 outb(8, TCO1_STS); /* Clear the Time Out Status bit */ 847 outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
836 outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */ 848 outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
837 outb(4, TCO2_STS); /* Clear BOOT_STS bit */ 849 outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
838 850
839 /* Make sure the watchdog is not running */ 851 /* Make sure the watchdog is not running */
840 iTCO_wdt_stop(); 852 iTCO_wdt_stop();
@@ -844,8 +856,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
844 if (iTCO_wdt_set_heartbeat(heartbeat)) { 856 if (iTCO_wdt_set_heartbeat(heartbeat)) {
845 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); 857 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
846 printk(KERN_INFO PFX 858 printk(KERN_INFO PFX
847 "heartbeat value must be 2 < heartbeat < 39 (TCO v1) " 859 "timeout value out of range, using %d\n", heartbeat);
848 "or 613 (TCO v2), using %d\n", heartbeat);
849 } 860 }
850 861
851 ret = misc_register(&iTCO_wdt_miscdev); 862 ret = misc_register(&iTCO_wdt_miscdev);