summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lepore <ian@FreeBSD.org>2017-08-13 18:10:24 +0000
committerIan Lepore <ian@FreeBSD.org>2017-08-13 18:10:24 +0000
commit2db14f97de02470dd2117179c291930ffab3b6ba (patch)
treeca8c08e1bf03d9dc303f5368dffad01c349ecb30
parent037331ddbd44ed4331f24a567acca874872b735a (diff)
Notes
-rw-r--r--share/man/man9/Makefile3
-rw-r--r--share/man/man9/config_intrhook.921
-rw-r--r--sys/kern/subr_autoconf.c38
-rw-r--r--sys/sys/kernel.h7
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_*/