mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
[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: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
00dd1e4339
commit
01df0e3a79
1 changed files with 28 additions and 13 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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.
|
||||
* http://www.kernelconcepts.de
|
||||
|
@ -63,6 +63,9 @@
|
|||
* 20050128 Wim Van Sebroeck <wim@iguana.be>
|
||||
* 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
|
||||
* 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 @@
|
|||
#include "i8xx_tco.h"
|
||||
|
||||
/* Module and version information */
|
||||
#define TCO_VERSION "0.07"
|
||||
#define TCO_VERSION "0.08"
|
||||
#define TCO_MODULE_NAME "i8xx TCO timer"
|
||||
#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
|
||||
#define PFX TCO_MODULE_NAME ": "
|
||||
|
@ -125,10 +128,18 @@ static int tco_timer_start (void)
|
|||
unsigned char val;
|
||||
|
||||
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 &= 0xf7;
|
||||
outb (val, TCO1_CNT + 1);
|
||||
val = inb (TCO1_CNT + 1);
|
||||
|
||||
spin_unlock(&tco_lock);
|
||||
|
||||
if (val & 0x08)
|
||||
|
@ -138,13 +149,20 @@ static int tco_timer_start (void)
|
|||
|
||||
static int tco_timer_stop (void)
|
||||
{
|
||||
unsigned char val;
|
||||
unsigned char val, val1;
|
||||
|
||||
spin_lock(&tco_lock);
|
||||
/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
|
||||
val = inb (TCO1_CNT + 1);
|
||||
val |= 0x08;
|
||||
outb (val, 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);
|
||||
|
||||
if ((val & 0x08) == 0)
|
||||
|
@ -155,6 +173,7 @@ static int tco_timer_stop (void)
|
|||
static int tco_timer_keepalive (void)
|
||||
{
|
||||
spin_lock(&tco_lock);
|
||||
/* Reload the timer by writing to the TCO Timer Reload register */
|
||||
outb (0x01, TCO1_RLD);
|
||||
spin_unlock(&tco_lock);
|
||||
return 0;
|
||||
|
@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
|
|||
printk (KERN_ERR PFX "failed to get TCOBASE address\n");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check chipset's NO_REBOOT bit
|
||||
*/
|
||||
|
||||
/* Check chipset's NO_REBOOT bit */
|
||||
pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
|
||||
if (val1 & 0x02) {
|
||||
val1 &= 0xfd;
|
||||
|
@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
|
|||
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 */
|
||||
if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
|
||||
printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
|
||||
|
@ -505,17 +527,10 @@ static int __init watchdog_init (void)
|
|||
|
||||
static void __exit watchdog_cleanup (void)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
/* Stop the timer before we leave */
|
||||
if (!nowayout)
|
||||
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 */
|
||||
misc_deregister (&i8xx_tco_miscdev);
|
||||
unregister_reboot_notifier(&i8xx_tco_notifier);
|
||||
|
|
Loading…
Reference in a new issue