From d8990b16e2c5174ace38ceeb2eca5322b0ba9913 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Mon, 31 Jan 2022 22:56:03 +0000 Subject: [PATCH 36/37] autoconf(9): Disentangle slightly circuitous config_detach logic. No functional change intended. --- sys/kern/subr_autoconf.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index 03afc7f54b55..5c1c865785f8 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -2029,6 +2029,11 @@ config_detach(device_t dev, int flags) alldevs_nwrite++; mutex_exit(&alldevs_lock); + /* + * Call the driver's .ca_detach function, unless it has none or + * we are skipping it because it's unforced shutdown time and + * the driver didn't ask to detach on shutdown. + */ if (!detachall && (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN && (dev->dv_flags & DVF_DETACH_SHUTDOWN) == 0) { @@ -2041,31 +2046,39 @@ config_detach(device_t dev, int flags) /* * If it was not possible to detach the device, then we either * panic() (for the forced but failed case), or return an error. - * - * If it was possible to detach the device, ensure that the - * device is deactivated. */ - if (rv == 0) { - config_detach_commit(dev); - dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */ - } else if ((flags & DETACH_FORCE) == 0) { + if (rv) { /* - * Detach failed -- likely EBUSY. Driver must not have - * called config_detach_commit. + * Detach failed -- likely EOPNOTSUPP or EBUSY. Driver + * must not have called config_detach_commit. */ KASSERTMSG(!dev->dv_detached, "%s committed to detaching and then backed out", device_xname(dev)); + if (flags & DETACH_FORCE) { + panic("config_detach: forced detach of %s failed (%d)", + device_xname(dev), rv); + } goto out; - } else { - panic("config_detach: forced detach of %s failed (%d)", - device_xname(dev), rv); } /* * The device has now been successfully detached. */ + /* + * If .ca_detach didn't commit to detach, then do that for it. + * This wakes any pending device_lookup_acquire calls so they + * will fail. + */ + config_detach_commit(dev); + + /* + * If it was possible to detach the device, ensure that the + * device is deactivated. + */ + dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */ + /* * Wait for all device_lookup_acquire references -- mostly, for * all attempts to open the device -- to drain. It is the