From 8061eede6f223c505049e46dffefe438a6a41716 Mon Sep 17 00:00:00 2001 From: pgoyette Date: Thu, 23 Apr 2015 23:22:03 +0000 Subject: [PATCH] Modularize sysmon and its components --- sys/dev/sysmon/sysmon.c | 290 ++++++++++++++++++++++++++++----- sys/dev/sysmon/sysmon_envsys.c | 61 ++++++- sys/dev/sysmon/sysmon_power.c | 68 +++++++- sys/dev/sysmon/sysmon_taskq.c | 62 ++++++- sys/dev/sysmon/sysmon_wdog.c | 64 +++++++- sys/dev/sysmon/sysmonconf.h | 43 ----- sys/dev/sysmon/sysmonvar.h | 27 ++- 7 files changed, 507 insertions(+), 108 deletions(-) delete mode 100644 sys/dev/sysmon/sysmonconf.h diff --git a/sys/dev/sysmon/sysmon.c b/sys/dev/sysmon/sysmon.c index f0ba012b324f..6f50caa8042e 100644 --- a/sys/dev/sysmon/sysmon.c +++ b/sys/dev/sysmon/sysmon.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon.c,v 1.19 2014/07/25 08:10:39 dholland Exp $ */ +/* $NetBSD: sysmon.c,v 1.20 2015/04/23 23:22:03 pgoyette Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -39,7 +39,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sysmon.c,v 1.19 2014/07/25 08:10:39 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon.c,v 1.20 2015/04/23 23:22:03 pgoyette Exp $"); #include #include @@ -49,9 +49,11 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon.c,v 1.19 2014/07/25 08:10:39 dholland Exp $") #include #include #include +#include +#include +#include #include -#include dev_type_open(sysmonopen); dev_type_close(sysmonclose); @@ -75,6 +77,97 @@ const struct cdevsw sysmon_cdevsw = { .d_flag = D_OTHER | D_MPSAFE }; +static int sysmon_match(device_t, cfdata_t, void *); +static void sysmon_attach(device_t, device_t, void *); +static int sysmon_detach(device_t, int); + +static int sysmon_modcmd(modcmd_t, void *); + +CFDRIVER_DECL(sysmon, DV_DULL, NULL); + +/* + * Info about our minor "devices" + */ +static struct sysmon_opvec *sysmon_opvec_table[] = { NULL, NULL, NULL }; +static int sysmon_refcnt[] = { 0, 0, 0 }; +static const char *sysmon_mod[] = { "sysmon_envsys", + "sysmon_wdog", + "sysmon_power" }; + +struct sysmon_softc { + device_t sc_dev; + kmutex_t sc_minor_mtx; +}; + +static device_t sysmon_dev = NULL; + +CFATTACH_DECL_NEW(sysmon, sizeof(struct sysmon_softc), + sysmon_match, sysmon_attach, sysmon_detach, NULL); +extern struct cfdriver sysmon_cd; + +static int +sysmon_match(device_t parent, cfdata_t data, void *aux) +{ + + return 1; +} + +static void +sysmon_attach(device_t parent, device_t self, void *aux) +{ + + struct sysmon_softc *sc = device_private(self); + + sc->sc_dev = self; + + mutex_init(&sc->sc_minor_mtx, MUTEX_DEFAULT, IPL_NONE); +} + +static int +sysmon_detach(device_t self, int flags) +{ + struct sysmon_softc *sc = device_private(self); + + mutex_destroy(&sc->sc_minor_mtx); + return 0; +} + +/* + * sysmon_attach_minor + * + * Attach a minor device for wdog, power, or envsys. Manage a + * reference count so we can prevent the device from being + * detached if there are still users with the minor device opened. + * + * If the opvec argument is NULL, this is a request to detach the + * minor device - make sure the refcnt is zero! + */ +int +sysmon_attach_minor(int minor, struct sysmon_opvec *opvec) +{ + struct sysmon_softc *sc = device_private(sysmon_dev); + int ret; + + mutex_enter(&sc->sc_minor_mtx); + if (opvec) { + if (sysmon_opvec_table[minor] == NULL) { + sysmon_refcnt[minor] = 0; + sysmon_opvec_table[minor] = opvec; + ret = 0; + } else + ret = EEXIST; + } else { + if (sysmon_refcnt[minor] == 0) { + sysmon_opvec_table[minor] = NULL; + ret = 0; + } else + ret = EBUSY; + } + + mutex_exit(&sc->sc_minor_mtx); + return ret; +} + /* * sysmonopen: * @@ -83,28 +176,33 @@ const struct cdevsw sysmon_cdevsw = { int sysmonopen(dev_t dev, int flag, int mode, struct lwp *l) { + struct sysmon_softc *sc = device_private(sysmon_dev); int error; + mutex_enter(&sc->sc_minor_mtx); + switch (minor(dev)) { -#if NSYSMON_ENVSYS > 0 case SYSMON_MINOR_ENVSYS: - error = sysmonopen_envsys(dev, flag, mode, l); - break; -#endif -#if NSYSMON_WDOG > 0 case SYSMON_MINOR_WDOG: - error = sysmonopen_wdog(dev, flag, mode, l); - break; -#endif -#if NSYSMON_POWER > 0 case SYSMON_MINOR_POWER: - error = sysmonopen_power(dev, flag, mode, l); + if (sysmon_opvec_table[minor(dev)] == NULL) { + mutex_exit(&sc->sc_minor_mtx); + error = module_autoload(sysmon_mod[minor(dev)], + MODULE_CLASS_MISC); + mutex_enter(&sc->sc_minor_mtx); + if (sysmon_opvec_table[minor(dev)] == NULL) + error = ENODEV; + } + error = (sysmon_opvec_table[minor(dev)]->so_open)(dev, flag, + mode, l); + if (error == 0) + sysmon_refcnt[minor(dev)]++; break; -#endif default: error = ENODEV; } + mutex_exit(&sc->sc_minor_mtx); return (error); } @@ -119,21 +217,20 @@ sysmonclose(dev_t dev, int flag, int mode, struct lwp *l) int error; switch (minor(dev)) { -#if NSYSMON_ENVSYS > 0 case SYSMON_MINOR_ENVSYS: - error = sysmonclose_envsys(dev, flag, mode, l); - break; -#endif -#if NSYSMON_WDOG > 0 case SYSMON_MINOR_WDOG: - error = sysmonclose_wdog(dev, flag, mode, l); - break; -#endif -#if NSYSMON_POWER > 0 case SYSMON_MINOR_POWER: - error = sysmonclose_power(dev, flag, mode, l); + if (sysmon_opvec_table[minor(dev)] == NULL) + error = ENODEV; + else { + error = (sysmon_opvec_table[minor(dev)]->so_close)(dev, + flag, mode, l); + if (error == 0) { + sysmon_refcnt[minor(dev)]--; + KASSERT(sysmon_refcnt[minor(dev)] >= 0); + } + } break; -#endif default: error = ENODEV; } @@ -152,21 +249,15 @@ sysmonioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) int error; switch (minor(dev)) { -#if NSYSMON_ENVSYS > 0 case SYSMON_MINOR_ENVSYS: - error = sysmonioctl_envsys(dev, cmd, data, flag, l); - break; -#endif -#if NSYSMON_WDOG > 0 case SYSMON_MINOR_WDOG: - error = sysmonioctl_wdog(dev, cmd, data, flag, l); - break; -#endif -#if NSYSMON_POWER > 0 case SYSMON_MINOR_POWER: - error = sysmonioctl_power(dev, cmd, data, flag, l); + if (sysmon_opvec_table[minor(dev)] == NULL) + error = ENODEV; + else + error = (sysmon_opvec_table[minor(dev)]->so_ioctl)(dev, + cmd, data, flag, l); break; -#endif default: error = ENODEV; } @@ -185,11 +276,13 @@ sysmonread(dev_t dev, struct uio *uio, int flags) int error; switch (minor(dev)) { -#if NSYSMON_POWER > 0 case SYSMON_MINOR_POWER: - error = sysmonread_power(dev, uio, flags); + if (sysmon_opvec_table[minor(dev)] == NULL) + error = ENODEV; + else + error = (sysmon_opvec_table[minor(dev)]->so_read)(dev, + uio, flags); break; -#endif default: error = ENODEV; } @@ -208,11 +301,13 @@ sysmonpoll(dev_t dev, int events, struct lwp *l) int rv; switch (minor(dev)) { -#if NSYSMON_POWER > 0 case SYSMON_MINOR_POWER: - rv = sysmonpoll_power(dev, events, l); + if (sysmon_opvec_table[minor(dev)] == NULL) + rv = events; + else + rv = (sysmon_opvec_table[minor(dev)]->so_poll)(dev, + events, l); break; -#endif default: rv = events; } @@ -231,14 +326,119 @@ sysmonkqfilter(dev_t dev, struct knote *kn) int error; switch (minor(dev)) { -#if NSYSMON_POWER > 0 case SYSMON_MINOR_POWER: - error = sysmonkqfilter_power(dev, kn); + if (sysmon_opvec_table[minor(dev)] == NULL) + error = ENODEV; + else + error = (sysmon_opvec_table[minor(dev)]->so_filter)(dev, + kn); break; -#endif default: error = 1; } return (error); } + +MODULE(MODULE_CLASS_DRIVER, sysmon, ""); + +int +sysmon_init(void) +{ + devmajor_t bmajor, cmajor; + static struct cfdata cf; + int error = 0; + + if (sysmon_dev != NULL) { + return EEXIST; + } + + error = config_cfdriver_attach(&sysmon_cd); + if (error) { + aprint_error("%s: unable to attach cfdriver\n", + sysmon_cd.cd_name); + return error; + } + error = config_cfattach_attach(sysmon_cd.cd_name, &sysmon_ca); + if (error) { + config_cfdriver_detach(&sysmon_cd); + aprint_error("%s: unable to attach cfattach\n", + sysmon_cd.cd_name); + return error; + } + + bmajor = cmajor = -1; + error = devsw_attach("sysmon", NULL, &bmajor, + &sysmon_cdevsw, &cmajor); + if (error) { + config_cfattach_detach(sysmon_cd.cd_name, &sysmon_ca); + config_cfdriver_detach(&sysmon_cd); + aprint_error("%s: unable to attach devsw\n", + sysmon_cd.cd_name); + return error; + } + + cf.cf_name = sysmon_cd.cd_name; + cf.cf_atname = sysmon_cd.cd_name; + cf.cf_unit = 0; + cf.cf_fstate = FSTATE_STAR; + cf.cf_pspec = NULL; + cf.cf_loc = NULL; + cf.cf_flags = 0; + + sysmon_dev = config_attach_pseudo(&cf); + if (sysmon_dev == NULL) { + aprint_error("%s: failed to attach pseudo device\n", + sysmon_cd.cd_name); + error = ENODEV; + } + + return error; +} + +int +sysmon_fini(void) +{ + int error = 0; + + if (sysmon_opvec_table[SYSMON_MINOR_ENVSYS] != NULL) + error = EBUSY; + else if (sysmon_opvec_table[SYSMON_MINOR_WDOG] != NULL) + error = EBUSY; + else if (sysmon_opvec_table[SYSMON_MINOR_POWER] != NULL) + error = EBUSY; + + else { + config_detach(sysmon_dev, 0); + devsw_detach(NULL, &sysmon_cdevsw); + config_cfattach_detach(sysmon_cd.cd_name, &sysmon_ca); + config_cfdriver_detach(&sysmon_cd); + } + if (error == 0) + sysmon_dev = NULL; + + return error; +} + +static +int +sysmon_modcmd(modcmd_t cmd, void *arg) +{ + int ret; + + switch (cmd) { + case MODULE_CMD_INIT: + ret = sysmon_init(); + break; + + case MODULE_CMD_FINI: + ret = sysmon_fini(); + break; + + case MODULE_CMD_STAT: + default: + ret = ENOTTY; + } + + return ret; +} diff --git a/sys/dev/sysmon/sysmon_envsys.c b/sys/dev/sysmon/sysmon_envsys.c index 9e59229c6403..f26ccdc811ae 100644 --- a/sys/dev/sysmon/sysmon_envsys.c +++ b/sys/dev/sysmon/sysmon_envsys.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_envsys.c,v 1.130 2015/04/13 16:33:25 riastradh Exp $ */ +/* $NetBSD: sysmon_envsys.c,v 1.131 2015/04/23 23:22:03 pgoyette Exp $ */ /*- * Copyright (c) 2007, 2008 Juan Romero Pardines. @@ -64,7 +64,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.130 2015/04/13 16:33:25 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.131 2015/04/23 23:22:03 pgoyette Exp $"); #include #include @@ -77,6 +77,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.130 2015/04/13 16:33:25 riastrad #include #include #include +#include #include #include @@ -101,17 +102,46 @@ static void sme_initial_refresh(void *); static uint32_t sme_get_max_value(struct sysmon_envsys *, bool (*)(const envsys_data_t*), bool); +MODULE(MODULE_CLASS_MISC, sysmon_envsys, "sysmon,sysmon_taskq"); + +static struct sysmon_opvec sysmon_envsys_opvec = { + sysmonopen_envsys, sysmonclose_envsys, sysmonioctl_envsys, + NULL, NULL, NULL +}; + /* * sysmon_envsys_init: * * + Initialize global mutex, dictionary and the linked list. */ -void +int sysmon_envsys_init(void) { + int error; + LIST_INIT(&sysmon_envsys_list); mutex_init(&sme_global_mtx, MUTEX_DEFAULT, IPL_NONE); sme_propd = prop_dictionary_create(); + + error = sysmon_attach_minor(SYSMON_MINOR_ENVSYS, &sysmon_envsys_opvec); + + return error; +} + +int +sysmon_envsys_fini(void) +{ + int error; + + if ( ! LIST_EMPTY(&sysmon_envsys_list)) + error = EBUSY; + else + error = sysmon_attach_minor(SYSMON_MINOR_ENVSYS, NULL); + + if (error == 0) + mutex_destroy(&sme_global_mtx); + + return error; } /* @@ -771,7 +801,6 @@ out: */ if (error == 0) { nevent = 0; - sysmon_task_queue_init(); if (sme->sme_flags & SME_INIT_REFRESH) { sysmon_task_queue_sched(0, sme_initial_refresh, sme); @@ -848,6 +877,7 @@ out2: SLIST_REMOVE_HEAD(&sme_evdrv_list, evdrv_head); kmem_free(evdv, sizeof(*evdv)); } +printf("%s: finished, error %d\n", __func__, error); if (!error) return 0; @@ -2034,3 +2064,26 @@ sysmon_envsys_refresh_sensor(struct sysmon_envsys *sme, envsys_data_t *edata) rnd_add_uint32(&edata->rnd_src, edata->value_cur); edata->value_prev = edata->value_cur; } + +static +int +sysmon_envsys_modcmd(modcmd_t cmd, void *arg) +{ + int ret; + + switch (cmd) { + case MODULE_CMD_INIT: + ret = sysmon_envsys_init(); + break; + + case MODULE_CMD_FINI: + ret = sysmon_envsys_fini(); + break; + + case MODULE_CMD_STAT: + default: + ret = ENOTTY; + } + + return ret; +} diff --git a/sys/dev/sysmon/sysmon_power.c b/sys/dev/sysmon/sysmon_power.c index 990604046235..41cd42402db0 100644 --- a/sys/dev/sysmon/sysmon_power.c +++ b/sys/dev/sysmon/sysmon_power.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_power.c,v 1.53 2015/04/13 16:33:25 riastradh Exp $ */ +/* $NetBSD: sysmon_power.c,v 1.54 2015/04/23 23:22:03 pgoyette Exp $ */ /*- * Copyright (c) 2007 Juan Romero Pardines. @@ -69,9 +69,12 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.53 2015/04/13 16:33:25 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.54 2015/04/23 23:22:03 pgoyette Exp $"); +#ifndef _LKM #include "opt_compat_netbsd.h" +#endif + #include #include #include @@ -84,10 +87,13 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.53 2015/04/13 16:33:25 riastradh #include #include #include +#include #include #include +MODULE(MODULE_CLASS_MISC, sysmon_power, "sysmon"); + /* * Singly linked list for dictionaries to be stored/sent. */ @@ -186,17 +192,24 @@ static int sysmon_power_daemon_task(struct power_event_dictionary *, void *, int); static void sysmon_power_destroy_dictionary(struct power_event_dictionary *); +static struct sysmon_opvec sysmon_power_opvec = { + sysmonopen_power, sysmonclose_power, sysmonioctl_power, + sysmonread_power, sysmonpoll_power, sysmonkqfilter_power +}; + #define SYSMON_NEXT_EVENT(x) (((x) + 1) % SYSMON_MAX_POWER_EVENTS) /* * sysmon_power_init: * * Initializes the mutexes and condition variables in the - * boot process via init_main.c. + * boot process via module initialization process. */ -void +int sysmon_power_init(void) { + int error; + mutex_init(&sysmon_power_event_queue_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&sysmon_power_event_queue_cv, "smpower"); selinit(&sysmon_power_event_queue_selinfo); @@ -204,6 +217,29 @@ sysmon_power_init(void) rnd_attach_source(&sysmon_rndsource, "system-power", RND_TYPE_POWER, RND_FLAG_DEFAULT); + error = sysmon_attach_minor(SYSMON_MINOR_POWER, &sysmon_power_opvec); + + return error; +} + +int +sysmon_power_fini(void) +{ + int error; + + if (sysmon_power_daemon != NULL) + error = EBUSY; + else + error = sysmon_attach_minor(SYSMON_MINOR_POWER, NULL); + + if (error == 0) { + rnd_detach_source(&sysmon_rndsource); + seldestroy(&sysmon_power_event_queue_selinfo); + cv_destroy(&sysmon_power_event_queue_cv); + mutex_destroy(&sysmon_power_event_queue_mtx); + } + + return error; } /* @@ -1059,3 +1095,27 @@ sysmon_pswitch_event(struct sysmon_pswitch *smpsw, int event) } } + +static +int +sysmon_power_modcmd(modcmd_t cmd, void *arg) +{ + int ret; + + switch (cmd) { + case MODULE_CMD_INIT: + ret = sysmon_power_init(); + break; + + case MODULE_CMD_FINI: + ret = sysmon_power_fini(); + break; + + case MODULE_CMD_STAT: + default: + ret = ENOTTY; + } + + return ret; +} + diff --git a/sys/dev/sysmon/sysmon_taskq.c b/sys/dev/sysmon/sysmon_taskq.c index 4d1457159368..2bf1b050aee4 100644 --- a/sys/dev/sysmon/sysmon_taskq.c +++ b/sys/dev/sysmon/sysmon_taskq.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_taskq.c,v 1.14 2008/09/05 22:06:52 gmcgarry Exp $ */ +/* $NetBSD: sysmon_taskq.c,v 1.15 2015/04/23 23:22:03 pgoyette Exp $ */ /* * Copyright (c) 2001, 2003 Wasabi Systems, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.14 2008/09/05 22:06:52 gmcgarry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.15 2015/04/23 23:22:03 pgoyette Exp $"); #include #include @@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_taskq.c,v 1.14 2008/09/05 22:06:52 gmcgarry E #include #include #include +#include #include @@ -71,15 +72,36 @@ static int sysmon_task_queue_cleanup_sem; static struct lwp *sysmon_task_queue_lwp; static void sysmon_task_queue_thread(void *); +MODULE(MODULE_CLASS_MISC, sysmon_taskq, NULL); + +/* + * XXX Normally, all initialization would be handled as part of + * the module(9) framework. However, there are a number of + * users of the sysmon_taskq facility that are not modular, + * and these can directly call sysmon_task_queue_init() + * directly. To accomodate these non-standard users, we + * make sure that sysmon_task_queue_init() handles multiple + * invocations. And we also ensure that, if any non-module + * user exists, we don't allow the module to be unloaded. + * (We can't use module_hold() for this, since the module(9) + * framework itself isn't necessarily initialized yet.) + */ + +/* + * sysmon_task_queue_preinit: + * + * Early one-time initialization of task-queue + */ void sysmon_task_queue_preinit(void) { + mutex_init(&sysmon_task_queue_mtx, MUTEX_DEFAULT, IPL_VM); mutex_init(&sysmon_task_queue_init_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&sysmon_task_queue_cv, "smtaskq"); + sysmon_task_queue_initialized = 0; } - /* * sysmon_task_queue_init: * @@ -91,12 +113,11 @@ sysmon_task_queue_init(void) int error; mutex_enter(&sysmon_task_queue_init_mtx); - if (sysmon_task_queue_initialized) { + if (sysmon_task_queue_initialized++) { mutex_exit(&sysmon_task_queue_init_mtx); return; } - sysmon_task_queue_initialized = 1; mutex_exit(&sysmon_task_queue_init_mtx); error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, @@ -117,6 +138,9 @@ void sysmon_task_queue_fini(void) { + if (sysmon_task_queue_initialized > 1) + return EBUSY; + mutex_enter(&sysmon_task_queue_mtx); sysmon_task_queue_cleanup_sem = 1; @@ -209,3 +233,31 @@ sysmon_task_queue_sched(u_int pri, void (*func)(void *), void *arg) return 0; } + +static +int +sysmon_taskq_modcmd(modcmd_t cmd, void *arg) +{ + int ret; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + sysmon_task_queue_preinit(); +#endif + sysmon_task_queue_init(); + ret = 0; + break; + + case MODULE_CMD_FINI: + sysmon_task_queue_fini(); + ret = 0; + break; + + case MODULE_CMD_STAT: + default: + ret = ENOTTY; + } + + return ret; +} diff --git a/sys/dev/sysmon/sysmon_wdog.c b/sys/dev/sysmon/sysmon_wdog.c index 1c05dff43ca9..61e56b43b8ed 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.25 2011/01/04 01:51:06 matt Exp $ */ +/* $NetBSD: sysmon_wdog.c,v 1.26 2015/04/23 23:22:03 pgoyette Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.25 2011/01/04 01:51:06 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.26 2015/04/23 23:22:03 pgoyette Exp $"); #include #include @@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.25 2011/01/04 01:51:06 matt Exp $" #include #include #include +#include #include @@ -74,9 +75,18 @@ void sysmon_wdog_critpoll(void *); void sysmon_wdog_shutdown(void *); void sysmon_wdog_ref(struct sysmon_wdog *); -void +static struct sysmon_opvec sysmon_wdog_opvec = { + sysmonopen_wdog, sysmonclose_wdog, sysmonioctl_wdog, + NULL, NULL, NULL +}; + +MODULE(MODULE_CLASS_MISC, sysmon_wdog, "sysmon"); + +int sysmon_wdog_init(void) { + int error; + 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"); @@ -87,6 +97,32 @@ sysmon_wdog_init(void) if (sysmon_wdog_cphook == NULL) printf("WARNING: unable to register watchdog critpoll hook\n"); callout_init(&sysmon_wdog_callout, 0); + + error = sysmon_attach_minor(SYSMON_MINOR_WDOG, &sysmon_wdog_opvec); + + return error; +} + +int +sysmon_wdog_fini(void) +{ + int error; + + if ( ! LIST_EMPTY(&sysmon_wdog_list)) + return EBUSY; + + error = sysmon_attach_minor(SYSMON_MINOR_WDOG, NULL); + + if (error == 0) { + callout_destroy(&sysmon_wdog_callout); + critpollhook_disestablish(sysmon_wdog_cphook); + shutdownhook_disestablish(sysmon_wdog_sdhook); + cv_destroy(&sysmon_wdog_cv); + mutex_destroy(&sysmon_wdog_mtx); + mutex_destroy(&sysmon_wdog_list_mtx); + } + + return error; } /* @@ -500,3 +536,25 @@ sysmon_wdog_shutdown(void *arg) smw->smw_name); } } +static +int +sysmon_wdog_modcmd(modcmd_t cmd, void *arg) +{ + int ret; + + switch (cmd) { + case MODULE_CMD_INIT: + ret = sysmon_wdog_init(); + break; + + case MODULE_CMD_FINI: + ret = sysmon_wdog_fini(); + break; + + case MODULE_CMD_STAT: + default: + ret = ENOTTY; + } + + return ret; +} diff --git a/sys/dev/sysmon/sysmonconf.h b/sys/dev/sysmon/sysmonconf.h deleted file mode 100644 index f9d4a57608b5..000000000000 --- a/sys/dev/sysmon/sysmonconf.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $NetBSD: sysmonconf.h,v 1.3 2003/04/18 01:31:35 thorpej Exp $ */ - -/*- - * Copyright (c) 2000 Zembu Labs, Inc. - * All rights reserved. - * - * Author: Jason R. Thorpe - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Zembu Labs, Inc. - * 4. Neither the name of Zembu Labs nor the names of its employees may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR- - * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS- - * CLAIMED. IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _DEV_SYSMON_SYSMONCONF_H_ -#define _DEV_SYSMON_SYSMONCONF_H_ - -#include "sysmon_envsys.h" -#include "sysmon_wdog.h" -#include "sysmon_power.h" - -#endif /* _DEV_SYSMON_SYSMONCONF_H_ */ diff --git a/sys/dev/sysmon/sysmonvar.h b/sys/dev/sysmon/sysmonvar.h index ac833ba14e0e..b3dd29ed636c 100644 --- a/sys/dev/sysmon/sysmonvar.h +++ b/sys/dev/sysmon/sysmonvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: sysmonvar.h,v 1.48 2015/04/18 14:44:44 mlelstv Exp $ */ +/* $NetBSD: sysmonvar.h,v 1.49 2015/04/23 23:22:03 pgoyette Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -242,7 +242,8 @@ void sysmon_envsys_foreach_sensor(sysmon_envsys_callback_t, void *, bool); int sysmon_envsys_update_limits(struct sysmon_envsys *, envsys_data_t *); -void sysmon_envsys_init(void); +int sysmon_envsys_init(void); +int sysmon_envsys_fini(void); /***************************************************************************** * Watchdog timer support @@ -270,7 +271,8 @@ int sysmon_wdog_setmode(struct sysmon_wdog *, int, u_int); int sysmon_wdog_register(struct sysmon_wdog *); int sysmon_wdog_unregister(struct sysmon_wdog *); -void sysmon_wdog_init(void); +int sysmon_wdog_init(void); +int sysmon_wdog_fini(void); /***************************************************************************** * Power management support @@ -298,6 +300,23 @@ void sysmon_pswitch_unregister(struct sysmon_pswitch *); void sysmon_pswitch_event(struct sysmon_pswitch *, int); void sysmon_penvsys_event(struct penvsys_state *, int); -void sysmon_power_init(void); +int sysmon_power_init(void); +int sysmon_power_fini(void); + +/* + * Interface to sysmon common code used for autoloading + */ +struct sysmon_opvec { + int (*so_open)(dev_t, int, int, struct lwp*); + int (*so_close)(dev_t, int, int, struct lwp*); + int (*so_ioctl)(dev_t, u_long, void *, int, struct lwp*); + int (*so_read)(dev_t, struct uio*, int); + int (*so_poll)(dev_t, int, struct lwp*); + int (*so_filter)(dev_t, struct knote*); +}; + +int sysmon_init(void); +int sysmon_fini(void); +int sysmon_attach_minor(int, struct sysmon_opvec*); #endif /* _DEV_SYSMON_SYSMONVAR_H_ */