Index: sys/kern/subr_autoconf.c =================================================================== --- sys/kern/subr_autoconf.c +++ sys/kern/subr_autoconf.c @@ -138,6 +138,7 @@ while (next_to_notify != NULL) { hook_entry = next_to_notify; next_to_notify = STAILQ_NEXT(hook_entry, ich_links); + hook_entry->ich_flags |= ICHF_RUNNING; mtx_unlock(&intr_config_hook_lock); (*hook_entry->ich_func)(hook_entry->ich_arg); mtx_lock(&intr_config_hook_lock); @@ -226,12 +227,11 @@ config_intrhook_establish(&ohook->och_hook); } -void -config_intrhook_disestablish(struct intr_config_hook *hook) +static void +config_intrhook_disestablish_locked(struct intr_config_hook *hook) { struct intr_config_hook *hook_entry; - mtx_lock(&intr_config_hook_lock); STAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) if (hook_entry == hook) break; @@ -245,7 +245,40 @@ TSRELEASE("config hooks"); /* Wakeup anyone watching the list */ + hook->ich_flags &= ~ICHF_RUNNING; wakeup(&intr_config_hook_list); +} + +void +config_intrhook_disestablish(struct intr_config_hook *hook) +{ + mtx_lock(&intr_config_hook_lock); + config_intrhook_disestablish_locked(hook); + mtx_unlock(&intr_config_hook_lock); +} + +void +config_intrhook_drain(struct intr_config_hook *hook) +{ + mtx_lock(&intr_config_hook_lock); + /* + * The config hook is not running, so just call disestablish + */ + if ((hook->ich_flags & ICHF_RUNNING) == 0) { + config_intrhook_disestablish_locked(hook); + mtx_unlock(&intr_config_hook_lock); + return; + } + + /* + * The config hook is running, so wait for it to complete and return. + */ + while (hook->ich_flags & ICHF_RUNNING) { + if (msleep(&intr_config_hook_list, &intr_config_hook_lock, + 0, "confhd", hz) == EWOULDBLOCK) { + // XXX do I whine? + } + } mtx_unlock(&intr_config_hook_lock); } Index: sys/sys/kernel.h =================================================================== --- sys/sys/kernel.h +++ sys/sys/kernel.h @@ -475,6 +475,7 @@ int config_intrhook_establish(struct intr_config_hook *hook); void config_intrhook_disestablish(struct intr_config_hook *hook); +void config_intrhook_drain(struct intr_config_hook *hook); void config_intrhook_oneshot(ich_func_t _func, void *_arg); #endif /* !_SYS_KERNEL_H_*/