Module Name:    src
Committed By:   riastradh
Date:           Mon Aug 27 07:36:37 UTC 2018

Modified Files:
        src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem:
            nouveau_nvkm_subdev_instmem_gk20a.c

Log Message:
Rewrite DMA/IOMMU stuff using bus_dma for gk20a.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 \
    
src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_gk20a.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_gk20a.c
diff -u src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_gk20a.c:1.3 src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_gk20a.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_gk20a.c:1.3	Mon Aug 27 07:36:28 2018
+++ src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/subdev/instmem/nouveau_nvkm_subdev_instmem_gk20a.c	Mon Aug 27 07:36:37 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: nouveau_nvkm_subdev_instmem_gk20a.c,v 1.3 2018/08/27 07:36:28 riastradh Exp $	*/
+/*	$NetBSD: nouveau_nvkm_subdev_instmem_gk20a.c,v 1.4 2018/08/27 07:36:37 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
@@ -44,7 +44,7 @@
  * goes beyond a certain threshold. At the moment this limit is 1MB.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_instmem_gk20a.c,v 1.3 2018/08/27 07:36:28 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_instmem_gk20a.c,v 1.4 2018/08/27 07:36:37 riastradh Exp $");
 
 #include "priv.h"
 
@@ -69,6 +69,20 @@ struct gk20a_instobj {
 };
 #define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
 
+#ifdef __NetBSD__
+
+struct gk20a_instobj_netbsd {
+	struct gk20a_instobj base;
+
+	bus_dma_segment_t *segs;
+	int nsegs;
+	bus_dmamap_t map;
+};
+#define	gk20a_instobj_netbsd(p) \
+	container_of(gk20a_instobj(p), struct gk20a_instobj_netbsd, base)
+
+#else
+
 /*
  * Used for objects allocated using the DMA API
  */
@@ -96,6 +110,8 @@ struct gk20a_instobj_iommu {
 #define gk20a_instobj_iommu(p) \
 	container_of(gk20a_instobj(p), struct gk20a_instobj_iommu, base)
 
+#endif	/* __NetBSD__ */
+
 struct gk20a_instmem {
 	struct nvkm_instmem base;
 
@@ -107,6 +123,7 @@ struct gk20a_instmem {
 	unsigned int vaddr_max;
 	struct list_head vaddr_lru;
 
+#ifndef __NetBSD__
 	/* Only used if IOMMU if present */
 	struct mutex *mm_mutex;
 	struct nvkm_mm *mm;
@@ -116,6 +133,7 @@ struct gk20a_instmem {
 
 	/* Only used by DMA API */
 	struct dma_attrs attrs;
+#endif
 
 	void __iomem * (*cpu_map)(struct nvkm_memory *);
 };
@@ -139,6 +157,39 @@ gk20a_instobj_size(struct nvkm_memory *m
 	return (u64)gk20a_instobj(memory)->mem.size << 12;
 }
 
+#ifdef __NetBSD__
+
+static void __iomem *
+gk20a_instobj_cpu_map_netbsd(struct nvkm_memory *memory)
+{
+	struct gk20a_instobj_netbsd *node = gk20a_instobj_netbsd(memory);
+	struct nvkm_device *device = node->base.imem->base.subdev.device;
+	bus_dma_tag_t dmat = device->func->dma_tag(device);
+	uint64_t nbytes = nvkm_memory_size(memory);
+	void *kva;
+	int ret;
+
+	/* XXX errno NetBSD->Linux */
+	ret = -bus_dmamem_map(dmat, node->segs, node->nsegs, nbytes, &kva,
+	    BUS_DMA_WAITOK);
+	if (ret)
+		return NULL;
+
+	return kva;
+}
+
+static void
+gk20a_instobj_cpu_unmap_netbsd(struct nvkm_memory *memory, void *kva)
+{
+	struct gk20a_instobj_netbsd *node = gk20a_instobj_netbsd(memory);
+	struct nvkm_device *device = node->base.imem->base.subdev.device;
+	bus_dma_tag_t dmat = device->func->dma_tag(device);
+
+	bus_dmamem_unmap(dmat, kva, nvkm_memory_size(memory));
+}
+
+#else
+
 static void __iomem *
 gk20a_instobj_cpu_map_dma(struct nvkm_memory *memory)
 {
@@ -172,6 +223,8 @@ gk20a_instobj_cpu_map_iommu(struct nvkm_
 		    pgprot_writecombine(PAGE_KERNEL));
 }
 
+#endif	/* __NetBSD__ */
+
 /*
  * Must be called while holding gk20a_instmem_lock
  */
@@ -188,7 +241,11 @@ gk20a_instmem_vaddr_gc(struct gk20a_inst
 		obj = list_first_entry(&imem->vaddr_lru, struct gk20a_instobj,
 				       vaddr_node);
 		list_del(&obj->vaddr_node);
+#ifdef __NetBSD__
+		gk20a_instobj_cpu_unmap_netbsd(&obj->memory, obj->vaddr);
+#else
 		vunmap(obj->vaddr);
+#endif
 		obj->vaddr = NULL;
 		imem->vaddr_use -= nvkm_memory_size(&obj->memory);
 		nvkm_debug(&imem->base.subdev, "(GC) vaddr used: %x/%x\n",
@@ -302,7 +359,11 @@ gk20a_instobj_dtor(struct gk20a_instobj 
 			break;
 		}
 	}
+#ifdef __NetBSD__
+	gk20a_instobj_cpu_unmap_netbsd(&node->memory, node->vaddr);
+#else
 	vunmap(node->vaddr);
+#endif
 	node->vaddr = NULL;
 	imem->vaddr_use -= nvkm_memory_size(&node->memory);
 	nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n",
@@ -312,6 +373,31 @@ out:
 	spin_unlock_irqrestore(&imem->lock, flags);
 }
 
+#ifdef __NetBSD__
+
+static void *
+gk20a_instobj_dtor_netbsd(struct nvkm_memory *memory)
+{
+	struct gk20a_instobj_netbsd *node = gk20a_instobj_netbsd(memory);
+	struct gk20a_instmem *imem = node->base.imem;
+	struct nvkm_device *device = imem->base.subdev.device;
+	bus_dma_tag_t dmat = device->func->dma_tag(device);
+
+	gk20a_instobj_dtor(&node->base);
+
+	if (unlikely(!node->map))
+		goto out;
+
+	bus_dmamap_unload(dmat, node->map);
+	bus_dmamap_destroy(dmat, node->map);
+	bus_dmamem_free(dmat, node->segs, nvkm_memory_size(memory));
+
+out:
+	return node;
+}
+
+#else
+
 static void *
 gk20a_instobj_dtor_dma(struct nvkm_memory *memory)
 {
@@ -369,6 +455,25 @@ out:
 	return node;
 }
 
+#endif	/* __NetBSD__ */
+
+#ifdef __NetBSD__
+
+static const struct nvkm_memory_func
+gk20a_instobj_func_netbsd = {
+	.dtor = gk20a_instobj_dtor_netbsd,
+	.target = gk20a_instobj_target,
+	.addr = gk20a_instobj_addr,
+	.size = gk20a_instobj_size,
+	.acquire = gk20a_instobj_acquire,
+	.release = gk20a_instobj_release,
+	.rd32 = gk20a_instobj_rd32,
+	.wr32 = gk20a_instobj_wr32,
+	.map = gk20a_instobj_map,
+};
+
+#else
+
 static const struct nvkm_memory_func
 gk20a_instobj_func_dma = {
 	.dtor = gk20a_instobj_dtor_dma,
@@ -395,6 +500,71 @@ gk20a_instobj_func_iommu = {
 	.map = gk20a_instobj_map,
 };
 
+#endif
+
+#ifdef __NetBSD__
+
+static int
+gk20a_instobj_ctor_netbsd(struct gk20a_instmem *imem, u32 pages, u32 align,
+			  struct gk20a_instobj **_node)
+{
+	struct gk20a_instobj_netbsd *node;
+	struct nvkm_subdev *subdev = &imem->base.subdev;
+	struct nvkm_device *device = subdev->device;
+	bus_dma_tag_t dmat = device->func->dma_tag(device);
+	bus_size_t nbytes = (bus_size_t)pages << PAGE_SHIFT;
+	int ret;
+
+	if (!(node = kzalloc(sizeof(*node), GFP_KERNEL))) {
+		ret = -ENOMEM;
+fail0:		return ret;
+	}
+	*_node = &node->base;
+
+	nvkm_memory_ctor(&gk20a_instobj_func_netbsd, &node->base.memory);
+
+	node->segs = kcalloc(pages, sizeof(node->segs[0]), GFP_KERNEL);
+	if (node->segs == NULL) {
+		ret = -ENOMEM;
+		goto fail0;
+	}
+
+	ret = -bus_dmamem_alloc(dmat, nbytes, align, 0, node->segs, pages,
+	    &node->nsegs, BUS_DMA_WAITOK);
+	if (ret) {
+		kfree(node->segs);
+		node->segs = NULL;
+fail1:		goto fail0;
+	}
+	KASSERT(0 <= node->nsegs);
+	KASSERT(node->nsegs <= pages);
+
+	/*
+	 * Must be a contiguous address range in bus space, so maxsegsz
+	 * is the full mapping size.
+	 */
+	ret = -bus_dmamap_create(dmat, nbytes, node->nsegs, nbytes, 0,
+	    BUS_DMA_WAITOK, &node->map);
+	if (ret) {
+fail2:		bus_dmamem_free(dmat, node->segs, node->nsegs);
+		goto fail1;
+	}
+
+	ret = -bus_dmamap_load_raw(dmat, node->map, node->segs, node->nsegs,
+	    nbytes, BUS_DMA_WAITOK);
+	if (ret) {
+fail3: __unused
+		bus_dmamap_destroy(dmat, node->map);
+		node->map = NULL;
+		goto fail2;
+	}
+
+	/* Success!  */
+	return 0;
+}
+
+#else
+
 static int
 gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
 		       struct gk20a_instobj **_node)
@@ -532,6 +702,8 @@ free_pages:
 	return ret;
 }
 
+#endif	/* __NetBSD__ */
+
 static int
 gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
 		  struct nvkm_memory **pmemory)
@@ -539,21 +711,31 @@ gk20a_instobj_new(struct nvkm_instmem *b
 	struct gk20a_instmem *imem = gk20a_instmem(base);
 	struct nvkm_subdev *subdev = &imem->base.subdev;
 	struct gk20a_instobj *node = NULL;
-	int ret;
+	int ret = 0;
 
+#ifdef __NetBSD__
+	nvkm_debug(subdev, "%s (%s): size: %x align: %x\n", __func__,
+		   "bus_dma", size, align);
+#else
 	nvkm_debug(subdev, "%s (%s): size: %x align: %x\n", __func__,
 		   imem->domain ? "IOMMU" : "DMA", size, align);
+#endif
 
 	/* Round size and align to page bounds */
 	size = max(roundup(size, PAGE_SIZE), PAGE_SIZE);
 	align = max(roundup(align, PAGE_SIZE), PAGE_SIZE);
 
+#ifdef __NetBSD__
+	ret = gk20a_instobj_ctor_netbsd(imem, size >> PAGE_SHIFT, align,
+	    &node);
+#else
 	if (imem->domain)
 		ret = gk20a_instobj_ctor_iommu(imem, size >> PAGE_SHIFT,
 					       align, &node);
 	else
 		ret = gk20a_instobj_ctor_dma(imem, size >> PAGE_SHIFT,
 					     align, &node);
+#endif
 	*pmemory = node ? &node->memory : NULL;
 	if (ret)
 		return ret;
@@ -599,7 +781,9 @@ int
 gk20a_instmem_new(struct nvkm_device *device, int index,
 		  struct nvkm_instmem **pimem)
 {
+#ifndef __NetBSD__
 	struct nvkm_device_tegra *tdev = device->func->tegra(device);
+#endif
 	struct gk20a_instmem *imem;
 
 	if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL)))
@@ -613,6 +797,10 @@ gk20a_instmem_new(struct nvkm_device *de
 	imem->vaddr_max = 0x100000;
 	INIT_LIST_HEAD(&imem->vaddr_lru);
 
+#ifdef __NetBSD__
+	imem->cpu_map = gk20a_instobj_cpu_map_netbsd;
+	nvkm_info(&imem->base.subdev, "using bus_dma\n");
+#else
 	if (tdev->iommu.domain) {
 		imem->mm_mutex = &tdev->iommu.mutex;
 		imem->mm = &tdev->iommu.mm;
@@ -633,6 +821,7 @@ gk20a_instmem_new(struct nvkm_device *de
 
 		nvkm_info(&imem->base.subdev, "using DMA API\n");
 	}
+#endif
 
 	return 0;
 }

Reply via email to