diff options
| author | matt <matt@NetBSD.org> | 2011-01-04 01:51:06 +0000 |
|---|---|---|
| committer | matt <matt@NetBSD.org> | 2011-01-04 01:51:06 +0000 |
| commit | 02c8abc4c5dfdf8ca51b5ae5d4c2c48e9f1a9b74 (patch) | |
| tree | f3d840e1954e030d04018884d0f3df4e221593b8 /sys/dev/sysmon | |
| parent | 02ab78e696dc6808df0e7c3bae4fc9a2c708dd06 (diff) | |
add support for autostarting watchdogs (wdog was started by firmware
and can't be disabled). Add critical pool hooks for kernel tickled
watchdogs.
Diffstat (limited to 'sys/dev/sysmon')
| -rw-r--r-- | sys/dev/sysmon/sysmon_wdog.c | 45 | ||||
| -rw-r--r-- | sys/dev/sysmon/sysmonvar.h | 3 |
2 files changed, 34 insertions, 14 deletions
diff --git a/sys/dev/sysmon/sysmon_wdog.c b/sys/dev/sysmon/sysmon_wdog.c index 86ddbadcfa0..1c05dff43ca 100644 --- a/sys/dev/sysmon/sysmon_wdog.c +++ b/sys/dev/sysmon/sysmon_wdog.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_wdog.c,v 1.24 2007/12/16 21:07:45 dyoung Exp $ */ +/* $NetBSD: sysmon_wdog.c,v 1.25 2011/01/04 01:51:06 matt Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.24 2007/12/16 21:07:45 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.25 2011/01/04 01:51:06 matt Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -64,11 +64,13 @@ static kcondvar_t sysmon_wdog_cv; static struct sysmon_wdog *sysmon_armed_wdog; static callout_t sysmon_wdog_callout; static void *sysmon_wdog_sdhook; +static void *sysmon_wdog_cphook; struct sysmon_wdog *sysmon_wdog_find(const char *); void sysmon_wdog_release(struct sysmon_wdog *); int sysmon_wdog_setmode(struct sysmon_wdog *, int, u_int); void sysmon_wdog_ktickle(void *); +void sysmon_wdog_critpoll(void *); void sysmon_wdog_shutdown(void *); void sysmon_wdog_ref(struct sysmon_wdog *); @@ -78,6 +80,13 @@ sysmon_wdog_init(void) mutex_init(&sysmon_wdog_list_mtx, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sysmon_wdog_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); cv_init(&sysmon_wdog_cv, "wdogref"); + sysmon_wdog_sdhook = shutdownhook_establish(sysmon_wdog_shutdown, NULL); + if (sysmon_wdog_sdhook == NULL) + printf("WARNING: unable to register watchdog shutdown hook\n"); + sysmon_wdog_cphook = critpollhook_establish(sysmon_wdog_critpoll, NULL); + if (sysmon_wdog_cphook == NULL) + printf("WARNING: unable to register watchdog critpoll hook\n"); + callout_init(&sysmon_wdog_callout, 0); } /* @@ -89,17 +98,6 @@ int sysmonopen_wdog(dev_t dev, int flag, int mode, struct lwp *l) { - mutex_enter(&sysmon_wdog_list_mtx); - if (sysmon_wdog_sdhook == NULL) { - sysmon_wdog_sdhook = - shutdownhook_establish(sysmon_wdog_shutdown, NULL); - if (sysmon_wdog_sdhook == NULL) - printf("WARNING: unable to register watchdog " - "shutdown hook\n"); - callout_init(&sysmon_wdog_callout, 0); - } - mutex_exit(&sysmon_wdog_list_mtx); - return 0; } @@ -323,6 +321,27 @@ sysmon_wdog_unregister(struct sysmon_wdog *smw) } /* + * sysmon_wdog_critpoll: + * + * Perform critical operations during long polling periods + */ +void +sysmon_wdog_critpoll(void *arg) +{ + struct sysmon_wdog *smw = sysmon_armed_wdog; + + if (smw == NULL) + return; + + if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_KTICKLE) { + if ((*smw->smw_tickle)(smw) != 0) { + printf("WARNING: KERNEL TICKLE OF WATCHDOG %s " + "FAILED!\n", smw->smw_name); + } + } +} + +/* * sysmon_wdog_find: * * Find a watchdog device. We increase the reference diff --git a/sys/dev/sysmon/sysmonvar.h b/sys/dev/sysmon/sysmonvar.h index cd6cf429440..9fe9ef1f1bc 100644 --- a/sys/dev/sysmon/sysmonvar.h +++ b/sys/dev/sysmon/sysmonvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: sysmonvar.h,v 1.39 2010/04/11 01:12:28 pgoyette Exp $ */ +/* $NetBSD: sysmonvar.h,v 1.40 2011/01/04 01:51:06 matt Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -239,6 +239,7 @@ int sysmonopen_wdog(dev_t, int, int, struct lwp *); int sysmonclose_wdog(dev_t, int, int, struct lwp *); int sysmonioctl_wdog(dev_t, u_long, void *, int, struct lwp *); +int sysmon_wdog_setmode(struct sysmon_wdog *, int, u_int); int sysmon_wdog_register(struct sysmon_wdog *); int sysmon_wdog_unregister(struct sysmon_wdog *); |
