Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Fix leaks in oosiop_alloc_cb error branches, note...
details: https://anonhg.NetBSD.org/src/rev/1cf10955e8e5
branches: trunk
changeset: 331643:1cf10955e8e5
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Aug 18 03:43:10 2014 +0000
description:
Fix leaks in oosiop_alloc_cb error branches, noted by maxv@.
While here, avoid a sketchy pointer cast that probably falls afoul of
strict aliasing rules.
Compile-tested only, with hppa.
diffstat:
sys/dev/ic/oosiop.c | 70 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 47 insertions(+), 23 deletions(-)
diffs (136 lines):
diff -r 82eea4a13e26 -r 1cf10955e8e5 sys/dev/ic/oosiop.c
--- a/sys/dev/ic/oosiop.c Mon Aug 18 03:14:12 2014 +0000
+++ b/sys/dev/ic/oosiop.c Mon Aug 18 03:43:10 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: oosiop.c,v 1.13 2010/11/13 13:52:02 uebayasi Exp $ */
+/* $NetBSD: oosiop.c,v 1.14 2014/08/18 03:43:10 riastradh Exp $ */
/*
* Copyright (c) 2001 Shuichiro URATA. All rights reserved.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: oosiop.c,v 1.13 2010/11/13 13:52:02 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: oosiop.c,v 1.14 2014/08/18 03:43:10 riastradh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -247,6 +247,7 @@
oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
{
struct oosiop_cb *cb;
+ void *xfer_kva;
struct oosiop_xfer *xfer;
bus_size_t xfersize;
bus_dma_segment_t seg;
@@ -258,7 +259,8 @@
cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT|M_ZERO);
if (cb == NULL) {
printf(": failed to allocate cb memory\n");
- return (ENOMEM);
+ err = ENOMEM;
+ goto fail0;
}
/*
@@ -269,57 +271,79 @@
&nseg, BUS_DMA_NOWAIT);
if (err) {
printf(": failed to allocate xfer block memory, err=%d\n", err);
- return (err);
+ goto fail1;
}
- err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
- (void **)(void *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ KASSERT(nseg == 1);
+ err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize, &xfer_kva,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
if (err) {
printf(": failed to map xfer block memory, err=%d\n", err);
- return (err);
+ goto fail2;
}
+ xfer = xfer_kva;
/* Initialize each command block */
for (i = 0; i < ncb; i++) {
err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
- 0, BUS_DMA_NOWAIT, &cb->cmddma);
+ 0, BUS_DMA_NOWAIT, &cb[i].cmddma);
if (err) {
printf(": failed to create cmddma map, err=%d\n", err);
- return (err);
+ goto loop_fail0;
}
err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER,
OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT,
- &cb->datadma);
+ &cb[i].datadma);
if (err) {
printf(": failed to create datadma map, err=%d\n", err);
- return (err);
+ goto loop_fail1;
}
err = bus_dmamap_create(sc->sc_dmat,
sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer),
- 0, BUS_DMA_NOWAIT, &cb->xferdma);
+ 0, BUS_DMA_NOWAIT, &cb[i].xferdma);
if (err) {
printf(": failed to create xfer block map, err=%d\n",
err);
- return (err);
+ goto loop_fail2;
}
- err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer,
+ err = bus_dmamap_load(sc->sc_dmat, cb[i].xferdma, xfer,
sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT);
if (err) {
printf(": failed to load xfer block, err=%d\n", err);
- return (err);
+ goto loop_fail3;
}
- cb->xfer = xfer;
+ cb[i].xfer = &xfer[i];
+ continue;
- s = splbio();
- TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
- splx(s);
-
- cb++;
- xfer++;
+loop_fail4: __unused
+ bus_dmamap_unload(sc->sc_dmat, cb[i].xferdma);
+loop_fail3: bus_dmamap_destroy(sc->sc_dmat, cb[i].xferdma);
+loop_fail2: bus_dmamap_destroy(sc->sc_dmat, cb[i].datadma);
+loop_fail1: bus_dmamap_destroy(sc->sc_dmat, cb[i].cmddma);
+loop_fail0: goto fail3;
}
- return (0);
+ for (i = 0; i < ncb; i++) {
+ s = splbio();
+ TAILQ_INSERT_TAIL(&sc->sc_free_cb, &cb[i], chain);
+ splx(s);
+ }
+
+ /* Success! */
+ return 0;
+
+fail3: while (i--) {
+ bus_dmamap_unload(sc->sc_dmat, cb[i].xferdma);
+ bus_dmamap_destroy(sc->sc_dmat, cb[i].xferdma);
+ bus_dmamap_destroy(sc->sc_dmat, cb[i].datadma);
+ bus_dmamap_destroy(sc->sc_dmat, cb[i].cmddma);
+ }
+ bus_dmamem_unmap(sc->sc_dmat, xfer_kva, xfersize);
+fail2: bus_dmamem_free(sc->sc_dmat, &seg, 1);
+fail1: free(cb, M_DEVBUF);
+fail0: KASSERT(err);
+ return err;
}
static inline void
Home |
Main Index |
Thread Index |
Old Index