aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/gpio/gpiobus.c
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <loos@FreeBSD.org>2015-08-17 16:51:37 +0000
committerLuiz Otavio O Souza <loos@FreeBSD.org>2015-08-17 16:51:37 +0000
commit978cdbedcdbf5dc067ce389771c5c18572d1319f (patch)
tree1a3a9d68b8e9a45cd707dd6b3c9908585f3762a1 /sys/dev/gpio/gpiobus.c
parentedcf7fbf595d66836eccafa5e612cfbad9025bfb (diff)
downloadsrc-978cdbedcdbf5dc067ce389771c5c18572d1319f.tar.gz
src-978cdbedcdbf5dc067ce389771c5c18572d1319f.zip
Fix a few bugs when gpiobus is detaching:
- Detach the gpiobus and the gpioc devices from the GPIO controller. - Fix the leak of gpiobus IRQ rman(9) region descriptor. - Fix the leak of child ivars and IRQ resource list. While here return NULL (instead of 0) for a device_t that fails to allocate the ivar memory. Tested with gpiobus built as a module. Sponsored by: Rubicon Communications (Netgate)
Notes
Notes: svn path=/head/; revision=286845
Diffstat (limited to 'sys/dev/gpio/gpiobus.c')
-rw-r--r--sys/dev/gpio/gpiobus.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index e741d288dbe9..6cafdafe9c61 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -155,12 +155,16 @@ gpiobus_attach_bus(device_t dev)
int
gpiobus_detach_bus(device_t dev)
{
+ int err;
#ifdef FDT
ofw_gpiobus_unregister_provider(dev);
#endif
+ err = bus_generic_detach(dev);
+ if (err != 0)
+ return (err);
- return (bus_generic_detach(dev));
+ return (device_delete_children(dev));
}
int
@@ -338,11 +342,14 @@ gpiobus_detach(device_t dev)
if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
return (err);
for (i = 0; i < ndevs; i++) {
- device_delete_child(dev, devlist[i]);
devi = GPIOBUS_IVAR(devlist[i]);
gpiobus_free_ivars(devi);
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(dev, devlist[i]);
}
free(devlist, M_TEMP);
+ rman_fini(&sc->sc_intr_rman);
if (sc->sc_pins) {
for (i = 0; i < sc->sc_npins; i++) {
if (sc->sc_pins[i].name != NULL)
@@ -442,7 +449,7 @@ gpiobus_add_child(device_t dev, u_int order, const char *name, int unit)
devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
if (devi == NULL) {
device_delete_child(dev, child);
- return (0);
+ return (NULL);
}
resource_list_init(&devi->rl);
device_set_ivars(child, devi);
@@ -461,8 +468,11 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
devi = GPIOBUS_IVAR(child);
resource_int_value(dname, dunit, "pins", &pins);
- if (gpiobus_parse_pins(sc, child, pins))
+ if (gpiobus_parse_pins(sc, child, pins)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
device_delete_child(bus, child);
+ }
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
device_printf(bus,