summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2004-10-15 03:50:04 +0000
committeryongari <yongari@FreeBSD.org>2004-10-15 03:50:04 +0000
commit20da9f17e35c33a9f08d08d4a049bee31fd20741 (patch)
treec063c7d172df3da134b8154b3559d45c4db2ba37
parent00b5d02fd05a3ab00d0b5fcbda7f7ae0eb19e180 (diff)
downloadFreeBSD-src-20da9f17e35c33a9f08d08d4a049bee31fd20741.zip
FreeBSD-src-20da9f17e35c33a9f08d08d4a049bee31fd20741.tar.gz
Plug possible memory leak in sound DMA buffer handling. It also
changes return code to ENOMEM in case of allocation failure. Approved by: jake (mentor), scottl (co-mentor) Reviewed by: truckman, matk
-rw-r--r--sys/dev/sound/pcm/buffer.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c
index 773bc35..096262c 100644
--- a/sys/dev/sound/pcm/buffer.c
+++ b/sys/dev/sound/pcm/buffer.c
@@ -61,11 +61,14 @@ sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
struct snd_dbuf *b = (struct snd_dbuf *)arg;
if (bootverbose) {
- device_printf(b->dev, "sndbuf_setmap %lx, %lx; ", (unsigned long)segs->ds_addr,
- (unsigned long)segs->ds_len);
- printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf));
+ device_printf(b->dev, "sndbuf_setmap %lx, %lx; ",
+ (u_long)segs[0].ds_addr, (u_long)segs[0].ds_len);
+ printf("%p -> %lx\n", b->buf, (u_long)segs[0].ds_addr);
}
- b->buf_addr = segs->ds_addr;
+ if (error == 0)
+ b->buf_addr = segs[0].ds_addr;
+ else
+ b->buf_addr = 0;
}
/*
@@ -76,14 +79,26 @@ sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
int
sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size)
{
+ int ret;
+
b->dmatag = dmatag;
b->maxsize = size;
b->bufsize = b->maxsize;
- if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT, &b->dmamap))
- return ENOSPC;
- if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, sndbuf_setmap, b, 0))
- return ENOSPC;
- return sndbuf_resize(b, 2, b->maxsize / 2);
+ b->buf_addr = 0;
+ if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT,
+ &b->dmamap))
+ return (ENOMEM);
+ if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize,
+ sndbuf_setmap, b, 0) != 0 || b->buf_addr == 0) {
+ bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
+ b->dmamap = NULL;
+ return (ENOMEM);
+ }
+
+ ret = sndbuf_resize(b, 2, b->maxsize / 2);
+ if (ret != 0)
+ sndbuf_free(b);
+ return (ret);
}
int
OpenPOWER on IntegriCloud