Date: Mon, 4 Jun 2012 18:45:18 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r236576 - projects/altix2/sys/kern Message-ID: <201206041845.q54IjI1S058985@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206041845.q54IjI1S058985>