Fix various bugs with freeing static DMA allocations in sound drivers:

- Don't compare the DMA map to NULL to determine if bus_dmamap_unload()
  should be called when releasing a static allocation.  Instead, compare
  the bus address against 0.
- Don't assume that the DMA map for static allocations is NULL.  Instead,
  save the value set by bus_dmamem_alloc() so it can later be passed to
  bus_dmamem_free().  Also, add missing calls to bus_dmamap_unload() in
  these cases before freeing the buffer.
- Use the bus address from the bus_dma callback instead of calling
  vtophys() on the address allocated by bus_dmamem_alloc().

Reviewed by:	kan
This commit is contained in:
John Baldwin 2014-06-17 16:07:57 +00:00
parent c34f1a08c6
commit 86843ea8de
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=267581
11 changed files with 97 additions and 82 deletions

View File

@ -1146,13 +1146,14 @@ atiixp_release_resource(struct atiixp_info *sc)
bus_dma_tag_destroy(sc->parent_dmat); bus_dma_tag_destroy(sc->parent_dmat);
sc->parent_dmat = NULL; sc->parent_dmat = NULL;
} }
if (sc->sgd_dmamap) if (sc->sgd_addr) {
bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap); bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap);
sc->sgd_addr = 0;
}
if (sc->sgd_table) { if (sc->sgd_table) {
bus_dmamem_free(sc->sgd_dmat, sc->sgd_table, sc->sgd_dmamap); bus_dmamem_free(sc->sgd_dmat, sc->sgd_table, sc->sgd_dmamap);
sc->sgd_table = NULL; sc->sgd_table = NULL;
} }
sc->sgd_dmamap = NULL;
if (sc->sgd_dmat) { if (sc->sgd_dmat) {
bus_dma_tag_destroy(sc->sgd_dmat); bus_dma_tag_destroy(sc->sgd_dmat);
sc->sgd_dmat = NULL; sc->sgd_dmat = NULL;

View File

@ -160,6 +160,7 @@ struct emu_memblk {
void *buf; void *buf;
bus_addr_t buf_addr; bus_addr_t buf_addr;
u_int32_t pte_start, pte_size; u_int32_t pte_start, pte_size;
bus_dmamap_t buf_map;
}; };
struct emu_mem { struct emu_mem {
@ -168,6 +169,8 @@ struct emu_mem {
void *silent_page; void *silent_page;
bus_addr_t silent_page_addr; bus_addr_t silent_page_addr;
bus_addr_t ptb_pages_addr; bus_addr_t ptb_pages_addr;
bus_dmamap_t ptb_map;
bus_dmamap_t silent_map;
SLIST_HEAD(, emu_memblk) blocks; SLIST_HEAD(, emu_memblk) blocks;
}; };
@ -239,7 +242,7 @@ struct sc_info {
/* stuff */ /* stuff */
static int emu_init(struct sc_info *); static int emu_init(struct sc_info *);
static void emu_intr(void *); static void emu_intr(void *);
static void *emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr); static void *emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr, bus_dmamap_t *map);
static void *emu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr); static void *emu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr);
static int emu_memfree(struct sc_info *sc, void *buf); static int emu_memfree(struct sc_info *sc, void *buf);
static int emu_memstart(struct sc_info *sc, void *buf); static int emu_memstart(struct sc_info *sc, void *buf);
@ -1315,24 +1318,27 @@ emu_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
} }
static void * static void *
emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr) emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr,
bus_dmamap_t *map)
{ {
void *buf; void *buf;
bus_dmamap_t map;
*addr = 0; *addr = 0;
if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, map))
return NULL; return NULL;
if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, emu_setmap, addr, 0) if (bus_dmamap_load(sc->parent_dmat, *map, buf, sz, emu_setmap, addr, 0)
|| !*addr) || !*addr) {
bus_dmamem_free(sc->parent_dmat, buf, *map);
return NULL; return NULL;
}
return buf; return buf;
} }
static void static void
emu_free(struct sc_info *sc, void *buf) emu_free(struct sc_info *sc, void *buf, bus_dmamap_t map)
{ {
bus_dmamem_free(sc->parent_dmat, buf, NULL); bus_dmamap_unload(sc->parent_dmat, map);
bus_dmamem_free(sc->parent_dmat, buf, map);
} }
static void * static void *
@ -1362,7 +1368,7 @@ emu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr)
blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT); blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT);
if (blk == NULL) if (blk == NULL)
return NULL; return NULL;
buf = emu_malloc(sc, sz, &blk->buf_addr); buf = emu_malloc(sc, sz, &blk->buf_addr, &blk->buf_map);
*addr = blk->buf_addr; *addr = blk->buf_addr;
if (buf == NULL) { if (buf == NULL) {
free(blk, M_DEVBUF); free(blk, M_DEVBUF);
@ -1405,7 +1411,7 @@ emu_memfree(struct sc_info *sc, void *buf)
if (blk == NULL) if (blk == NULL)
return EINVAL; return EINVAL;
SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
emu_free(sc, buf); emu_free(sc, buf, blk->buf_map);
tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1; tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1;
for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
@ -1882,14 +1888,14 @@ emu_init(struct sc_info *sc)
SLIST_INIT(&sc->mem.blocks); SLIST_INIT(&sc->mem.blocks);
sc->mem.ptb_pages = emu_malloc(sc, EMUMAXPAGES * sizeof(u_int32_t), sc->mem.ptb_pages = emu_malloc(sc, EMUMAXPAGES * sizeof(u_int32_t),
&sc->mem.ptb_pages_addr); &sc->mem.ptb_pages_addr, &sc->mem.ptb_map);
if (sc->mem.ptb_pages == NULL) if (sc->mem.ptb_pages == NULL)
return -1; return -1;
sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE, sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE,
&sc->mem.silent_page_addr); &sc->mem.silent_page_addr, &sc->mem.silent_map);
if (sc->mem.silent_page == NULL) { if (sc->mem.silent_page == NULL) {
emu_free(sc, sc->mem.ptb_pages); emu_free(sc, sc->mem.ptb_pages, sc->mem.ptb_map);
return -1; return -1;
} }
/* Clear page with silence & setup all pointers to this page */ /* Clear page with silence & setup all pointers to this page */
@ -2025,8 +2031,8 @@ emu_uninit(struct sc_info *sc)
/* init envelope engine */ /* init envelope engine */
if (!SLIST_EMPTY(&sc->mem.blocks)) if (!SLIST_EMPTY(&sc->mem.blocks))
device_printf(sc->dev, "warning: memblock list not empty\n"); device_printf(sc->dev, "warning: memblock list not empty\n");
emu_free(sc, sc->mem.ptb_pages); emu_free(sc, sc->mem.ptb_pages, sc->mem.ptb_map);
emu_free(sc, sc->mem.silent_page); emu_free(sc, sc->mem.silent_page, sc->mem.silent_map);
if(sc->mpu) if(sc->mpu)
mpu401_uninit(sc->mpu); mpu401_uninit(sc->mpu);

View File

@ -273,14 +273,17 @@ struct emu_memblk {
char owner[16]; char owner[16];
bus_addr_t buf_addr; bus_addr_t buf_addr;
uint32_t pte_start, pte_size; uint32_t pte_start, pte_size;
bus_dmamap_t buf_map;
}; };
struct emu_mem { struct emu_mem {
uint8_t bmap[EMU_MAXPAGES / 8]; uint8_t bmap[EMU_MAXPAGES / 8];
uint32_t *ptb_pages; uint32_t *ptb_pages;
void *silent_page; void *silent_page;
bus_addr_t silent_page_addr;
bus_addr_t ptb_pages_addr; bus_addr_t ptb_pages_addr;
bus_addr_t silent_page_addr;
bus_dmamap_t ptb_map;
bus_dmamap_t silent_map;
bus_dma_tag_t dmat; bus_dma_tag_t dmat;
struct emu_sc_info *card; struct emu_sc_info *card;
SLIST_HEAD(, emu_memblk) blocks; SLIST_HEAD(, emu_memblk) blocks;
@ -377,8 +380,8 @@ struct emu_sc_info {
}; };
static void emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error); static void emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error);
static void* emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr); static void* emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, bus_dmamap_t *map);
static void emu_free(struct emu_mem *mem, void *dmabuf); static void emu_free(struct emu_mem *mem, void *dmabuf, bus_dmamap_t map);
static void* emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner); static void* emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner);
static int emu_memfree(struct emu_mem *mem, void *membuf); static int emu_memfree(struct emu_mem *mem, void *membuf);
static int emu_memstart(struct emu_mem *mem, void *membuf); static int emu_memstart(struct emu_mem *mem, void *membuf);
@ -1057,30 +1060,32 @@ emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error)
} }
static void * static void *
emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr) emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr,
bus_dmamap_t *map)
{ {
void *dmabuf; void *dmabuf;
bus_dmamap_t map;
int error; int error;
*addr = 0; *addr = 0;
if ((error = bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, &map))) { if ((error = bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, map))) {
if (mem->card->dbg_level > 2) if (mem->card->dbg_level > 2)
device_printf(mem->card->dev, "emu_malloc: failed to alloc DMA map: %d\n", error); device_printf(mem->card->dev, "emu_malloc: failed to alloc DMA map: %d\n", error);
return (NULL); return (NULL);
} }
if ((error = bus_dmamap_load(mem->dmat, map, dmabuf, sz, emu_setmap, addr, 0)) || !*addr) { if ((error = bus_dmamap_load(mem->dmat, *map, dmabuf, sz, emu_setmap, addr, 0)) || !*addr) {
if (mem->card->dbg_level > 2) if (mem->card->dbg_level > 2)
device_printf(mem->card->dev, "emu_malloc: failed to load DMA memory: %d\n", error); device_printf(mem->card->dev, "emu_malloc: failed to load DMA memory: %d\n", error);
bus_dmamem_free(mem->dmat, dmabuf, *map);
return (NULL); return (NULL);
} }
return (dmabuf); return (dmabuf);
} }
static void static void
emu_free(struct emu_mem *mem, void *dmabuf) emu_free(struct emu_mem *mem, void *dmabuf, bus_dmamap_t map)
{ {
bus_dmamem_free(mem->dmat, dmabuf, NULL); bus_dmamap_unload(mem->dmat, map);
bus_dmamem_free(mem->dmat, dmabuf, map);
} }
static void * static void *
@ -1121,7 +1126,7 @@ emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char *ow
return (NULL); return (NULL);
} }
bzero(blk, sizeof(*blk)); bzero(blk, sizeof(*blk));
membuf = emu_malloc(mem, sz, &blk->buf_addr); membuf = emu_malloc(mem, sz, &blk->buf_addr, &blk->buf_map);
*addr = blk->buf_addr; *addr = blk->buf_addr;
if (membuf == NULL) { if (membuf == NULL) {
if (mem->card->dbg_level > 2) if (mem->card->dbg_level > 2)
@ -1159,7 +1164,7 @@ emu_memfree(struct emu_mem *mem, void *membuf)
if (blk == NULL) if (blk == NULL)
return (EINVAL); return (EINVAL);
SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link); SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
emu_free(mem, membuf); emu_free(mem, membuf, blk->buf_map);
tmp = (uint32_t) (mem->silent_page_addr) << 1; tmp = (uint32_t) (mem->silent_page_addr) << 1;
for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) { for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
mem->bmap[idx >> 3] &= ~(1 << (idx & 7)); mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
@ -2724,13 +2729,13 @@ emu_init(struct emu_sc_info *sc)
sc->mem.card = sc; sc->mem.card = sc;
SLIST_INIT(&sc->mem.blocks); SLIST_INIT(&sc->mem.blocks);
sc->mem.ptb_pages = emu_malloc(&sc->mem, EMU_MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr); sc->mem.ptb_pages = emu_malloc(&sc->mem, EMU_MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr, &sc->mem.ptb_map);
if (sc->mem.ptb_pages == NULL) if (sc->mem.ptb_pages == NULL)
return (ENOMEM); return (ENOMEM);
sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr); sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr, &sc->mem.silent_map);
if (sc->mem.silent_page == NULL) { if (sc->mem.silent_page == NULL) {
emu_free(&sc->mem, sc->mem.ptb_pages); emu_free(&sc->mem, sc->mem.ptb_pages, sc->mem.ptb_map);
return (ENOMEM); return (ENOMEM);
} }
/* Clear page with silence & setup all pointers to this page */ /* Clear page with silence & setup all pointers to this page */
@ -2946,8 +2951,8 @@ emu_uninit(struct emu_sc_info *sc)
if (blk != NULL) if (blk != NULL)
device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner); device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner);
emu_free(&sc->mem, sc->mem.ptb_pages); emu_free(&sc->mem, sc->mem.ptb_pages, sc->mem.ptb_map);
emu_free(&sc->mem, sc->mem.silent_page); emu_free(&sc->mem, sc->mem.silent_page, sc->mem.silent_map);
return (0); return (0);
} }

View File

@ -163,6 +163,7 @@ struct sc_info {
u_int32_t psize, rsize; /* DMA buffer size(byte) */ u_int32_t psize, rsize; /* DMA buffer size(byte) */
u_int16_t blk[2]; /* transfer check blocksize(dword) */ u_int16_t blk[2]; /* transfer check blocksize(dword) */
bus_dmamap_t pmap, rmap; bus_dmamap_t pmap, rmap;
bus_addr_t paddr, raddr;
/* current status */ /* current status */
u_int32_t speed; u_int32_t speed;
@ -2166,15 +2167,16 @@ envy24_pci_probe(device_t dev)
static void static void
envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{ {
/* struct sc_info *sc = (struct sc_info *)arg; */ struct sc_info *sc = (struct sc_info *)arg;
sc->paddr = segs->ds_addr;
#if(0) #if(0)
device_printf(sc->dev, "envy24_dmapsetmap()\n"); device_printf(sc->dev, "envy24_dmapsetmap()\n");
if (bootverbose) { if (bootverbose) {
printf("envy24(play): setmap %lx, %lx; ", printf("envy24(play): setmap %lx, %lx; ",
(unsigned long)segs->ds_addr, (unsigned long)segs->ds_addr,
(unsigned long)segs->ds_len); (unsigned long)segs->ds_len);
printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap)); printf("%p -> %lx\n", sc->pmap, sc->paddr);
} }
#endif #endif
} }
@ -2182,15 +2184,16 @@ envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
static void static void
envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{ {
/* struct sc_info *sc = (struct sc_info *)arg; */ struct sc_info *sc = (struct sc_info *)arg;
sc->raddr = segs->ds_addr;
#if(0) #if(0)
device_printf(sc->dev, "envy24_dmarsetmap()\n"); device_printf(sc->dev, "envy24_dmarsetmap()\n");
if (bootverbose) { if (bootverbose) {
printf("envy24(record): setmap %lx, %lx; ", printf("envy24(record): setmap %lx, %lx; ",
(unsigned long)segs->ds_addr, (unsigned long)segs->ds_addr,
(unsigned long)segs->ds_len); (unsigned long)segs->ds_len);
printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap)); printf("%p -> %lx\n", sc->rmap, sc->raddr);
} }
#endif #endif
} }
@ -2200,19 +2203,17 @@ envy24_dmafree(struct sc_info *sc)
{ {
#if(0) #if(0)
device_printf(sc->dev, "envy24_dmafree():"); device_printf(sc->dev, "envy24_dmafree():");
if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap); printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
else printf(" sc->rmap(null)"); printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
else printf(" sc->pmap(null)");
if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf); if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
else printf(" sc->rbuf(null)"); else printf(" sc->rbuf(null)");
if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf); if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
else printf(" sc->pbuf(null)\n"); else printf(" sc->pbuf(null)\n");
#endif #endif
#if(0) #if(0)
if (sc->rmap) if (sc->raddr)
bus_dmamap_unload(sc->dmat, sc->rmap); bus_dmamap_unload(sc->dmat, sc->rmap);
if (sc->pmap) if (sc->paddr)
bus_dmamap_unload(sc->dmat, sc->pmap); bus_dmamap_unload(sc->dmat, sc->pmap);
if (sc->rbuf) if (sc->rbuf)
bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
@ -2225,7 +2226,7 @@ envy24_dmafree(struct sc_info *sc)
bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
#endif #endif
sc->rmap = sc->pmap = NULL; sc->raddr = sc->paddr = 0;
sc->pbuf = NULL; sc->pbuf = NULL;
sc->rbuf = NULL; sc->rbuf = NULL;
@ -2235,7 +2236,6 @@ envy24_dmafree(struct sc_info *sc)
static int static int
envy24_dmainit(struct sc_info *sc) envy24_dmainit(struct sc_info *sc)
{ {
u_int32_t addr;
#if(0) #if(0)
device_printf(sc->dev, "envy24_dmainit()\n"); device_printf(sc->dev, "envy24_dmainit()\n");
@ -2245,7 +2245,7 @@ envy24_dmainit(struct sc_info *sc)
sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM; sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
sc->pbuf = NULL; sc->pbuf = NULL;
sc->rbuf = NULL; sc->rbuf = NULL;
sc->pmap = sc->rmap = NULL; sc->paddr = sc->raddr = 0;
sc->blk[0] = sc->blk[1] = 0; sc->blk[0] = sc->blk[1] = 0;
/* allocate DMA buffer */ /* allocate DMA buffer */
@ -2273,11 +2273,10 @@ envy24_dmainit(struct sc_info *sc)
bzero(sc->rbuf, sc->rsize); bzero(sc->rbuf, sc->rsize);
/* set values to register */ /* set values to register */
addr = vtophys(sc->pbuf);
#if(0) #if(0)
device_printf(sc->dev, "pbuf(0x%08x)\n", addr); device_printf(sc->dev, "paddr(0x%08x)\n", sc->paddr);
#endif #endif
envy24_wrmt(sc, ENVY24_MT_PADDR, addr, 4); envy24_wrmt(sc, ENVY24_MT_PADDR, sc->paddr, 4);
#if(0) #if(0)
device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4)); device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1); device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
@ -2286,8 +2285,7 @@ envy24_dmainit(struct sc_info *sc)
#if(0) #if(0)
device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2)); device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
#endif #endif
addr = vtophys(sc->rbuf); envy24_wrmt(sc, ENVY24_MT_RADDR, sc->raddr, 4);
envy24_wrmt(sc, ENVY24_MT_RADDR, addr, 4);
envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2); envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
return 0; return 0;

View File

@ -162,6 +162,7 @@ struct sc_info {
u_int32_t psize, rsize; /* DMA buffer size(byte) */ u_int32_t psize, rsize; /* DMA buffer size(byte) */
u_int16_t blk[2]; /* transfer check blocksize(dword) */ u_int16_t blk[2]; /* transfer check blocksize(dword) */
bus_dmamap_t pmap, rmap; bus_dmamap_t pmap, rmap;
bus_addr_t paddr, raddr;
/* current status */ /* current status */
u_int32_t speed; u_int32_t speed;
@ -2082,6 +2083,7 @@ envy24ht_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{ {
struct sc_info *sc = arg; struct sc_info *sc = arg;
sc->paddr = segs->ds_addr;
#if(0) #if(0)
device_printf(sc->dev, "envy24ht_dmapsetmap()\n"); device_printf(sc->dev, "envy24ht_dmapsetmap()\n");
if (bootverbose) { if (bootverbose) {
@ -2099,6 +2101,7 @@ envy24ht_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{ {
struct sc_info *sc = arg; struct sc_info *sc = arg;
sc->raddr = segs->ds_addr;
#if(0) #if(0)
device_printf(sc->dev, "envy24ht_dmarsetmap()\n"); device_printf(sc->dev, "envy24ht_dmarsetmap()\n");
if (bootverbose) { if (bootverbose) {
@ -2116,19 +2119,17 @@ envy24ht_dmafree(struct sc_info *sc)
{ {
#if(0) #if(0)
device_printf(sc->dev, "envy24ht_dmafree():"); device_printf(sc->dev, "envy24ht_dmafree():");
if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap); printf(" sc->raddr(0x%08x)", (u_int32_t)sc->raddr);
else printf(" sc->rmap(null)"); printf(" sc->paddr(0x%08x)", (u_int32_t)sc->paddr);
if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
else printf(" sc->pmap(null)");
if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf); if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
else printf(" sc->rbuf(null)"); else printf(" sc->rbuf(null)");
if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf); if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
else printf(" sc->pbuf(null)\n"); else printf(" sc->pbuf(null)\n");
#endif #endif
#if(0) #if(0)
if (sc->rmap) if (sc->raddr)
bus_dmamap_unload(sc->dmat, sc->rmap); bus_dmamap_unload(sc->dmat, sc->rmap);
if (sc->pmap) if (sc->paddr)
bus_dmamap_unload(sc->dmat, sc->pmap); bus_dmamap_unload(sc->dmat, sc->pmap);
if (sc->rbuf) if (sc->rbuf)
bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
@ -2141,7 +2142,7 @@ envy24ht_dmafree(struct sc_info *sc)
bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
#endif #endif
sc->rmap = sc->pmap = NULL; sc->raddr = sc->paddr = 0;
sc->pbuf = NULL; sc->pbuf = NULL;
sc->rbuf = NULL; sc->rbuf = NULL;
@ -2160,7 +2161,7 @@ envy24ht_dmainit(struct sc_info *sc)
sc->rsize = ENVY24HT_REC_BUFUNIT * ENVY24HT_SAMPLE_NUM; sc->rsize = ENVY24HT_REC_BUFUNIT * ENVY24HT_SAMPLE_NUM;
sc->pbuf = NULL; sc->pbuf = NULL;
sc->rbuf = NULL; sc->rbuf = NULL;
sc->pmap = sc->rmap = NULL; sc->paddr = sc->raddr = 0;
sc->blk[0] = sc->blk[1] = 0; sc->blk[0] = sc->blk[1] = 0;
/* allocate DMA buffer */ /* allocate DMA buffer */

View File

@ -611,19 +611,19 @@ hdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size)
static void static void
hdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma) hdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma)
{ {
if (dma->dma_map != NULL) { if (dma->dma_paddr != 0) {
#if 0 #if 0
/* Flush caches */ /* Flush caches */
bus_dmamap_sync(dma->dma_tag, dma->dma_map, bus_dmamap_sync(dma->dma_tag, dma->dma_map,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
#endif #endif
bus_dmamap_unload(dma->dma_tag, dma->dma_map); bus_dmamap_unload(dma->dma_tag, dma->dma_map);
dma->dma_paddr = 0;
} }
if (dma->dma_vaddr != NULL) { if (dma->dma_vaddr != NULL) {
bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
dma->dma_vaddr = NULL; dma->dma_vaddr = NULL;
} }
dma->dma_map = NULL;
if (dma->dma_tag != NULL) { if (dma->dma_tag != NULL) {
bus_dma_tag_destroy(dma->dma_tag); bus_dma_tag_destroy(dma->dma_tag);
dma->dma_tag = NULL; dma->dma_tag = NULL;

View File

@ -344,7 +344,6 @@ hdspe_dmafree(struct sc_info *sc)
bus_dmamap_unload(sc->dmat, sc->pmap); bus_dmamap_unload(sc->dmat, sc->pmap);
bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
sc->rmap = sc->pmap = NULL;
sc->rbuf = sc->pbuf = NULL; sc->rbuf = sc->pbuf = NULL;
} }

View File

@ -110,6 +110,7 @@ struct agg_chinfo {
struct snd_dbuf *buffer; struct snd_dbuf *buffer;
/* OS independent */ /* OS independent */
bus_dmamap_t map;
bus_addr_t phys; /* channel buffer physical address */ bus_addr_t phys; /* channel buffer physical address */
bus_addr_t base; /* channel buffer segment base */ bus_addr_t base; /* channel buffer segment base */
u_int32_t blklen; /* DMA block length in WORDs */ u_int32_t blklen; /* DMA block length in WORDs */
@ -130,6 +131,7 @@ struct agg_rchinfo {
struct snd_dbuf *buffer; struct snd_dbuf *buffer;
/* OS independent */ /* OS independent */
bus_dmamap_t map;
bus_addr_t phys; /* channel buffer physical address */ bus_addr_t phys; /* channel buffer physical address */
bus_addr_t base; /* channel buffer segment base */ bus_addr_t base; /* channel buffer segment base */
u_int32_t blklen; /* DMA block length in WORDs */ u_int32_t blklen; /* DMA block length in WORDs */
@ -166,6 +168,7 @@ struct agg_info {
struct ac97_info *codec; struct ac97_info *codec;
/* OS independent */ /* OS independent */
bus_dmamap_t stat_map;
u_int8_t *stat; /* status buffer pointer */ u_int8_t *stat; /* status buffer pointer */
bus_addr_t phys; /* status buffer physical address */ bus_addr_t phys; /* status buffer physical address */
unsigned int bufsz; /* channel buffer size in bytes */ unsigned int bufsz; /* channel buffer size in bytes */
@ -262,8 +265,9 @@ static int agg_suspend(device_t);
static int agg_resume(device_t); static int agg_resume(device_t);
static int agg_shutdown(device_t); static int agg_shutdown(device_t);
static void *dma_malloc(bus_dma_tag_t, u_int32_t, bus_addr_t*); static void *dma_malloc(bus_dma_tag_t, u_int32_t, bus_addr_t*,
static void dma_free(bus_dma_tag_t, void *); bus_dmamap_t *);
static void dma_free(bus_dma_tag_t, void *, bus_dmamap_t);
/* ----------------------------- /* -----------------------------
@ -1297,7 +1301,7 @@ aggpch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
ch->buffer = b; ch->buffer = b;
ch->num = ess->playchns; ch->num = ess->playchns;
p = dma_malloc(ess->buf_dmat, ess->bufsz, &physaddr); p = dma_malloc(ess->buf_dmat, ess->bufsz, &physaddr, &ch->map);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
ch->phys = physaddr; ch->phys = physaddr;
@ -1360,7 +1364,7 @@ aggpch_free(kobj_t obj, void *data)
struct agg_info *ess = ch->parent; struct agg_info *ess = ch->parent;
/* free up buffer - called after channel stopped */ /* free up buffer - called after channel stopped */
dma_free(ess->buf_dmat, sndbuf_getbuf(ch->buffer)); dma_free(ess->buf_dmat, sndbuf_getbuf(ch->buffer), ch->map);
/* return 0 if ok */ /* return 0 if ok */
return 0; return 0;
@ -1722,25 +1726,26 @@ setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
} }
static void * static void *
dma_malloc(bus_dma_tag_t dmat, u_int32_t sz, bus_addr_t *phys) dma_malloc(bus_dma_tag_t dmat, u_int32_t sz, bus_addr_t *phys,
bus_dmamap_t *map)
{ {
void *buf; void *buf;
bus_dmamap_t map;
if (bus_dmamem_alloc(dmat, &buf, BUS_DMA_NOWAIT, &map)) if (bus_dmamem_alloc(dmat, &buf, BUS_DMA_NOWAIT, map))
return NULL; return NULL;
if (bus_dmamap_load(dmat, map, buf, sz, setmap, phys, 0) if (bus_dmamap_load(dmat, *map, buf, sz, setmap, phys, 0) != 0 ||
|| !*phys || map) { *phys == 0) {
bus_dmamem_free(dmat, buf, map); bus_dmamem_free(dmat, buf, *map);
return NULL; return NULL;
} }
return buf; return buf;
} }
static void static void
dma_free(bus_dma_tag_t dmat, void *buf) dma_free(bus_dma_tag_t dmat, void *buf, bus_dmamap_t map)
{ {
bus_dmamem_free(dmat, buf, NULL); bus_dmamap_unload(dmat, map);
bus_dmamem_free(dmat, buf, map);
} }
static int static int
@ -1836,7 +1841,8 @@ agg_attach(device_t dev)
} }
/* Allocate the room for brain-damaging status buffer. */ /* Allocate the room for brain-damaging status buffer. */
ess->stat = dma_malloc(ess->stat_dmat, 3*ess->bufsz, &ess->phys); ess->stat = dma_malloc(ess->stat_dmat, 3*ess->bufsz, &ess->phys,
&ess->stat_map);
if (ess->stat == NULL) { if (ess->stat == NULL) {
device_printf(dev, "cannot allocate status buffer\n"); device_printf(dev, "cannot allocate status buffer\n");
ret = ENOMEM; ret = ENOMEM;
@ -1939,7 +1945,7 @@ agg_attach(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, regid, reg); bus_release_resource(dev, SYS_RES_IOPORT, regid, reg);
if (ess != NULL) { if (ess != NULL) {
if (ess->stat != NULL) if (ess->stat != NULL)
dma_free(ess->stat_dmat, ess->stat); dma_free(ess->stat_dmat, ess->stat, ess->stat_map);
if (ess->stat_dmat != NULL) if (ess->stat_dmat != NULL)
bus_dma_tag_destroy(ess->stat_dmat); bus_dma_tag_destroy(ess->stat_dmat);
if (ess->buf_dmat != NULL) if (ess->buf_dmat != NULL)
@ -1983,7 +1989,7 @@ agg_detach(device_t dev)
bus_teardown_intr(dev, ess->irq, ess->ih); bus_teardown_intr(dev, ess->irq, ess->ih);
bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq); bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq);
bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg); bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg);
dma_free(ess->stat_dmat, ess->stat); dma_free(ess->stat_dmat, ess->stat, ess->stat_map);
bus_dma_tag_destroy(ess->stat_dmat); bus_dma_tag_destroy(ess->stat_dmat);
bus_dma_tag_destroy(ess->buf_dmat); bus_dma_tag_destroy(ess->buf_dmat);
mtx_destroy(&ess->lock); mtx_destroy(&ess->lock);

View File

@ -1381,7 +1381,7 @@ via_attach(device_t dev)
bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
if (via->parent_dmat) if (via->parent_dmat)
bus_dma_tag_destroy(via->parent_dmat); bus_dma_tag_destroy(via->parent_dmat);
if (via->sgd_dmamap) if (via->sgd_addr)
bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
if (via->sgd_table) if (via->sgd_table)
bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);

View File

@ -606,7 +606,7 @@ via_attach(device_t dev)
if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); if (via->sgd_addr) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
if (via->lock) snd_mtxfree(via->lock); if (via->lock) snd_mtxfree(via->lock);

View File

@ -139,10 +139,9 @@ sndbuf_free(struct snd_dbuf *b)
if (b->buf) { if (b->buf) {
if (b->flags & SNDBUF_F_MANAGED) { if (b->flags & SNDBUF_F_MANAGED) {
if (b->dmamap) if (b->buf_addr)
bus_dmamap_unload(b->dmatag, b->dmamap); bus_dmamap_unload(b->dmatag, b->dmamap);
if (b->dmatag) bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
} else } else
free(b->buf, M_DEVBUF); free(b->buf, M_DEVBUF);
} }