Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Aug 2015 16:51:38 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286845 - head/sys/dev/gpio
Message-ID:  <201508171651.t7HGpcLc026127@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: loos
Date: Mon Aug 17 16:51:37 2015
New Revision: 286845
URL: https://svnweb.freebsd.org/changeset/base/286845

Log:
  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)

Modified:
  head/sys/dev/gpio/gpiobus.c

Modified: head/sys/dev/gpio/gpiobus.c
==============================================================================
--- head/sys/dev/gpio/gpiobus.c	Mon Aug 17 13:07:12 2015	(r286844)
+++ head/sys/dev/gpio/gpiobus.c	Mon Aug 17 16:51:37 2015	(r286845)
@@ -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 or
 	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
 	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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508171651.t7HGpcLc026127>