[WATCHDOG] iTCO_wdt: fix memory corruption when RCBA is disabled by hardware

According to 9.1.33 on p.343 of ICH8.pdf RCBA can be disabled by
hardware if bit 0 of RCBA register is not set.

Perform correct check for this to prevent memory corruption under
some virtual machines where this feature is disabled.

Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Vasily Averin <vvs@openvz.org>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Denis V. Lunev 2009-06-05 15:13:08 +04:00 committed by Wim Van Sebroeck
parent e73a780272
commit de8cd9a306

View file

@ -666,6 +666,11 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
GCS = RCBA + ICH6_GCS(0x3410). */ GCS = RCBA + ICH6_GCS(0x3410). */
if (iTCO_wdt_private.iTCO_version == 2) { if (iTCO_wdt_private.iTCO_version == 2) {
pci_read_config_dword(pdev, 0xf0, &base_address); pci_read_config_dword(pdev, 0xf0, &base_address);
if ((base_address & 1) == 0) {
printk(KERN_ERR PFX "RCBA is disabled by harddware\n");
ret = -ENODEV;
goto out;
}
RCBA = base_address & 0xffffc000; RCBA = base_address & 0xffffc000;
iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4);
} }
@ -675,7 +680,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
"reboot disabled by hardware\n"); "reboot disabled by hardware\n");
ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
goto out; goto out_unmap;
} }
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */ /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
@ -686,7 +691,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
printk(KERN_ERR PFX printk(KERN_ERR PFX
"I/O address 0x%04lx already in use\n", SMI_EN); "I/O address 0x%04lx already in use\n", SMI_EN);
ret = -EIO; ret = -EIO;
goto out; goto out_unmap;
} }
/* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
val32 = inl(SMI_EN); val32 = inl(SMI_EN);
@ -742,9 +747,10 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
release_region(TCOBASE, 0x20); release_region(TCOBASE, 0x20);
unreg_smi_en: unreg_smi_en:
release_region(SMI_EN, 4); release_region(SMI_EN, 4);
out: out_unmap:
if (iTCO_wdt_private.iTCO_version == 2) if (iTCO_wdt_private.iTCO_version == 2)
iounmap(iTCO_wdt_private.gcs); iounmap(iTCO_wdt_private.gcs);
out:
pci_dev_put(iTCO_wdt_private.pdev); pci_dev_put(iTCO_wdt_private.pdev);
iTCO_wdt_private.ACPIBASE = 0; iTCO_wdt_private.ACPIBASE = 0;
return ret; return ret;