summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorloos <loos@FreeBSD.org>2015-01-31 12:17:07 +0000
committerloos <loos@FreeBSD.org>2015-01-31 12:17:07 +0000
commita2924f5feeb568dc5a1dc2b53be66542d8825e87 (patch)
tree32cccced059cc9d62c6880a990ae89819afccc09 /sys/arm
parent4b26a78e587bd62c2b734d552d2ec5a699e6d93f (diff)
downloadFreeBSD-src-a2924f5feeb568dc5a1dc2b53be66542d8825e87.zip
FreeBSD-src-a2924f5feeb568dc5a1dc2b53be66542d8825e87.tar.gz
Clean up and fix the device detach routine and the failure path on GPIO
drivers. This paves the way for upcoming work.
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/allwinner/a10_gpio.c7
-rw-r--r--sys/arm/altera/socfpga/socfpga_gpio.c1
-rw-r--r--sys/arm/freescale/imx/imx_gpio.c17
-rw-r--r--sys/arm/freescale/vybrid/vf_gpio.c1
-rw-r--r--sys/arm/rockchip/rk30xx_gpio.c13
-rw-r--r--sys/arm/samsung/exynos/exynos5_pad.c19
-rw-r--r--sys/arm/ti/ti_gpio.c28
7 files changed, 49 insertions, 37 deletions
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c
index 23bf399..12d6989 100644
--- a/sys/arm/allwinner/a10_gpio.c
+++ b/sys/arm/allwinner/a10_gpio.c
@@ -427,7 +427,7 @@ a10_gpio_attach(device_t dev)
RF_ACTIVE);
if (!sc->sc_mem_res) {
device_printf(dev, "cannot allocate memory window\n");
- return (ENXIO);
+ goto fail;
}
sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
@@ -437,9 +437,8 @@ a10_gpio_attach(device_t dev)
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE);
if (!sc->sc_irq_res) {
- bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
device_printf(dev, "cannot allocate interrupt\n");
- return (ENXIO);
+ goto fail;
}
/* Find our node. */
@@ -472,6 +471,8 @@ fail:
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ mtx_destroy(&sc->sc_mtx);
+
return (ENXIO);
}
diff --git a/sys/arm/altera/socfpga/socfpga_gpio.c b/sys/arm/altera/socfpga/socfpga_gpio.c
index 196c1e9..1a50c7c 100644
--- a/sys/arm/altera/socfpga/socfpga_gpio.c
+++ b/sys/arm/altera/socfpga/socfpga_gpio.c
@@ -163,6 +163,7 @@ socfpga_gpio_attach(device_t dev)
if (bus_alloc_resources(dev, socfpga_gpio_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
+ mtx_destroy(&sc->sc_mtx);
return (ENXIO);
}
diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c
index c23f75b..911c9bbb 100644
--- a/sys/arm/freescale/imx/imx_gpio.c
+++ b/sys/arm/freescale/imx/imx_gpio.c
@@ -389,6 +389,8 @@ imx51_gpio_attach(device_t dev)
if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) {
device_printf(dev, "could not allocate resources\n");
+ bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
+ mtx_destroy(&sc->sc_mtx);
return (ENXIO);
}
@@ -411,6 +413,7 @@ imx51_gpio_attach(device_t dev)
imx51_gpio_intr, NULL, sc, &sc->gpio_ih[irq]))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
+ imx51_gpio_detach(dev);
return (ENXIO);
}
}
@@ -434,6 +437,7 @@ imx51_gpio_attach(device_t dev)
static int
imx51_gpio_detach(device_t dev)
{
+ int irq;
struct imx51_gpio_softc *sc;
sc = device_get_softc(dev);
@@ -441,13 +445,12 @@ imx51_gpio_detach(device_t dev)
KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
bus_generic_detach(dev);
-
- if (sc->sc_res[3])
- bus_release_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]);
-
- if (sc->sc_res[0])
- bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
-
+ for (irq = 1; irq <= sc->sc_l_irq; irq ++) {
+ if (sc->gpio_ih[irq])
+ bus_teardown_intr(dev, sc->sc_res[irq], sc->gpio_ih[irq]);
+ }
+ bus_release_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]);
+ bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
mtx_destroy(&sc->sc_mtx);
return(0);
diff --git a/sys/arm/freescale/vybrid/vf_gpio.c b/sys/arm/freescale/vybrid/vf_gpio.c
index a31ff78..1fcf329 100644
--- a/sys/arm/freescale/vybrid/vf_gpio.c
+++ b/sys/arm/freescale/vybrid/vf_gpio.c
@@ -125,6 +125,7 @@ vf_gpio_attach(device_t dev)
if (bus_alloc_resources(dev, vf_gpio_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
+ mtx_destroy(&sc->sc_mtx);
return (ENXIO);
}
diff --git a/sys/arm/rockchip/rk30xx_gpio.c b/sys/arm/rockchip/rk30xx_gpio.c
index 6eb7db7..0728dbf 100644
--- a/sys/arm/rockchip/rk30xx_gpio.c
+++ b/sys/arm/rockchip/rk30xx_gpio.c
@@ -399,13 +399,14 @@ rk30_gpio_attach(device_t dev)
if (rk30_gpio_sc)
return (ENXIO);
sc->sc_dev = dev;
+ mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_mem_res) {
device_printf(dev, "cannot allocate memory window\n");
- return (ENXIO);
+ goto fail;
}
sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
@@ -421,17 +422,15 @@ rk30_gpio_attach(device_t dev)
if (sc->sc_bank == -1) {
device_printf(dev,
"unsupported device unit (only GPIO0..3 are supported)\n");
- bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
- return (ENXIO);
+ goto fail;
}
rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE);
if (!sc->sc_irq_res) {
- bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
device_printf(dev, "cannot allocate interrupt\n");
- return (ENXIO);
+ goto fail;
}
/* Find our node. */
@@ -441,8 +440,6 @@ rk30_gpio_attach(device_t dev)
/* Node is not a GPIO controller. */
goto fail;
- mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
-
/* Initialize the software controlled pins. */
for (i = 0; i < RK30_GPIO_PINS; i++) {
snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
@@ -467,6 +464,8 @@ fail:
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ mtx_destroy(&sc->sc_mtx);
+
return (ENXIO);
}
diff --git a/sys/arm/samsung/exynos/exynos5_pad.c b/sys/arm/samsung/exynos/exynos5_pad.c
index c28ebb1..0e58bf5 100644
--- a/sys/arm/samsung/exynos/exynos5_pad.c
+++ b/sys/arm/samsung/exynos/exynos5_pad.c
@@ -509,12 +509,12 @@ pad_attach(device_t dev)
sc->nports = 5;
break;
default:
- return (-1);
+ goto fail;
};
if (bus_alloc_resources(dev, sc->pad_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
- return (ENXIO);
+ goto fail;
}
/* Memory interface */
@@ -534,9 +534,9 @@ pad_attach(device_t dev)
NULL, sc, &sc->gpio_ih[i]))) {
device_printf(dev,
"ERROR: Unable to register interrupt handler\n");
- return (ENXIO);
+ goto fail;
}
- };
+ }
for (i = 0; i < sc->gpio_npins; i++) {
sc->gpio_pins[i].gp_pin = i;
@@ -563,6 +563,17 @@ pad_attach(device_t dev)
device_add_child(dev, "gpiobus", -1);
return (bus_generic_attach(dev));
+
+fail:
+ for (i = 0; i < sc->nports; i++) {
+ if (sc->gpio_ih[i])
+ bus_teardown_intr(dev, sc->res[sc->nports + i],
+ sc->gpio_ih[i]);
+ }
+ bus_release_resources(dev, sc->pad_spec, sc->res);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (ENXIO);
}
static int
diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
index ed24958..8874ff3 100644
--- a/sys/arm/ti/ti_gpio.c
+++ b/sys/arm/ti/ti_gpio.c
@@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#define TI_GPIO_MASK(p) (1U << ((p) % PINS_PER_BANK))
static struct ti_gpio_softc *ti_gpio_sc = NULL;
+static int ti_gpio_detach(device_t);
static u_int
ti_max_gpio_banks(void)
@@ -763,21 +764,21 @@ ti_gpio_attach(device_t dev)
*/
if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) {
device_printf(dev, "Error: could not allocate mem resources\n");
+ ti_gpio_detach(dev);
return (ENXIO);
}
/* Request the IRQ resources */
if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) {
- bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
device_printf(dev, "Error: could not allocate irq resources\n");
+ ti_gpio_detach(dev);
return (ENXIO);
}
/* Setup the IRQ resources */
if (ti_gpio_attach_intr(dev) != 0) {
- ti_gpio_detach_intr(dev);
- bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
- bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
+ device_printf(dev, "Error: could not setup irq handlers\n");
+ ti_gpio_detach(dev);
return (ENXIO);
}
@@ -809,11 +810,7 @@ ti_gpio_attach(device_t dev)
/* Initialize the GPIO module. */
err = ti_gpio_bank_init(dev, i);
if (err != 0) {
- ti_gpio_detach_intr(dev);
- bus_release_resources(dev, ti_gpio_irq_spec,
- sc->sc_irq_res);
- bus_release_resources(dev, ti_gpio_mem_spec,
- sc->sc_mem_res);
+ ti_gpio_detach(dev);
return (err);
}
}
@@ -852,18 +849,17 @@ ti_gpio_detach(device_t dev)
if (sc->sc_mem_res[i] != NULL)
ti_gpio_intr_clr(sc, i, 0xffffffff);
}
-
bus_generic_detach(dev);
-
- free(sc->sc_events, M_DEVBUF);
- free(sc->sc_irq_polarity, M_DEVBUF);
- free(sc->sc_irq_trigger, M_DEVBUF);
-
+ if (sc->sc_events)
+ free(sc->sc_events, M_DEVBUF);
+ if (sc->sc_irq_polarity)
+ free(sc->sc_irq_polarity, M_DEVBUF);
+ if (sc->sc_irq_trigger)
+ free(sc->sc_irq_trigger, M_DEVBUF);
/* Release the memory and IRQ resources. */
ti_gpio_detach_intr(dev);
bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res);
-
TI_GPIO_LOCK_DESTROY(sc);
return (0);
OpenPOWER on IntegriCloud