diff options
author | yongari <yongari@FreeBSD.org> | 2004-10-15 03:50:04 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2004-10-15 03:50:04 +0000 |
commit | 20da9f17e35c33a9f08d08d4a049bee31fd20741 (patch) | |
tree | c063c7d172df3da134b8154b3559d45c4db2ba37 | |
parent | 00b5d02fd05a3ab00d0b5fcbda7f7ae0eb19e180 (diff) | |
download | FreeBSD-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.c | 33 |
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 |