intpm: better clean up resources after a failed attachment

bus_generic_detach() fails when called from attach method
thus preventing further clean up actions.

MFC after:	1 week
This commit is contained in:
Andriy Gapon 2016-09-08 12:27:34 +00:00
parent c47117f43a
commit a2f51f57d1

View File

@ -199,6 +199,23 @@ sb8xx_attach(device_t dev)
return (0); return (0);
} }
static void
intsmb_release_resources(device_t dev)
{
struct intsmb_softc *sc = device_get_softc(dev);
if (sc->smbus)
device_delete_child(dev, sc->smbus);
if (sc->irq_hand)
bus_teardown_intr(dev, sc->irq_res, sc->irq_hand);
if (sc->irq_res)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
if (sc->io_res)
bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid,
sc->io_res);
mtx_destroy(&sc->lock);
}
static int static int
intsmb_attach(device_t dev) intsmb_attach(device_t dev)
{ {
@ -311,12 +328,15 @@ no_intr:
sc->isbusy = 0; sc->isbusy = 0;
sc->smbus = device_add_child(dev, "smbus", -1); sc->smbus = device_add_child(dev, "smbus", -1);
if (sc->smbus == NULL) { if (sc->smbus == NULL) {
device_printf(dev, "failed to add smbus child\n");
error = ENXIO; error = ENXIO;
goto fail; goto fail;
} }
error = device_probe_and_attach(sc->smbus); error = device_probe_and_attach(sc->smbus);
if (error) if (error) {
device_printf(dev, "failed to probe+attach smbus child\n");
goto fail; goto fail;
}
#ifdef ENABLE_ALART #ifdef ENABLE_ALART
/* Enable Arart */ /* Enable Arart */
@ -325,30 +345,22 @@ no_intr:
return (0); return (0);
fail: fail:
intsmb_detach(dev); intsmb_release_resources(dev);
return (error); return (error);
} }
static int static int
intsmb_detach(device_t dev) intsmb_detach(device_t dev)
{ {
struct intsmb_softc *sc = device_get_softc(dev);
int error; int error;
error = bus_generic_detach(dev); error = bus_generic_detach(dev);
if (error) if (error) {
device_printf(dev, "bus detach failed\n");
return (error); return (error);
}
if (sc->smbus) intsmb_release_resources(dev);
device_delete_child(dev, sc->smbus);
if (sc->irq_hand)
bus_teardown_intr(dev, sc->irq_res, sc->irq_hand);
if (sc->irq_res)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
if (sc->io_res)
bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid,
sc->io_res);
mtx_destroy(&sc->lock);
return (0); return (0);
} }