Commit 7e6811daa662fc4eb87ddfb3ea0ea9d782044157

Authored by Pádraig Brady
Committed by Wim Van Sebroeck
1 parent bb6f36070c

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>

Showing 2 changed files with 21 additions and 19 deletions Side-by-side Diff

drivers/watchdog/iTCO_vendor_support.c
... ... @@ -101,13 +101,6 @@
101 101 outl(val32, SMI_EN); /* Needed to deactivate watchdog */
102 102 }
103 103  
104   -static 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 105 * Vendor Support: 2
113 106 * Board: Super Micro Computer Inc. P4SBx, P4DPx
... ... @@ -337,9 +330,7 @@
337 330  
338 331 void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat)
339 332 {
340   - if (vendorsupport == SUPERMICRO_OLD_BOARD)
341   - supermicro_old_pre_keepalive(acpibase);
342   - else if (vendorsupport == SUPERMICRO_NEW_BOARD)
  333 + if (vendorsupport == SUPERMICRO_NEW_BOARD)
343 334 supermicro_new_pre_set_heartbeat(heartbeat);
344 335 }
345 336 EXPORT_SYMBOL(iTCO_vendor_pre_keepalive);
drivers/watchdog/iTCO_wdt.c
... ... @@ -40,7 +40,7 @@
40 40  
41 41 /* Module and version information */
42 42 #define DRV_NAME "iTCO_wdt"
43   -#define DRV_VERSION "1.05"
  43 +#define DRV_VERSION "1.06"
44 44 #define PFX DRV_NAME ": "
45 45  
46 46 /* Includes */
... ... @@ -391,8 +391,8 @@
391 391 #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
392 392 static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
393 393 module_param(heartbeat, int, 0);
394   -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
395   - "(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default="
  394 +MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
  395 + "5..76 (TCO v1) or 3..614 (TCO v2), default="
396 396 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
397 397  
398 398 static int nowayout = WATCHDOG_NOWAYOUT;
399 399  
... ... @@ -523,8 +523,13 @@
523 523 /* Reload the timer by writing to the TCO Timer Counter register */
524 524 if (iTCO_wdt_private.iTCO_version == 2)
525 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 531 outb(0x01, TCO_RLD);
  532 + }
528 533  
529 534 spin_unlock(&iTCO_wdt_private.io_lock);
530 535 return 0;
... ... @@ -537,6 +542,11 @@
537 542 unsigned int tmrval;
538 543  
539 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 550 /* from the specs: */
541 551 /* "Values of 0h-3h are ignored and should not be attempted" */
542 552 if (tmrval < 0x04)
... ... @@ -593,6 +603,8 @@
593 603 spin_lock(&iTCO_wdt_private.io_lock);
594 604 val8 = inb(TCO_RLD);
595 605 val8 &= 0x3f;
  606 + if (!(inw(TCO1_STS) & 0x0008))
  607 + val8 += (inb(TCOv1_TMR) & 0x3f);
596 608 spin_unlock(&iTCO_wdt_private.io_lock);
597 609  
598 610 *time_left = (val8 * 6) / 10;
... ... @@ -832,9 +844,9 @@
832 844 TCOBASE);
833 845  
834 846 /* Clear out the (probably old) status */
835   - outb(8, TCO1_STS); /* Clear the Time Out Status bit */
836   - outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */
837   - outb(4, TCO2_STS); /* Clear BOOT_STS bit */
  847 + outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
  848 + outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
  849 + outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
838 850  
839 851 /* Make sure the watchdog is not running */
840 852 iTCO_wdt_stop();
... ... @@ -844,8 +856,7 @@
844 856 if (iTCO_wdt_set_heartbeat(heartbeat)) {
845 857 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
846 858 printk(KERN_INFO PFX
847   - "heartbeat value must be 2 < heartbeat < 39 (TCO v1) "
848   - "or 613 (TCO v2), using %d\n", heartbeat);
  859 + "timeout value out of range, using %d\n", heartbeat);
849 860 }
850 861  
851 862 ret = misc_register(&iTCO_wdt_miscdev);