From owner-svn-src-projects@FreeBSD.ORG Sun Nov 17 03:11:37 2013 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 63F5DD76; Sun, 17 Nov 2013 03:11:37 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 549632437; Sun, 17 Nov 2013 03:11:37 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rAH3BbGr096780; Sun, 17 Nov 2013 03:11:37 GMT (envelope-from marcel@svn.freebsd.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rAH3BbCw096779; Sun, 17 Nov 2013 03:11:37 GMT (envelope-from marcel@svn.freebsd.org) Message-Id: <201311170311.rAH3BbCw096779@svn.freebsd.org> From: Marcel Moolenaar Date: Sun, 17 Nov 2013 03:11:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r258249 - projects/altix2/sys/sparc64/sparc64 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Nov 2013 03:11:37 -0000 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); }