From d4e519a36a0233b7206a8879f41929e3929c5279 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 5 Dec 2006 06:11:10 +0000 Subject: More properly cleanup the iicbus child when deleting it. These are from patches by John Wehle, but the commentary has been updated by me. Obtained from: ports/multimedia/pvr250, indirectly --- sys/dev/iicbus/iicbb.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'sys/dev/iicbus/iicbb.c') diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c index 6c70478..7fa80c1 100644 --- a/sys/dev/iicbus/iicbb.c +++ b/sys/dev/iicbus/iicbb.c @@ -63,10 +63,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); @@ -82,6 +83,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 */ @@ -129,15 +131,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) { -- cgit v1.1