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 *));

Reply via email to