git: ee900888c42f - main - dwwdt: make it actually useful
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 11 Jan 2022 13:57:06 UTC
The branch main has been updated by avg: URL: https://cgit.FreeBSD.org/src/commit/?id=ee900888c42f12f7ccf73e5a320446da4661a0e9 commit ee900888c42f12f7ccf73e5a320446da4661a0e9 Author: Andriy Gapon <avg@FreeBSD.org> AuthorDate: 2022-01-11 13:56:07 +0000 Commit: Andriy Gapon <avg@FreeBSD.org> CommitDate: 2022-01-11 13:56:07 +0000 dwwdt: make it actually useful Flip dwwdt_prevent_restart to false. What's the use of a watchdog if it does not restart a hung system? Add a knob for panic-ing on the first timeout, resetting on the second one. This can be useful if interrupts can still work, otherwise a reset recovers a system without any aid for debugging the hang. The change also doubles the timeout that's programmed into the hardware. The previous version of the code always had the interrupt on the first timeout enabled, but it took no action on it. Only the second timeout could be configured to reset the system. So, the hardware timeout was set to a half of the user requested timeout. But now,we can take a corrective action on the first timeout, so we use the user requested timeout. While here, define boolean sysctl-s as such. Reviewed by: manu MFC after: 3 weeks Differential Revision: https://reviews.freebsd.org/D33534 --- sys/dev/dwwdt/dwwdt.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/sys/dev/dwwdt/dwwdt.c b/sys/dev/dwwdt/dwwdt.c index 4eab26ef2915..5cc20c3c9d2f 100644 --- a/sys/dev/dwwdt/dwwdt.c +++ b/sys/dev/dwwdt/dwwdt.c @@ -93,15 +93,20 @@ static struct ofw_compat_data compat_data[] = { SYSCTL_NODE(_dev, OID_AUTO, dwwdt, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "Synopsys Designware watchdog timer"); -/* Setting this to 0 enables full restart mode. */ -static uint32_t dwwdt_prevent_restart = 1; -SYSCTL_UINT(_dev_dwwdt, OID_AUTO, prevent_restart, CTLFLAG_RW | CTLFLAG_MPSAFE, - &dwwdt_prevent_restart, 1, - "Prevent system restart (0 - Disabled; 1 - Enabled)"); -static uint32_t dwwdt_debug_enabled = 0; -SYSCTL_UINT(_dev_dwwdt, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_MPSAFE, - &dwwdt_debug_enabled, 1, "Debug mode (0 - Disabled; 1 - Enabled)"); +/* Setting this to true disables full restart mode. */ +static bool dwwdt_prevent_restart = false; +SYSCTL_BOOL(_dev_dwwdt, OID_AUTO, prevent_restart, CTLFLAG_RW | CTLFLAG_MPSAFE, + &dwwdt_prevent_restart, 0, "Disable system reset on timeout"); + +static bool dwwdt_debug_enabled = false; +SYSCTL_BOOL(_dev_dwwdt, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_MPSAFE, + &dwwdt_debug_enabled, 0, "Enable debug mode"); + +static bool dwwdt_panic_first = true; +SYSCTL_BOOL(_dev_dwwdt, OID_AUTO, panic_first, CTLFLAG_RW | CTLFLAG_MPSAFE, + &dwwdt_panic_first, 0, + "Try to panic on timeout, reset on another timeout"); static int dwwdt_probe(device_t); static int dwwdt_attach(device_t); @@ -181,13 +186,17 @@ dwwdt_intr(void *arg) KASSERT((DWWDT_READ4(sc, DWWDT_STAT) & DWWDT_STAT_STATUS) != 0, ("Missing interrupt status bit?")); - if (dwwdt_prevent_restart != 0 || sc->sc_status == DWWDT_STOPPED) { + if (dwwdt_prevent_restart || sc->sc_status == DWWDT_STOPPED) { /* * Confirm interrupt reception. Restart counter. * This also emulates stopping watchdog. */ (void)DWWDT_READ4(sc, DWWDT_EOI); + return; } + + if (dwwdt_panic_first) + panic("dwwdt pre-timeout interrupt"); } static void @@ -199,7 +208,7 @@ dwwdt_event(void *arg, unsigned int cmd, int *error) int val; timeout = cmd & WD_INTERVAL; - val = MAX(0, timeout + exponent - DWWDT_EXP_OFFSET); + val = MAX(0, timeout + exponent - DWWDT_EXP_OFFSET + 1); dwwdt_stop(sc); if (cmd == 0 || val > 0x0f) { @@ -341,7 +350,7 @@ dwwdt_shutdown(device_t dev) sc = device_get_softc(dev); /* Prevent restarts during shutdown. */ - dwwdt_prevent_restart = 1; + dwwdt_prevent_restart = true; dwwdt_stop(sc); return (bus_generic_shutdown(dev)); }