diff options
author | imp <imp@FreeBSD.org> | 2006-12-05 06:11:10 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2006-12-05 06:11:10 +0000 |
commit | d4e519a36a0233b7206a8879f41929e3929c5279 (patch) | |
tree | 9250337f2b7fd75c0ad8f4701c8698c8ce799421 /sys | |
parent | d8269ebb497800fe71e8016ceb0e5a2c2085aaff (diff) | |
download | FreeBSD-src-d4e519a36a0233b7206a8879f41929e3929c5279.zip FreeBSD-src-d4e519a36a0233b7206a8879f41929e3929c5279.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/iicbus/iicbb.c | 33 |
1 files changed, 27 insertions, 6 deletions
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) { |