Date: Sun, 17 Nov 2013 03:11:37 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r258249 - projects/altix2/sys/sparc64/sparc64 Message-ID: <201311170311.rAH3BbCw096779@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Sun Nov 17 03:11:36 2013 New Revision: 258249 URL: http://svnweb.freebsd.org/changeset/base/258249 Log: Finish the first rough implementation. This seems to work fairly well. I can now do some basic performance comparisons to see how much overhead the busdma/mi approach has. Modified: projects/altix2/sys/sparc64/sparc64/iommu.c Modified: projects/altix2/sys/sparc64/sparc64/iommu.c ============================================================================== --- projects/altix2/sys/sparc64/sparc64/iommu.c Sun Nov 17 03:08:17 2013 (r258248) +++ projects/altix2/sys/sparc64/sparc64/iommu.c Sun Nov 17 03:11:36 2013 (r258249) @@ -1180,33 +1180,124 @@ iommu_xlate(device_t bus __unused, devic } int -iommu_map(device_t bus __unused, device_t dev __unused, - busdma_md_t md __unused, u_int idx __unused, bus_addr_t *ba_p __unused) +iommu_map(device_t bus, device_t dev __unused, busdma_md_t md, u_int idx, + bus_addr_t *ba_p) { + struct iommu_state *is, **isp; + struct resource *r; + busdma_tag_t tag; + bus_addr_t ba; + u_long align, bndry, maxaddr, size, start; + u_int flags, stream; + + isp = device_get_softc(bus); + is = *isp; + + ba = *ba_p; - return (ENOSYS); + tag = busdma_md_get_tag(md); + align = (busdma_tag_get_align(tag) + IO_PAGE_MASK) >> IO_PAGE_SHIFT; + bndry = busdma_tag_get_bndry(tag) >> IO_PAGE_SHIFT; + maxaddr = busdma_tag_get_maxaddr(tag) >> IO_PAGE_SHIFT; + size = busdma_md_get_size(md, idx) + (ba & IO_PAGE_MASK); + size = round_io_page(size) >> IO_PAGE_SHIFT; + + r = rman_reserve_resource_bound(&is->is_dvma_rman, 0L, maxaddr, size, + bndry, RF_ACTIVE | rman_make_alignment_flags(align), NULL); + if (r == NULL) + return (ENOMEM); + + size = rman_get_size(r); + start = rman_get_start(r) << IO_PAGE_SHIFT; + + *ba_p = start | (ba & IO_PAGE_MASK); + ba &= ~IO_PAGE_MASK; + busdma_md_set_iommu(md, idx, (uintptr_t)(void *)r); + + flags = busdma_md_get_flags(md); + stream = size >= IOMMU_STREAM_THRESH && IOMMU_HAS_SB(is) && + (flags & BUSDMA_ALLOC_COHERENT) == 0; + while (size > 0) { + iommu_enter(is, start, ba, stream, 0); + start += IO_PAGE_SIZE; + ba += IO_PAGE_SIZE; + size--; + } + return (0); } int -iommu_unmap(device_t bus __unused, device_t dev __unused, - busdma_md_t md __unused, u_int idx __unused) +iommu_unmap(device_t bus, device_t dev __unused, busdma_md_t md, u_int idx) { + struct iommu_state *is, **isp; + struct resource *r; + u_int sync; - return (ENOSYS); + isp = device_get_softc(bus); + is = *isp; + + IS_LOCK(is); + r = (void *)busdma_md_get_iommu(md, idx); + sync = iommu_remove(is, rman_get_start(r) << IO_PAGE_SHIFT, + rman_get_size(r) << IO_PAGE_SHIFT); + if (sync) + iommu_strbuf_sync(is); + rman_release_resource(r); + IS_UNLOCK(is); + return (0); } int -iommu_sync(device_t bus, device_t dev __unused, - busdma_md_t md __unused, u_int op __unused, bus_addr_t addr __unused, - bus_size_t size __unused) +iommu_sync(device_t bus, device_t dev __unused, busdma_md_t md, u_int op, + bus_addr_t addr, bus_size_t size) { struct iommu_state *is, **isp; + struct resource *r; + bus_addr_t ba; + bus_size_t sz; + u_long va; + u_int flags, idx, nsegs, sync; + + if ((op & BUSDMA_SYNC_PREWRITE) != BUSDMA_SYNC_PREWRITE && + (op & BUSDMA_SYNC_POSTREAD) != BUSDMA_SYNC_POSTREAD) + return (0); + + if ((op & BUSDMA_SYNC_PREWRITE) == BUSDMA_SYNC_PREWRITE) + membar(Sync); + + flags = busdma_md_get_flags(md); + if ((flags & BUSDMA_ALLOC_COHERENT) != 0) + return (0); isp = device_get_softc(bus); is = *isp; - if ((op & BUSDMA_SYNC_PREWRITE) == BUSDMA_SYNC_PREWRITE) - membar(Sync); + nsegs = busdma_md_get_nsegs(md); + for (idx = 0; idx < nsegs; idx++) { + ba = busdma_md_get_busaddr(md, idx); + sz = busdma_md_get_size(md, idx); + if (ba + sz <= addr || addr + size <= ba) + continue; + r = (void *)busdma_md_get_iommu(md, idx); + if (r == NULL) + continue; + + sz = rman_get_size(r); + va = rman_get_start(r) << IO_PAGE_SHIFT; + sync = 0; + IS_LOCK(is); + while (sz > 0) { + if ((IOMMU_GET_TTE(is, va) & IOTTE_STREAM) != 0) { + sync++; + iommu_strbuf_flush(is, va); + } + va += IO_PAGE_SIZE; + sz--; + } + if (sync) + iommu_strbuf_sync(is); + IS_UNLOCK(is); + } return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311170311.rAH3BbCw096779>