svn commit: r236576 - projects/altix2/sys/kern

Marcel Moolenaar marcel at FreeBSD.org
Mon Jun 4 18:45:18 UTC 2012


Author: marcel
Date: Mon Jun  4 18:45:18 2012
New Revision: 236576
URL: http://svn.freebsd.org/changeset/base/236576

Log:
  Implement BUSDMA_IOMMU_MAP. We want to map starting with the root and
  ending with the leaf. In other words, we want to map top-down (root to
  leaf) and not bottom-up (learfd to root).  Given that we have a fairly
  shallow device tree, use recursion to walk up to the root first and
  then call the BUSDMA_IOMMU_MAP on the device on the way back down (i.e.
  while unwinding from the recursion.  At the root, bus addresses are
  the same as CPU (physical addresses), so we assign the CPU address to
  the bus address.

Modified:
  projects/altix2/sys/kern/busdma_if.m
  projects/altix2/sys/kern/subr_busdma.c

Modified: projects/altix2/sys/kern/busdma_if.m
==============================================================================
--- projects/altix2/sys/kern/busdma_if.m	Mon Jun  4 18:43:51 2012	(r236575)
+++ projects/altix2/sys/kern/busdma_if.m	Mon Jun  4 18:45:18 2012	(r236576)
@@ -38,6 +38,12 @@ CODE {
 	{
 		return (0);
 	}
+
+	static int
+	default_iommu_map_unmap(device_t dev, busdma_md_t md)
+	{
+		return (0);
+	}
 };
 
 METHOD int iommu_xlate {
@@ -48,9 +54,9 @@ METHOD int iommu_xlate {
 METHOD int iommu_map {
 	device_t	dev;
 	busdma_md_t	md;
-};
+} DEFAULT default_iommu_map_unmap;
 
 METHOD int iommu_unmap {
 	device_t	dev;
 	busdma_md_t	md;
-};
+} DEFAULT default_iommu_map_unmap;

Modified: projects/altix2/sys/kern/subr_busdma.c
==============================================================================
--- projects/altix2/sys/kern/subr_busdma.c	Mon Jun  4 18:43:51 2012	(r236575)
+++ projects/altix2/sys/kern/subr_busdma.c	Mon Jun  4 18:45:18 2012	(r236576)
@@ -131,15 +131,17 @@ _busdma_tag_dump(const char *func, devic
 }
 
 static void
-_busdma_md_dump(const char *func, struct busdma_md *md) 
+_busdma_md_dump(const char *func, device_t dev, struct busdma_md *md) 
 {
 	struct busdma_tag *tag;
 	struct busdma_md_seg *seg;
 	int idx;
 
 	tag = md->md_tag;
+	if (dev == NULL)
+		dev = tag->dt_device;
 	printf("[%s: %s: md=%p (tag=%p, flags=%x, nsegs=%u)", func,
-	    device_get_nameunit(tag->dt_device), md, tag, md->md_flags,
+	    device_get_nameunit(dev), md, tag, md->md_flags,
 	    md->md_nsegs);
 	if (md->md_nsegs == 0) {
 		printf(" -- UNUSED]\n");
@@ -221,12 +223,14 @@ _busdma_md_create(struct busdma_tag *tag
 }
 
 static int
-_busdma_iommu_xlate(device_t dev, struct busdma_mtag *mtag)
+_busdma_iommu_xlate(device_t leaf, struct busdma_mtag *mtag)
 {
+	device_t dev;
 	int error;
 
 	error = 0;
-	while (!error && dev != NULL) {
+	dev = device_get_parent(leaf);
+	while (!error && dev != root_bus) {
 		_busdma_mtag_dump(__func__, dev, mtag);
 		error = BUSDMA_IOMMU_XLATE(dev, mtag);
 		if (!error)
@@ -236,6 +240,44 @@ _busdma_iommu_xlate(device_t dev, struct
 	return (error);
 }
 
+static int
+_busdma_iommu_map_r(device_t dev, struct busdma_md *md)
+{
+	struct busdma_md_seg *seg;
+	u_int idx;
+	int error;
+
+	if (dev == root_bus) {
+		/*
+		 * A bus address and a physical address are one and the same
+		 * at this level.
+		 */
+		for (idx = 0; idx < md->md_nsegs; idx++) {
+			seg = &md->md_seg[idx];
+			seg->mds_busaddr = seg->mds_paddr;
+		}
+		_busdma_md_dump(__func__, dev, md);
+		return (0);
+	}
+
+	error = _busdma_iommu_map_r(device_get_parent(dev), md);
+	if (!error) {
+		error = BUSDMA_IOMMU_MAP(dev, md);
+		_busdma_md_dump(__func__, dev, md);
+	}
+	return (error);
+}
+
+static int
+_busdma_iommu_map(device_t leaf, struct busdma_md *md)
+{
+	int error;
+ 
+	_busdma_md_dump(__func__, leaf, md);
+	error = _busdma_iommu_map_r(device_get_parent(leaf), md);
+	return (error);
+}
+
 int
 busdma_tag_create(device_t dev, bus_addr_t align, bus_addr_t bndry,
     bus_addr_t maxaddr, bus_size_t maxsz, u_int nsegs, bus_size_t maxsegsz,
@@ -298,7 +340,7 @@ busdma_md_create(struct busdma_tag *tag,
 	if (md == NULL)
 		return (ENOMEM);
 
-	_busdma_md_dump(__func__, md);
+	_busdma_md_dump(__func__, NULL, md);
 	*md_p = md;
 	return (0);
 }
@@ -442,16 +484,14 @@ busdma_mem_alloc(struct busdma_tag *tag,
 			goto fail;
 		}
 		seg->mds_paddr = pmap_kextract(seg->mds_vaddr);
-		seg->mds_busaddr = seg->mds_paddr;
 		maxsz -= seg->mds_size;
 		idx++;
 	}
 	if (maxsz == 0) {
 		md->md_nsegs = idx;
-		error = BUSDMA_IOMMU_MAP(tag->dt_device, md);
+		error = _busdma_iommu_map(tag->dt_device, md);
 		if (error)
-			printf("BUSDMA_IOMMU_MAP: error=%d\n", error);
-		_busdma_md_dump(__func__, md);
+			printf("_busdma_iommu_map: error=%d\n", error);
 		*md_p = md;
 		return (0);
 	}


More information about the svn-src-projects mailing list