Commit 01df0e3a authored by Wim Van Sebroeck's avatar Wim Van Sebroeck Committed by Linus Torvalds

[PATCH] i8xx_tco.c: arm watchdog only when started

i8xx_tco.c v0.08: only "arm" the watchdog when the watchdog has been
started.  (Kernel Bug 4251: system reset when battery is read and i8xx_tco
driver loaded)
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 00dd1e43
/* /*
* i8xx_tco 0.07: TCO timer driver for i8xx chipsets * i8xx_tco: TCO timer driver for i8xx chipsets
* *
* (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
* http://www.kernelconcepts.de * http://www.kernelconcepts.de
...@@ -63,6 +63,9 @@ ...@@ -63,6 +63,9 @@
* 20050128 Wim Van Sebroeck <wim@iguana.be> * 20050128 Wim Van Sebroeck <wim@iguana.be>
* 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
* chipsets. Also added support for the "undocumented" ICH7 chipset. * chipsets. Also added support for the "undocumented" ICH7 chipset.
* 20050807 Wim Van Sebroeck <wim@iguana.be>
* 0.08 Make sure that the watchdog is only "armed" when started.
* (Kernel Bug 4251)
*/ */
/* /*
...@@ -87,7 +90,7 @@ ...@@ -87,7 +90,7 @@
#include "i8xx_tco.h" #include "i8xx_tco.h"
/* Module and version information */ /* Module and version information */
#define TCO_VERSION "0.07" #define TCO_VERSION "0.08"
#define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_MODULE_NAME "i8xx TCO timer"
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
#define PFX TCO_MODULE_NAME ": " #define PFX TCO_MODULE_NAME ": "
...@@ -125,10 +128,18 @@ static int tco_timer_start (void) ...@@ -125,10 +128,18 @@ static int tco_timer_start (void)
unsigned char val; unsigned char val;
spin_lock(&tco_lock); spin_lock(&tco_lock);
/* disable chipset's NO_REBOOT bit */
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
val &= 0xfd;
pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
val = inb (TCO1_CNT + 1); val = inb (TCO1_CNT + 1);
val &= 0xf7; val &= 0xf7;
outb (val, TCO1_CNT + 1); outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1); val = inb (TCO1_CNT + 1);
spin_unlock(&tco_lock); spin_unlock(&tco_lock);
if (val & 0x08) if (val & 0x08)
...@@ -138,13 +149,20 @@ static int tco_timer_start (void) ...@@ -138,13 +149,20 @@ static int tco_timer_start (void)
static int tco_timer_stop (void) static int tco_timer_stop (void)
{ {
unsigned char val; unsigned char val, val1;
spin_lock(&tco_lock); spin_lock(&tco_lock);
/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
val = inb (TCO1_CNT + 1); val = inb (TCO1_CNT + 1);
val |= 0x08; val |= 0x08;
outb (val, TCO1_CNT + 1); outb (val, TCO1_CNT + 1);
val = inb (TCO1_CNT + 1); val = inb (TCO1_CNT + 1);
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
val1 |= 0x02;
pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
spin_unlock(&tco_lock); spin_unlock(&tco_lock);
if ((val & 0x08) == 0) if ((val & 0x08) == 0)
...@@ -155,6 +173,7 @@ static int tco_timer_stop (void) ...@@ -155,6 +173,7 @@ static int tco_timer_stop (void)
static int tco_timer_keepalive (void) static int tco_timer_keepalive (void)
{ {
spin_lock(&tco_lock); spin_lock(&tco_lock);
/* Reload the timer by writing to the TCO Timer Reload register */
outb (0x01, TCO1_RLD); outb (0x01, TCO1_RLD);
spin_unlock(&tco_lock); spin_unlock(&tco_lock);
return 0; return 0;
...@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void) ...@@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
printk (KERN_ERR PFX "failed to get TCOBASE address\n"); printk (KERN_ERR PFX "failed to get TCOBASE address\n");
return 0; return 0;
} }
/*
* Check chipset's NO_REBOOT bit /* Check chipset's NO_REBOOT bit */
*/
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
if (val1 & 0x02) { if (val1 & 0x02) {
val1 &= 0xfd; val1 &= 0xfd;
...@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void) ...@@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
return 0; /* Cannot reset NO_REBOOT bit */ return 0; /* Cannot reset NO_REBOOT bit */
} }
} }
/* Disable reboots untill the watchdog starts */
val1 |= 0x02;
pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
/* Set the TCO_EN bit in SMI_EN register */ /* Set the TCO_EN bit in SMI_EN register */
if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
...@@ -505,17 +527,10 @@ static int __init watchdog_init (void) ...@@ -505,17 +527,10 @@ static int __init watchdog_init (void)
static void __exit watchdog_cleanup (void) static void __exit watchdog_cleanup (void)
{ {
u8 val;
/* Stop the timer before we leave */ /* Stop the timer before we leave */
if (!nowayout) if (!nowayout)
tco_timer_stop (); tco_timer_stop ();
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
val |= 0x02;
pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
/* Deregister */ /* Deregister */
misc_deregister (&i8xx_tco_miscdev); misc_deregister (&i8xx_tco_miscdev);
unregister_reboot_notifier(&i8xx_tco_notifier); unregister_reboot_notifier(&i8xx_tco_notifier);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment