Skip to content

Commit cb01104

Browse files
jan-kiszkaWim Van Sebroeck
authored andcommitted
watchdog: iTCO_wdt: Account for rebooting on second timeout
This was already attempted to fix via 1fccb73: If the BIOS did not enable TCO SMIs, the timer definitely needs to trigger twice in order to cause a reboot. If TCO SMIs are on, as well as SMIs in general, we can continue to assume that the BIOS will perform a reboot on the first timeout. QEMU with its ICH9 and related BIOS falls into the former category, currently taking twice the configured timeout in order to reboot the machine. For iTCO version that fall under turn_SMI_watchdog_clear_off, this is also true and was currently only addressed for v1, irrespective of the turn_SMI_watchdog_clear_off value. Signed-off-by: Jan Kiszka <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]> Signed-off-by: Wim Van Sebroeck <[email protected]>
1 parent 5b606ae commit cb01104

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

drivers/watchdog/iTCO_wdt.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
#define TCOBASE(p) ((p)->tco_res->start)
7272
/* SMI Control and Enable Register */
7373
#define SMI_EN(p) ((p)->smi_res->start)
74+
#define TCO_EN (1 << 13)
75+
#define GBL_SMI_EN (1 << 0)
7476

7577
#define TCO_RLD(p) (TCOBASE(p) + 0x00) /* TCO Timer Reload/Curr. Value */
7678
#define TCOv1_TMR(p) (TCOBASE(p) + 0x01) /* TCOv1 Timer Initial Value*/
@@ -355,8 +357,12 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t)
355357

356358
tmrval = seconds_to_ticks(p, t);
357359

358-
/* For TCO v1 the timer counts down twice before rebooting */
359-
if (p->iTCO_version == 1)
360+
/*
361+
* If TCO SMIs are off, the timer counts down twice before rebooting.
362+
* Otherwise, the BIOS generally reboots when the SMI triggers.
363+
*/
364+
if (p->smi_res &&
365+
(SMI_EN(p) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN))
360366
tmrval /= 2;
361367

362368
/* from the specs: */
@@ -521,7 +527,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
521527
* Disables TCO logic generating an SMI#
522528
*/
523529
val32 = inl(SMI_EN(p));
524-
val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
530+
val32 &= ~TCO_EN; /* Turn off SMI clearing watchdog */
525531
outl(val32, SMI_EN(p));
526532
}
527533

0 commit comments

Comments
 (0)