diff options
| author | pgoyette <pgoyette@NetBSD.org> | 2015-04-18 10:49:31 +0000 |
|---|---|---|
| committer | pgoyette <pgoyette@NetBSD.org> | 2015-04-18 10:49:31 +0000 |
| commit | a4ebc4d9269d25e2872daed83fe802432c0f3408 (patch) | |
| tree | 313d6a90ce273e79a2afc8e0e85ebb461e285fdf /sys/dev/sysmon | |
| parent | 622c5d23e5077908d0705696086ad4b85ae5f420 (diff) | |
Update attach/detach routines and provide MODULE interface.
Confirmed that atf tests (which run via rump) still pass, and also
confirmed that panic/reboot work in both monolithic kernel and
loaded module.
Diffstat (limited to 'sys/dev/sysmon')
| -rw-r--r-- | sys/dev/sysmon/swwdog.c | 198 |
1 files changed, 160 insertions, 38 deletions
diff --git a/sys/dev/sysmon/swwdog.c b/sys/dev/sysmon/swwdog.c index 751cb90505f..95da9d7aaa4 100644 --- a/sys/dev/sysmon/swwdog.c +++ b/sys/dev/sysmon/swwdog.c @@ -1,4 +1,4 @@ -/* $NetBSD: swwdog.c,v 1.13 2014/04/13 13:19:50 pgoyette Exp $ */ +/* $NetBSD: swwdog.c,v 1.14 2015/04/18 10:49:31 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.13 2014/04/13 13:19:50 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.14 2015/04/18 10:49:31 pgoyette Exp $"); /* * @@ -41,8 +41,8 @@ __KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.13 2014/04/13 13:19:50 pgoyette Exp $") * */ #include <sys/param.h> -#include <sys/callout.h> #include <sys/device.h> +#include <sys/callout.h> #include <sys/kernel.h> #include <sys/kmem.h> #include <sys/reboot.h> @@ -50,41 +50,58 @@ __KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.13 2014/04/13 13:19:50 pgoyette Exp $") #include <sys/sysctl.h> #include <sys/wdog.h> #include <sys/workqueue.h> +#include <sys/module.h> #include <dev/sysmon/sysmonvar.h> -#include "ioconf.h" +#ifndef _MODULE +#include "opt_modular.h" +#endif struct swwdog_softc { - device_t sc_dev; - struct sysmon_wdog sc_smw; - struct callout sc_c; - int sc_wdog_armed; + device_t sc_dev; + struct sysmon_wdog sc_smw; + struct callout sc_c; + int sc_armed; }; -void swwdogattach(int); +bool swwdog_reboot = false; /* false --> panic , true --> reboot */ -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 struct workqueue *wq; +static device_t swwdog_dev; + +MODULE(MODULE_CLASS_DRIVER, swwdog, NULL); -static int swwdog_setmode(struct sysmon_wdog *); -static int swwdog_tickle(struct sysmon_wdog *); +#ifdef _LKM +CFDRIVER_DECL(swwdog, DV_DULL, NULL); +#endif -static int swwdog_arm(struct swwdog_softc *); -static int swwdog_disarm(struct swwdog_softc *); +int swwdogattach(int); -static void swwdog_panic(void *); +static int swwdog_setmode(struct sysmon_wdog *); +static int swwdog_tickle(struct sysmon_wdog *); +static bool swwdog_suspend(device_t, const pmf_qual_t *); +static int swwdog_arm(struct swwdog_softc *); +static int swwdog_disarm(struct swwdog_softc *); -bool swwdog_reboot = false; /* set for panic instead of reboot */ +static void swwdog_panic(void *); -#define SWDOG_DEFAULT 60 /* 60-second default period */ +static void swwdog_sysctl_setup(void); +static struct sysctllog *swwdog_sysctllog = NULL; + +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_init(void *); +static int swwdog_fini(void *); +static int swwdog_modcmd(modcmd_t, void *); CFATTACH_DECL_NEW(swwdog, sizeof(struct swwdog_softc), swwdog_match, swwdog_attach, swwdog_detach, NULL); +extern struct cfdriver swwdog_cd; -static void swwdog_sysctl_setup(void); -static struct sysctllog *swwdog_sysctllog; +#define SWDOG_DEFAULT 60 /* 60-second default period */ static void doreboot(struct work *wrkwrkwrk, void *p) @@ -93,41 +110,51 @@ doreboot(struct work *wrkwrkwrk, void *p) cpu_reboot(0, NULL); } -static struct workqueue *wq; - -void +int swwdogattach(int n __unused) { - int err; + int error; static struct cfdata cf; +printf("%s: entered\n", __func__); /* XXX PRG */ if (workqueue_create(&wq, "swwreboot", doreboot, NULL, PRI_NONE, IPL_NONE, 0) != 0) { aprint_error("failed to create swwdog reboot wq"); + return 1; } - 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); + error = config_cfattach_attach(swwdog_cd.cd_name, &swwdog_ca); + if (error) { + aprint_error("%s: unable to attach cfattach\n", + swwdog_cd.cd_name); workqueue_destroy(wq); - return; + return error; } cf.cf_name = swwdog_cd.cd_name; cf.cf_atname = swwdog_cd.cd_name; cf.cf_unit = 0; cf.cf_fstate = FSTATE_STAR; + cf.cf_pspec = NULL; + cf.cf_loc = NULL; + cf.cf_flags = 0; - (void)config_attach_pseudo(&cf); + swwdog_dev = config_attach_pseudo(&cf); - return; +printf("%s: swwdog_dev = 0x%p\n", __func__, swwdog_dev); /* XXX PRG */ + if (swwdog_dev == NULL) { + config_cfattach_detach(swwdog_cd.cd_name, &swwdog_ca); + workqueue_destroy(wq); + return 1; + } + return 0; } static int swwdog_match(device_t parent, cfdata_t data, void *aux) { + +printf("%s: entered\n", __func__); /* XXX PRG */ return 1; } @@ -136,20 +163,31 @@ swwdog_attach(device_t parent, device_t self, void *aux) { struct swwdog_softc *sc = device_private(self); +printf("%s: entered\n", __func__); /* XXX PRG */ + if (workqueue_create(&wq, "swwreboot", doreboot, NULL, + PRI_NONE, IPL_NONE, 0) != 0) { + aprint_error_dev(self, "failed to create reboot workqueue"); + } + 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; sc->sc_smw.smw_period = SWDOG_DEFAULT; + callout_init(&sc->sc_c, 0); callout_setfunc(&sc->sc_c, swwdog_panic, sc); if (sysmon_wdog_register(&sc->sc_smw) == 0) aprint_normal_dev(self, "software watchdog initialized\n"); - else + else { aprint_error_dev(self, "unable to register software " "watchdog with sysmon\n"); + callout_destroy(&sc->sc_c); + workqueue_destroy(wq); + return; + } if (!pmf_device_register(self, swwdog_suspend, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); @@ -162,13 +200,15 @@ swwdog_detach(device_t self, int flags) { struct swwdog_softc *sc = device_private(self); +printf("%s: entered\n", __func__); /* XXX PRG */ pmf_device_deregister(self); swwdog_disarm(sc); - callout_destroy(&sc->sc_c); sysctl_teardown(&swwdog_sysctllog); + sysmon_wdog_unregister(&sc->sc_smw); + callout_destroy(&sc->sc_c); workqueue_destroy(wq); - return 1; + return 0; } static bool @@ -236,7 +276,7 @@ swwdog_panic(void *vsc) swwdog_reboot = false; callout_schedule(&sc->sc_c, 60 * hz); /* deliberate double-panic */ - printf("%s: %d second timer expired\n", device_xname(sc->sc_dev), + printf("%s: %d second timer expired\n", "swwdog", sc->sc_smw.smw_period); if (do_panic) @@ -261,3 +301,85 @@ swwdog_sysctl_setup(void) NULL, 0, &swwdog_reboot, sizeof(bool), CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL); } + +/* + * Module management + */ + +static +int +swwdog_init(void *arg) +{ +#ifdef _LKM + /* + * Merge the driver info into the kernel tables and attach the + * pseudo-device + */ + int error; + + error = config_cfdriver_attach(&swwdog_cd); + if (error) { + aprint_error("%s: unable to attach cfdriver\n", + swwdog_cd.cd_name); + return error; + } + error = swwdogattach(1); + if (error) { + aprint_error("%s: device attach failed\n", swwdog_cd.cd_name); + config_cfdriver_detach(&swwdog_cd); + } + + return error; +#else + + return 0; +#endif +} + +static +int +swwdog_fini(void *arg) +{ + int error; + + error = config_detach(swwdog_dev, 0); + + error = config_cfattach_detach(swwdog_cd.cd_name, &swwdog_ca); + if (error) + aprint_error("%s: error detaching cfattach: %d\n", + swwdog_cd.cd_name, error); + +#ifdef _LKM + error = config_cfdriver_detach(&swwdog_cd); + if (error) + aprint_error("%s: error detaching cfdriver: %d\n", + swwdog_cd.cd_name, error); +#endif + + return error; +} + +static +int +swwdog_modcmd(modcmd_t cmd, void *arg) +{ + int ret; + +printf("%s: cmd %d\n", __func__, cmd); /* XXX PRG */ + switch (cmd) { + case MODULE_CMD_INIT: + ret = swwdog_init(arg); + break; + + case MODULE_CMD_FINI: + ret = swwdog_fini(arg); + break; + + case MODULE_CMD_STAT: + default: + ret = ENOTTY; + } + + return ret; +} + |
