Bring in two updates from FreeBSD.
authorSascha Wildner <saw@online.de>
Thu, 25 Dec 2008 01:04:19 +0000 (02:04 +0100)
committerSascha Wildner <saw@online.de>
Thu, 25 Dec 2008 01:04:38 +0000 (02:04 +0100)
r1.14 - newbus will zero softc, so no need to duplicate the zeroing here.
r1.18 - More properly cleanup the iicbus child when deleting it.[1]

[1] Tested-by:  Vincent Stemen <vince.dragonfly@hightek.org>

sys/bus/iicbus/iicbb.c

index 8019799..6cd9e36 100644 (file)
@@ -69,10 +69,11 @@ struct iicbb_softc {
        device_t iicbus;
 };
 
-static int iicbb_probe(device_t);
 static int iicbb_attach(device_t);
+static void iicbb_child_detached(device_t, device_t);
 static int iicbb_detach(device_t);
 static int iicbb_print_child(device_t, device_t);
+static int iicbb_probe(device_t);
 
 static int iicbb_callback(device_t, int, caddr_t);
 static int iicbb_start(device_t, u_char, int);
@@ -88,6 +89,7 @@ static device_method_t iicbb_methods[] = {
        DEVMETHOD(device_detach,        iicbb_detach),
 
        /* bus interface */
+       DEVMETHOD(bus_child_detached,   iicbb_child_detached),
        DEVMETHOD(bus_print_child,      iicbb_print_child),
 
        /* iicbus interface */
@@ -123,13 +125,9 @@ iicbb_attach(device_t dev)
 {
        struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
 
-       bzero(sc, sizeof(struct iicbb_softc));
-
        sc->iicbus = device_add_child(dev, "iicbus", -1);
-
        if (!sc->iicbus)
                return (ENXIO);
-
        bus_generic_attach(dev);
 
        return (0);
@@ -139,15 +137,34 @@ static int
 iicbb_detach(device_t dev)
 {
        struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
-
-       if (sc->iicbus) {
-               bus_generic_detach(dev);
-               device_delete_child(dev, sc->iicbus);
-       }
+       device_t child;
+
+       /*
+        * We need to save child because the detach indirectly causes
+        * sc->iicbus to be zeroed.  Since we added the device
+        * unconditionally in iicbb_attach, we need to make sure we
+        * delete it here.  See iicbb_child_detached.  We need that
+        * callback in case newbus detached our children w/o detaching
+        * us (say iicbus is a module and unloaded w/o iicbb being
+        * unloaded).
+        */
+       child = sc->iicbus;
+       bus_generic_detach(dev);
+       if (child)
+               device_delete_child(dev, child);
 
        return (0);
 }
 
+static void
+iicbb_child_detached( device_t dev, device_t child )
+{
+       struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
+
+       if (child == sc->iicbus)
+               sc->iicbus = NULL;
+}
+
 static int
 iicbb_print_child(device_t bus, device_t dev)
 {