Skip site navigation (1)Skip section navigation (2)
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>