Skip to content

Commit

Permalink
Free the segment objects properly.
Browse files Browse the repository at this point in the history
  • Loading branch information
marcel authored and marcel committed Jun 12, 2015
1 parent 484f91b commit 71bc1e1
Showing 1 changed file with 48 additions and 12 deletions.
60 changes: 48 additions & 12 deletions tools/bus_space/busdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,51 +273,87 @@ bd_mem_alloc(int tid, u_int flags)
tag->refcnt++;
md->key = ioc.result;

/* XXX we need to support multiple segments */
assert(ioc.u.mem.phys_nsegs == 1);
pseg = obj_alloc(OBJ_TYPE_SEG);
pseg->refcnt = 1;
pseg->parent = md;
pseg->u.seg.address = ioc.u.mem.phys_addr;
pseg->u.seg.size = tag->u.tag.maxsz;
md->u.md.seg[BUSDMA_MD_PHYS] = pseg;
md->u.md.nsegs[BUSDMA_MD_PHYS] = ioc.u.mem.phys_nsegs;

assert(ioc.u.mem.bus_nsegs == 1);

bseg = pseg = vseg = NULL;

bseg = obj_alloc(OBJ_TYPE_SEG);
if (bseg == NULL)
goto fail;
bseg->refcnt = 1;
bseg->parent = md;
bseg->u.seg.address = ioc.u.mem.bus_addr;
bseg->u.seg.size = tag->u.tag.maxsz;
md->u.md.seg[BUSDMA_MD_BUS] = bseg;
md->u.md.nsegs[BUSDMA_MD_BUS] = ioc.u.mem.bus_nsegs;

pseg = obj_alloc(OBJ_TYPE_SEG);
if (pseg == NULL)
goto fail;
pseg->refcnt = 1;
pseg->parent = md;
pseg->u.seg.address = ioc.u.mem.phys_addr;
pseg->u.seg.size = tag->u.tag.maxsz;
md->u.md.seg[BUSDMA_MD_PHYS] = pseg;
md->u.md.nsegs[BUSDMA_MD_PHYS] = ioc.u.mem.phys_nsegs;

vseg = obj_alloc(OBJ_TYPE_SEG);
if (vseg == NULL)
goto fail;
vseg->refcnt = 1;
vseg->parent = md;
vseg->u.seg.address = (uintptr_t)mmap(NULL, pseg->u.seg.size,
PROT_READ | PROT_WRITE, MAP_NOCORE | MAP_SHARED, md->fd,
pseg->u.seg.address);
if (vseg->u.seg.address == (uintptr_t)MAP_FAILED)
goto fail;
vseg->u.seg.size = pseg->u.seg.size;
md->u.md.seg[BUSDMA_MD_VIRT] = vseg;
md->u.md.nsegs[BUSDMA_MD_VIRT] = 1;

return (md->oid);

fail:
if (vseg != NULL)
obj_free(vseg);
if (pseg != NULL)
obj_free(pseg);
if (bseg != NULL)
obj_free(bseg);
memset(&ioc, 0, sizeof(ioc));
ioc.request = PROTO_IOC_BUSDMA_MEM_FREE;
ioc.key = md->key;
ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc);
md->parent->refcnt--;
obj_free(md);
return (-1);
}

int
bd_mem_free(int mdid)
{
struct proto_ioc_busdma ioc;
struct obj *md, *seg;
struct obj *md, *seg, *seg0;

md = obj_lookup(mdid, OBJ_TYPE_MD);
if (md == NULL)
return (errno);

for (seg = md->u.md.seg[BUSDMA_MD_VIRT];
seg != NULL;
seg = seg->u.seg.next)
for (seg = md->u.md.seg[BUSDMA_MD_VIRT]; seg != NULL; seg = seg0) {
munmap((void *)seg->u.seg.address, seg->u.seg.size);
seg0 = seg->u.seg.next;
obj_free(seg);
}
for (seg = md->u.md.seg[BUSDMA_MD_PHYS]; seg != NULL; seg = seg0) {
seg0 = seg->u.seg.next;
obj_free(seg);
}
for (seg = md->u.md.seg[BUSDMA_MD_BUS]; seg != NULL; seg = seg0) {
seg0 = seg->u.seg.next;
obj_free(seg);
}
memset(&ioc, 0, sizeof(ioc));
ioc.request = PROTO_IOC_BUSDMA_MEM_FREE;
ioc.key = md->key;
Expand Down

0 comments on commit 71bc1e1

Please sign in to comment.