Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+28 −13
Original line number Diff line number Diff line
/*
 *	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);