iicbus: Use device_delete_children() instead of explicit child removal

If the bus is detached and deleted by a call to device_delete_child() or
device_delete_children() on a device higher in the tree, I²C children
were already detached and deleted. So the device_t pointer stored in sc
points to freed memory: we must not try to delete it again.

By using device_delete_children(), we let subr_bus.c figure out if there
are children to take care of.

While here, make sure iicbus_detach() and iicoc_detach() call
device_delete_children() too, to be safe.

Reviewed by:	jhb, imp
Approved by:	jhb, imp
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D3926
This commit is contained in:
Jean-Sébastien Pédron 2015-10-20 19:52:59 +00:00
parent b90d6d94c1
commit 238b89fcad
4 changed files with 5 additions and 18 deletions

View File

@ -149,22 +149,9 @@ iicbb_attach(device_t dev)
static int
iicbb_detach(device_t dev)
{
struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
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);
device_delete_children(dev);
return (0);
}

View File

@ -135,6 +135,7 @@ iicbus_detach(device_t dev)
iicbus_reset(dev, IIC_FASTEST, 0, NULL);
bus_generic_detach(dev);
device_delete_children(dev);
mtx_destroy(&sc->lock);
return (0);
}

View File

@ -229,6 +229,7 @@ static int
iicoc_detach(device_t dev)
{
bus_generic_detach(dev);
device_delete_children(dev);
return (0);
}

View File

@ -167,11 +167,9 @@ static int
iicsmb_detach(device_t dev)
{
struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev);
bus_generic_detach(dev);
if (sc->smbus) {
device_delete_child(dev, sc->smbus);
}
device_delete_children(dev);
mtx_destroy(&sc->lock);
return (0);