Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile +++ share/man/man9/Makefile @@ -858,6 +858,7 @@ condvar.9 cv_wait_unlock.9 \ condvar.9 cv_wmesg.9 MLINKS+=config_intrhook.9 config_intrhook_disestablish.9 \ + config_intrhook.9 config_intrhook_drain.9 \ config_intrhook.9 config_intrhook_establish.9 \ config_intrhook.9 config_intrhook_oneshot.9 MLINKS+=contigmalloc.9 contigmalloc_domainset.9 \ Index: share/man/man9/config_intrhook.9 =================================================================== --- share/man/man9/config_intrhook.9 +++ share/man/man9/config_intrhook.9 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 10, 2017 +.Dd March 1, 2021 .Dt CONFIG_INTRHOOK 9 .Os .Sh NAME @@ -41,6 +41,8 @@ .Ft void .Fn config_intrhook_disestablish "struct intr_config_hook *hook" .Ft void +.Fn config_intrhook_drain "struct intr_config_hook *hook" +.Ft void .Fn config_intrhook_oneshot "ich_func_t func" "void *arg" .Sh DESCRIPTION The @@ -55,6 +57,13 @@ function removes the entry from the hook queue. .Pp The +.Fn config_intrhook_drain +function removes the entry from the hook queue in a safe way. +If the hook is not currently active it removes it from the hook queue. +If the hook is active, it will wait for the hook to complete and return. +If the hook has previously completed, it will return immediately. +.Pp +The .Fn config_intrhook_oneshot function schedules a function to be run as described for .Fn config_intrhook_establish ; Index: sys/dev/nvme/nvme.c =================================================================== --- sys/dev/nvme/nvme.c +++ sys/dev/nvme/nvme.c @@ -143,10 +143,7 @@ { struct nvme_controller *ctrlr = DEVICE2SOFTC(dev); - if (ctrlr->config_hook.ich_arg != NULL) { - config_intrhook_disestablish(&ctrlr->config_hook); - ctrlr->config_hook.ich_arg = NULL; - } + config_intrhook_drain(&ctrlr->config_hook); nvme_ctrlr_destruct(ctrlr, dev); return (0); Index: sys/dev/nvme/nvme_ctrlr.c =================================================================== --- sys/dev/nvme/nvme_ctrlr.c +++ sys/dev/nvme/nvme_ctrlr.c @@ -1135,7 +1135,6 @@ fail: nvme_ctrlr_fail(ctrlr); config_intrhook_disestablish(&ctrlr->config_hook); - ctrlr->config_hook.ich_arg = NULL; return; } @@ -1154,7 +1153,6 @@ nvme_sysctl_initialize_ctrlr(ctrlr); config_intrhook_disestablish(&ctrlr->config_hook); - ctrlr->config_hook.ich_arg = NULL; ctrlr->is_initialized = 1; nvme_notify_new_controller(ctrlr); Index: sys/kern/subr_autoconf.c =================================================================== --- sys/kern/subr_autoconf.c +++ sys/kern/subr_autoconf.c @@ -245,7 +245,7 @@ TSRELEASE("config hooks"); /* Wakeup anyone watching the list */ - hook->ich_flags &= ~ICHF_RUNNING; + hook->ich_flags |= ICHF_DONE; wakeup(&intr_config_hook_list); } @@ -261,8 +261,17 @@ config_intrhook_drain(struct intr_config_hook *hook) { mtx_lock(&intr_config_hook_lock); + + /* + * The config hook has completed, so just return. + */ + if ((hook->ich_flags & ICHF_DONE) != 0) { + mtx_unlock(&intr_config_hook_lock); + return; + } + /* - * The config hook is not running, so just call disestablish + * The config hook is hasn't started running, just call disestablish. */ if ((hook->ich_flags & ICHF_RUNNING) == 0) { config_intrhook_disestablish_locked(hook); @@ -273,7 +282,7 @@ /* * The config hook is running, so wait for it to complete and return. */ - while (hook->ich_flags & ICHF_RUNNING) { + while ((hook->ich_flags & ICHF_DONE) == 0) { if (msleep(&intr_config_hook_list, &intr_config_hook_lock, 0, "confhd", hz) == EWOULDBLOCK) { // XXX do I whine?