Hi, could we allow config_attach() to 'fail' without leaving dead device behind? ie. with gpioow(4) it's easy to make a load of these while testing stuff, which does lead to inconsistent unit numbering unless you manually detach the broken ones before attaching another..
for devices which are found during autoconf, i guess DETACH_QUIET would be wanted to keep dmesg pretty, as the error messages printed from any ca->ca_attach() should be enough, and would mean no visible change for drivers failing out with this:) for smaller diff i chose to use the DVF_ACTIVE, while i'd actually prefer adding "DVF_FAILED" or something. untested morning-coffee-qual.diff below. comments? -Artturi diff --git sys/dev/gpio/gpioow.c sys/dev/gpio/gpioow.c index 64d79ab0cb8..912537b7de7 100644 --- sys/dev/gpio/gpioow.c +++ sys/dev/gpio/gpioow.c @@ -101,7 +101,7 @@ gpioow_attach(struct device *parent, struct device *self, void *aux) /* Check that we have enough pins */ if (gpio_npins(ga->ga_mask) != GPIOOW_NPINS) { printf(": invalid pin mask\n"); - return; + goto fail_nomap; } /* Map pins */ @@ -110,7 +110,7 @@ gpioow_attach(struct device *parent, struct device *self, void *aux) if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, &sc->sc_map)) { printf(": can't map pins\n"); - return; + goto fail_nomap; } /* Configure data pin */ @@ -153,6 +153,8 @@ gpioow_attach(struct device *parent, struct device *self, void *aux) fail: gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); +fail_nomap: + config_defer_failure(self); } int diff --git sys/kern/subr_autoconf.c sys/kern/subr_autoconf.c index 3fff153e8ad..9a797712510 100644 --- sys/kern/subr_autoconf.c +++ sys/kern/subr_autoconf.c @@ -409,6 +409,11 @@ config_attach(struct device *parent, void *match, void *aux, cfprint_t print) if (--autoconf_attdet == 0) wakeup(&autoconf_attdet); mtx_leave(&autoconf_attdet_mtx); + + if ((dev->dv_flags & DVF_ACTIVE) == 0) { + if (config_detach(dev, 0) == 0) + dev = NULL; + } return (dev); } @@ -678,6 +683,17 @@ config_defer(struct device *dev, void (*func)(struct device *)) config_pending_incr(); } +/* + * Defer the detachment of the specified device until the end + * of its own configuration. + */ +void +config_defer_failure(struct device *dev) +{ + + dev->dv_flags &= ~DVF_ACTIVE; +} + /* * Defer the configuration of the specified device until after * root file system is mounted. diff --git sys/sys/device.h sys/sys/device.h index 00a1f6ad2a6..3820cc6e0f5 100644 --- sys/sys/device.h +++ sys/sys/device.h @@ -185,6 +185,7 @@ int config_activate_children(struct device *, int); struct device *config_make_softc(struct device *parent, struct cfdata *cf); void config_defer(struct device *, void (*)(struct device *)); +void config_defer_failure(struct device *); void config_pending_incr(void); void config_pending_decr(void); void config_mountroot(struct device *, void (*)(struct device *));