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