Convert swwdog(4) from a simple defpseudo device to a defpseudodev so
that we can attach a power management handler. The handler prevents a suspend if the watchdog is active, to be consistent with other watchdog drivers. As discussed on tech-kern.
This commit is contained in:
parent
95c959ca44
commit
01497b95ec
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: swwdog.4,v 1.4 2010/01/30 21:55:28 pooka Exp $
|
||||
.\" $NetBSD: swwdog.4,v 1.5 2010/07/22 14:10:14 pgoyette Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2004, 2005 Steven M. Bellovin
|
||||
.\" All rights reserved.
|
||||
|
@ -31,7 +31,7 @@
|
|||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd January 30, 2010
|
||||
.Dd July 21, 2010
|
||||
.\" Written by Steven M. Bellovin
|
||||
.Dt SWWDOG 4
|
||||
.Os
|
||||
|
@ -45,14 +45,26 @@ The
|
|||
.Nm
|
||||
driver provides a software watchdog timer that works with
|
||||
.Xr wdogctl 8 .
|
||||
If the timer expires, the system reboots unless the variable
|
||||
If the timer expires, the system reboots unless the boolean variable
|
||||
.Va swwdog_panic
|
||||
is non-zero; if it is, the system will panic instead.
|
||||
is
|
||||
.Dv true ;
|
||||
if it is, the system will panic instead.
|
||||
.Va swwdog_reboot
|
||||
is accessible as a
|
||||
.Xr sysctl 8
|
||||
variable, machdep.swwdog0.reboot and defaults to
|
||||
.Dv false .
|
||||
.Pp
|
||||
The default period of
|
||||
.Nm
|
||||
is 60 seconds.
|
||||
.Pp
|
||||
As with other watchdog timers, the
|
||||
.Nm
|
||||
driver prevents a system from suspending when the watchdog is armed.
|
||||
.Sh SEE ALSO
|
||||
.Xr sysctl 8
|
||||
.Xr wdogctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
@ -61,7 +73,10 @@ driver was written by
|
|||
.An Steven M. Bellovin .
|
||||
.Sh BUGS
|
||||
Only one watchdog timer can be active at any given time.
|
||||
Arguably, this is a bug in the watchdog timer framework.
|
||||
(Arguably, this is a bug in the watchdog timer framework.)
|
||||
Therefore, only a single instance of the
|
||||
.Nm
|
||||
device can be created.
|
||||
.Pp
|
||||
Kernel tickle mode is useless with
|
||||
.Nm
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.sysmon,v 1.11 2010/01/30 21:55:28 pooka Exp $
|
||||
# $NetBSD: files.sysmon,v 1.12 2010/07/22 14:10:15 pgoyette Exp $
|
||||
|
||||
define sysmon_taskq
|
||||
file dev/sysmon/sysmon_taskq.c sysmon_taskq needs-flag
|
||||
|
@ -18,5 +18,5 @@ file dev/sysmon/sysmon_wdog.c sysmon_wdog needs-flag
|
|||
file dev/sysmon/sysmon.c sysmon_envsys | sysmon_wdog |
|
||||
sysmon_power
|
||||
|
||||
defpseudo swwdog: sysmon_wdog
|
||||
defpseudodev swwdog: sysmon_wdog
|
||||
file dev/sysmon/swwdog.c swwdog
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: swwdog.c,v 1.9 2010/01/31 02:54:56 pooka Exp $ */
|
||||
/* $NetBSD: swwdog.c,v 1.10 2010/07/22 14:10:15 pgoyette Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Steven M. Bellovin
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.9 2010/01/31 02:54:56 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.10 2010/07/22 14:10:15 pgoyette Exp $");
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -44,21 +44,29 @@ __KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.9 2010/01/31 02:54:56 pooka Exp $");
|
|||
#include <sys/callout.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wdog.h>
|
||||
#include <dev/sysmon/sysmonvar.h>
|
||||
|
||||
#define NSWWDOG 1
|
||||
#include "ioconf.h"
|
||||
|
||||
struct swwdog_softc {
|
||||
device_t sc_dev;
|
||||
struct sysmon_wdog sc_smw;
|
||||
struct callout sc_c;
|
||||
char sc_name[20];
|
||||
int sc_wdog_armed;
|
||||
} sc_wdog[NSWWDOG];
|
||||
};
|
||||
|
||||
void swwdogattach(int);
|
||||
|
||||
static int swwdog_match(device_t, cfdata_t, void *);
|
||||
static void swwdog_attach(device_t, device_t, void *);
|
||||
static int swwdog_detach(device_t, int);
|
||||
static bool swwdog_suspend(device_t, const pmf_qual_t *);
|
||||
|
||||
static int swwdog_setmode(struct sysmon_wdog *);
|
||||
static int swwdog_tickle(struct sysmon_wdog *);
|
||||
|
||||
|
@ -67,21 +75,50 @@ static int swwdog_disarm(struct swwdog_softc *);
|
|||
|
||||
static void swwdog_panic(void *);
|
||||
|
||||
int swwdog_reboot = 0; /* set for panic instead of reboot */
|
||||
bool swwdog_reboot = false; /* set for panic instead of reboot */
|
||||
|
||||
#define SWDOG_DEFAULT 60 /* 60-second default period */
|
||||
|
||||
CFATTACH_DECL_NEW(swwdog, sizeof(struct swwdog_softc),
|
||||
swwdog_match, swwdog_attach, swwdog_detach, NULL);
|
||||
|
||||
void
|
||||
swwdogattach(int count __unused)
|
||||
swwdogattach(int n __unused)
|
||||
{
|
||||
int i;
|
||||
int err;
|
||||
static struct cfdata cf;
|
||||
|
||||
for (i = 0; i < NSWWDOG; i++) {
|
||||
struct swwdog_softc *sc = &sc_wdog[i];
|
||||
err = config_cfattach_attach(swwdog_cd.cd_name, &swwdog_ca);
|
||||
if (err) {
|
||||
aprint_error("%s: couldn't register cfattach: %d\n",
|
||||
swwdog_cd.cd_name, err);
|
||||
config_cfdriver_detach(&swwdog_cd);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(sc->sc_name, sizeof sc->sc_name, "swwdog%d", i);
|
||||
printf("%s: ", sc->sc_name);
|
||||
sc->sc_smw.smw_name = sc->sc_name;
|
||||
cf.cf_name = swwdog_cd.cd_name;
|
||||
cf.cf_atname = swwdog_cd.cd_name;
|
||||
cf.cf_unit = 0;
|
||||
cf.cf_fstate = FSTATE_STAR;
|
||||
|
||||
(void)config_attach_pseudo(&cf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
swwdog_match(device_t parent, cfdata_t data, void *aux)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
swwdog_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct swwdog_softc *sc = device_private(self);
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_smw.smw_name = device_xname(self);
|
||||
sc->sc_smw.smw_cookie = sc;
|
||||
sc->sc_smw.smw_setmode = swwdog_setmode;
|
||||
sc->sc_smw.smw_tickle = swwdog_tickle;
|
||||
|
@ -90,11 +127,35 @@ swwdogattach(int count __unused)
|
|||
callout_setfunc(&sc->sc_c, swwdog_panic, sc);
|
||||
|
||||
if (sysmon_wdog_register(&sc->sc_smw) == 0)
|
||||
printf("software watchdog initialized\n");
|
||||
aprint_normal_dev(self, "software watchdog initialized\n");
|
||||
else
|
||||
printf("unable to register software watchdog "
|
||||
"with sysmon\n");
|
||||
}
|
||||
aprint_error_dev(self, "unable to register software "
|
||||
"watchdog with sysmon\n");
|
||||
|
||||
if (!pmf_device_register(self, swwdog_suspend, NULL))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
}
|
||||
|
||||
static int
|
||||
swwdog_detach(device_t self, int flags)
|
||||
{
|
||||
struct swwdog_softc *sc = device_private(self);
|
||||
|
||||
swwdog_disarm(sc);
|
||||
callout_destroy(&sc->sc_c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
swwdog_suspend(device_t dev, const pmf_qual_t *qual)
|
||||
{
|
||||
struct swwdog_softc *sc = device_private(dev);
|
||||
|
||||
/* Don't allow suspend if watchdog is armed */
|
||||
if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -144,13 +205,13 @@ static void
|
|||
swwdog_panic(void *vsc)
|
||||
{
|
||||
struct swwdog_softc *sc = vsc;
|
||||
int do_panic;
|
||||
bool do_panic;
|
||||
|
||||
do_panic = swwdog_reboot;
|
||||
swwdog_reboot = 1;
|
||||
callout_schedule(&sc->sc_c, 60 * hz); /* deliberate double-panic */
|
||||
|
||||
printf("%s: %d second timer expired\n", sc->sc_name,
|
||||
printf("%s: %d second timer expired\n", device_xname(sc->sc_dev),
|
||||
sc->sc_smw.smw_period);
|
||||
|
||||
if (do_panic)
|
||||
|
@ -158,3 +219,26 @@ swwdog_panic(void *vsc)
|
|||
else
|
||||
cpu_reboot(0, NULL);
|
||||
}
|
||||
|
||||
SYSCTL_SETUP(sysctl_swwdog, "swwdog subtree setup")
|
||||
{
|
||||
int err;
|
||||
const struct sysctlnode *me;
|
||||
|
||||
err = sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_PERMANENT,
|
||||
CTLTYPE_NODE, "machdep", NULL,
|
||||
NULL, 0, NULL, 0,
|
||||
CTL_HW, CTL_EOL);
|
||||
|
||||
if (err == 0)
|
||||
err = sysctl_createv(NULL, 0, NULL, &me, CTLFLAG_READWRITE,
|
||||
CTLTYPE_NODE, "swwdog", NULL,
|
||||
NULL, 0, NULL, 0,
|
||||
CTL_HW, CTL_CREATE, CTL_EOL);
|
||||
|
||||
if (err == 0)
|
||||
err = sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READWRITE,
|
||||
CTLTYPE_BOOL, "reboot", "reboot if timer expires",
|
||||
NULL, 0, &swwdog_reboot, sizeof(bool),
|
||||
CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# $NetBSD: Makefile,v 1.2 2010/02/16 20:42:45 pooka Exp $
|
||||
# $NetBSD: Makefile,v 1.3 2010/07/22 14:10:14 pgoyette Exp $
|
||||
#
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../dev/sysmon
|
||||
|
||||
LIB= rumpdev_sysmon
|
||||
IOCONF= SYSMON.ioconf
|
||||
|
||||
SRCS= sysmon_taskq.c sysmon_power.c sysmon_envsys.c sysmon_envsys_events.c \
|
||||
sysmon_envsys_tables.c sysmon_envsys_util.c sysmon_wdog.c sysmon.c \
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# $NetBSD: SYSMON.ioconf,v 1.1 2010/07/22 14:10:14 pgoyette Exp $
|
||||
#
|
||||
|
||||
ioconf swwdog
|
||||
|
||||
include "conf/files"
|
||||
|
||||
pseudo-device swwdog
|
Loading…
Reference in New Issue