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