svn commit: r284322 - head/tools/bus_space
Marcel Moolenaar
marcel at FreeBSD.org
Fri Jun 12 14:53:57 UTC 2015
Author: marcel
Date: Fri Jun 12 14:53:56 2015
New Revision: 284322
URL: https://svnweb.freebsd.org/changeset/base/284322
Log:
Free the segment objects properly.
Modified:
head/tools/bus_space/busdma.c
Modified: head/tools/bus_space/busdma.c
==============================================================================
--- head/tools/bus_space/busdma.c Fri Jun 12 14:30:27 2015 (r284321)
+++ head/tools/bus_space/busdma.c Fri Jun 12 14:53:56 2015 (r284322)
@@ -273,17 +273,15 @@ 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;
@@ -291,33 +289,71 @@ bd_mem_alloc(int tid, u_int flags)
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;
More information about the svn-src-all
mailing list