diff options
author | Ian Lepore <ian@FreeBSD.org> | 2017-08-13 18:10:24 +0000 |
---|---|---|
committer | Ian Lepore <ian@FreeBSD.org> | 2017-08-13 18:10:24 +0000 |
commit | 2db14f97de02470dd2117179c291930ffab3b6ba (patch) | |
tree | ca8c08e1bf03d9dc303f5368dffad01c349ecb30 | |
parent | 037331ddbd44ed4331f24a567acca874872b735a (diff) |
Notes
-rw-r--r-- | share/man/man9/Makefile | 3 | ||||
-rw-r--r-- | share/man/man9/config_intrhook.9 | 21 | ||||
-rw-r--r-- | sys/kern/subr_autoconf.c | 38 | ||||
-rw-r--r-- | sys/sys/kernel.h | 7 |
4 files changed, 63 insertions, 6 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 9bbb71cecb03..7d0ba0000ad7 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -669,7 +669,8 @@ MLINKS+=condvar.9 cv_broadcast.9 \ condvar.9 cv_wait_unlock.9 \ condvar.9 cv_wmesg.9 MLINKS+=config_intrhook.9 config_intrhook_disestablish.9 \ - config_intrhook.9 config_intrhook_establish.9 + config_intrhook.9 config_intrhook_establish.9 \ + config_intrhook.9 config_intrhook_oneshot.9 MLINKS+=contigmalloc.9 contigfree.9 MLINKS+=casuword.9 casueword.9 \ casuword.9 casueword32.9 \ diff --git a/share/man/man9/config_intrhook.9 b/share/man/man9/config_intrhook.9 index 60bf9d848587..c92136fa076f 100644 --- a/share/man/man9/config_intrhook.9 +++ b/share/man/man9/config_intrhook.9 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 24, 2006 +.Dd August 10, 2017 .Dt CONFIG_INTRHOOK 9 .Os .Sh NAME @@ -35,10 +35,13 @@ but before root is mounted .Sh SYNOPSIS .In sys/kernel.h +.Vt typedef void (*ich_func_t)(void *arg); .Ft int .Fn config_intrhook_establish "struct intr_config_hook *hook" .Ft void .Fn config_intrhook_disestablish "struct intr_config_hook *hook" +.Ft void +.Fn config_intrhook_oneshot "ich_func_t func" "void *arg" .Sh DESCRIPTION The .Fn config_intrhook_establish @@ -51,6 +54,18 @@ The .Fn config_intrhook_disestablish function removes the entry from the hook queue. .Pp +The +.Fn config_intrhook_oneshot +function schedules a function to be run as described for +.Fn config_intrhook_establish ; +the entry is automatically removed from the hook queue +after that function runs. +This is appropriate when additional device configuration must be done +after interrupts are enabled, but there is no need to stall the +boot process after that. +This function allocates memory using M_WAITOK; do not call this while +holding any non-sleepable locks. +.Pp Before root is mounted, all the previously established hooks are run. The boot process is then stalled until all handlers remove their hook @@ -71,8 +86,8 @@ This structure is defined as follows: .Bd -literal struct intr_config_hook { TAILQ_ENTRY(intr_config_hook) ich_links;/* Private */ - void (*ich_func)(void *arg); /* function to call */ - void *ich_arg; /* Argument to call */ + ich_func_t ich_func; /* function to call */ + void *ich_arg; /* Argument to call */ }; .Ed .Pp diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index bd4fadf084a8..64fe21a2bd75 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/linker.h> #include <sys/lock.h> +#include <sys/malloc.h> #include <sys/mutex.h> #include <sys/systm.h> @@ -63,6 +64,27 @@ MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock, "intr config", MTX_DEF); static void run_interrupt_driven_config_hooks(void); /* + * Private data and a shim function for implementing config_interhook_oneshot(). + */ +struct oneshot_config_hook { + struct intr_config_hook + och_hook; /* Must be first */ + ich_func_t och_func; + void *och_arg; +}; + +static void +config_intrhook_oneshot_func(void *arg) +{ + struct oneshot_config_hook *ohook; + + ohook = arg; + ohook->och_func(ohook->och_arg); + config_intrhook_disestablish(&ohook->och_hook); + free(ohook, M_DEVBUF); +} + +/* * If we wait too long for an interrupt-driven config hook to return, print * a diagnostic. */ @@ -183,6 +205,22 @@ config_intrhook_establish(struct intr_config_hook *hook) return (0); } +/* + * Register a hook function that is automatically unregistered after it runs. + */ +void +config_intrhook_oneshot(ich_func_t func, void *arg) +{ + struct oneshot_config_hook *ohook; + + ohook = malloc(sizeof(*ohook), M_DEVBUF, M_WAITOK); + ohook->och_func = func; + ohook->och_arg = arg; + ohook->och_hook.ich_func = config_intrhook_oneshot_func; + ohook->och_hook.ich_arg = ohook; + config_intrhook_establish(&ohook->och_hook); +} + void config_intrhook_disestablish(struct intr_config_hook *hook) { diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 7124349a8c2a..c9478fded4ac 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -400,13 +400,16 @@ struct tunable_str { #define TUNABLE_STR_FETCH(path, var, size) \ getenv_string((path), (var), (size)) +typedef void (*ich_func_t)(void *_arg); + struct intr_config_hook { TAILQ_ENTRY(intr_config_hook) ich_links; - void (*ich_func)(void *arg); - void *ich_arg; + ich_func_t ich_func; + void *ich_arg; }; int config_intrhook_establish(struct intr_config_hook *hook); void config_intrhook_disestablish(struct intr_config_hook *hook); +void config_intrhook_oneshot(ich_func_t _func, void *_arg); #endif /* !_SYS_KERNEL_H_*/ |