From 1c055e55a242a33e574e48be530e06770a210dcd Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 19 Feb 2024 03:26:26 +0000
Subject: [PATCH] add r8169 read mac form eeprom

---
 kernel/drivers/rknpu/rknpu_gem.c |  446 +++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 328 insertions(+), 118 deletions(-)

diff --git a/kernel/drivers/rknpu/rknpu_gem.c b/kernel/drivers/rknpu/rknpu_gem.c
index 6e0e442..415d3a4 100644
--- a/kernel/drivers/rknpu/rknpu_gem.c
+++ b/kernel/drivers/rknpu/rknpu_gem.c
@@ -13,7 +13,6 @@
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 #include <linux/iommu.h>
-#include <linux/dma-iommu.h>
 #include <linux/pfn_t.h>
 #include <linux/version.h>
 #include <asm/cacheflush.h>
@@ -25,6 +24,7 @@
 #include "rknpu_drv.h"
 #include "rknpu_ioctl.h"
 #include "rknpu_gem.h"
+#include "rknpu_iommu.h"
 
 #define RKNPU_GEM_ALLOC_FROM_PAGES 1
 
@@ -67,6 +67,7 @@
 			      rknpu_obj->size);
 		goto free_sgt;
 	}
+	iommu_flush_iotlb_all(iommu_get_domain_for_dev(drm->dev));
 
 	if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING) {
 		rknpu_obj->cookie = vmap(rknpu_obj->pages, rknpu_obj->num_pages,
@@ -115,15 +116,14 @@
 		rknpu_obj->kv_addr = NULL;
 	}
 
-	dma_unmap_sg(drm->dev, rknpu_obj->sgt->sgl, rknpu_obj->sgt->nents,
-		     DMA_BIDIRECTIONAL);
-
-	drm_gem_put_pages(&rknpu_obj->base, rknpu_obj->pages, true, true);
-
 	if (rknpu_obj->sgt != NULL) {
+		dma_unmap_sg(drm->dev, rknpu_obj->sgt->sgl,
+			     rknpu_obj->sgt->nents, DMA_BIDIRECTIONAL);
 		sg_free_table(rknpu_obj->sgt);
 		kfree(rknpu_obj->sgt);
 	}
+
+	drm_gem_put_pages(&rknpu_obj->base, rknpu_obj->pages, true, true);
 }
 #endif
 
@@ -182,7 +182,9 @@
 	if (rknpu_obj->flags & RKNPU_MEM_ZEROING)
 		gfp_mask |= __GFP_ZERO;
 
-	if (!(rknpu_obj->flags & RKNPU_MEM_NON_DMA32)) {
+	if (!rknpu_dev->iommu_en ||
+	    rknpu_dev->config->dma_mask <= DMA_BIT_MASK(32) ||
+	    (rknpu_obj->flags & RKNPU_MEM_DMA32)) {
 		gfp_mask &= ~__GFP_HIGHMEM;
 		gfp_mask |= __GFP_DMA32;
 	}
@@ -253,10 +255,15 @@
 			  i, &s->dma_address, s->length);
 	}
 
-	if (drm_prime_sg_to_page_addr_arrays(sgt, rknpu_obj->pages, NULL,
-					     nr_pages)) {
-		LOG_DEV_ERROR(drm->dev, "invalid sgtable.\n");
-		ret = -EINVAL;
+#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
+	ret = drm_prime_sg_to_page_addr_arrays(sgt, rknpu_obj->pages, NULL,
+					       nr_pages);
+#else
+	ret = drm_prime_sg_to_page_array(sgt, rknpu_obj->pages, nr_pages);
+#endif
+
+	if (ret < 0) {
+		LOG_DEV_ERROR(drm->dev, "invalid sgtable, ret: %d\n", ret);
 		goto err_free_sg_table;
 	}
 
@@ -335,9 +342,28 @@
 	return drm_gem_handle_delete(file_priv, handle);
 }
 
+#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
+static const struct vm_operations_struct vm_ops = {
+	.fault = rknpu_gem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static const struct drm_gem_object_funcs rknpu_gem_object_funcs = {
+	.free = rknpu_gem_free_object,
+	.export = drm_gem_prime_export,
+	.get_sg_table = rknpu_gem_prime_get_sg_table,
+	.vmap = rknpu_gem_prime_vmap,
+	.vunmap = rknpu_gem_prime_vunmap,
+	.mmap = rknpu_gem_mmap_obj,
+	.vm_ops = &vm_ops,
+};
+#endif
+
 static struct rknpu_gem_object *rknpu_gem_init(struct drm_device *drm,
 					       unsigned long size)
 {
+	struct rknpu_device *rknpu_dev = drm->dev_private;
 	struct rknpu_gem_object *rknpu_obj = NULL;
 	struct drm_gem_object *obj = NULL;
 	gfp_t gfp_mask;
@@ -348,6 +374,9 @@
 		return ERR_PTR(-ENOMEM);
 
 	obj = &rknpu_obj->base;
+#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
+	obj->funcs = &rknpu_gem_object_funcs;
+#endif
 
 	ret = drm_gem_object_init(drm, obj, size);
 	if (ret < 0) {
@@ -363,7 +392,9 @@
 	if (rknpu_obj->flags & RKNPU_MEM_ZEROING)
 		gfp_mask |= __GFP_ZERO;
 
-	if (!(rknpu_obj->flags & RKNPU_MEM_NON_DMA32)) {
+	if (!rknpu_dev->iommu_en ||
+	    rknpu_dev->config->dma_mask <= DMA_BIT_MASK(32) ||
+	    (rknpu_obj->flags & RKNPU_MEM_DMA32)) {
 		gfp_mask &= ~__GFP_HIGHMEM;
 		gfp_mask |= __GFP_DMA32;
 	}
@@ -380,7 +411,8 @@
 	kfree(rknpu_obj);
 }
 
-static int rknpu_gem_alloc_buf_with_sram(struct rknpu_gem_object *rknpu_obj)
+static int rknpu_gem_alloc_buf_with_cache(struct rknpu_gem_object *rknpu_obj,
+					  enum rknpu_cache_type cache_type)
 {
 	struct drm_device *drm = rknpu_obj->base.dev;
 	struct rknpu_device *rknpu_dev = drm->dev_private;
@@ -393,18 +425,37 @@
 	unsigned long offset = 0;
 	int i = 0;
 	int ret = -EINVAL;
+	phys_addr_t cache_start = 0;
+	unsigned long cache_offset = 0;
+	unsigned long cache_size = 0;
 
-	/* iova map to sram */
+	switch (cache_type) {
+	case RKNPU_CACHE_SRAM:
+		cache_start = rknpu_dev->sram_start;
+		cache_offset = rknpu_obj->sram_obj->range_start *
+			       rknpu_dev->sram_mm->chunk_size;
+		cache_size = rknpu_obj->sram_size;
+		break;
+	case RKNPU_CACHE_NBUF:
+		cache_start = rknpu_dev->nbuf_start;
+		cache_offset = 0;
+		cache_size = rknpu_obj->nbuf_size;
+		break;
+	default:
+		LOG_ERROR("Unknown rknpu_cache_type: %d", cache_type);
+		return -EINVAL;
+	}
+
+	/* iova map to cache */
 	domain = iommu_get_domain_for_dev(rknpu_dev->dev);
 	if (!domain) {
 		LOG_ERROR("failed to get iommu domain!");
 		return -EINVAL;
 	}
 
-	cookie = domain->iova_cookie;
+	cookie = (void *)domain->iova_cookie;
 	iovad = &cookie->iovad;
-	rknpu_obj->iova_size =
-		iova_align(iovad, rknpu_obj->sram_size + rknpu_obj->size);
+	rknpu_obj->iova_size = iova_align(iovad, cache_size + rknpu_obj->size);
 	rknpu_obj->iova_start = rknpu_iommu_dma_alloc_iova(
 		domain, rknpu_obj->iova_size, dma_get_mask(drm->dev), drm->dev);
 	if (!rknpu_obj->iova_start) {
@@ -416,20 +467,20 @@
 		 &rknpu_obj->iova_start, rknpu_obj->iova_size);
 
 	/*
-	 * Overview SRAM + DDR map to IOVA
+	 * Overview cache + DDR map to IOVA
 	 * --------
-	 * sram_size: rknpu_obj->sram_size
-	 *   - allocate from SRAM, this size value has been page-aligned
+	 * cache_size:
+	 *   - allocate from CACHE, this size value has been page-aligned
 	 * size: rknpu_obj->size
 	 *   - allocate from DDR pages, this size value has been page-aligned
 	 * iova_size: rknpu_obj->iova_size
-	 *   - from iova_align(sram_size + size)
-	 *   - it may be larger than the (sram_size + size), and the larger part is not mapped
+	 *   - from iova_align(cache_size + size)
+	 *   - it may be larger than the (cache_size + size), and the larger part is not mapped
 	 * --------
 	 *
-	 * |<- sram_size ->|      |<- - - - size - - - ->|
+	 * |<- cache_size ->|      |<- - - - size - - - ->|
 	 * +---------------+      +----------------------+
-	 * |     SRAM      |      |         DDR          |
+	 * |     CACHE      |      |         DDR          |
 	 * +---------------+      +----------------------+
 	 *         |                    |
 	 * |       V       |            V          |
@@ -439,20 +490,18 @@
 	 * |<- - - - - - - iova_size - - - - - - ->|
 	 *
 	 */
-	offset = rknpu_obj->sram_obj->range_start *
-		 rknpu_dev->sram_mm->chunk_size;
 	ret = iommu_map(domain, rknpu_obj->iova_start,
-			rknpu_dev->sram_start + offset, rknpu_obj->sram_size,
+			cache_start + cache_offset, cache_size,
 			IOMMU_READ | IOMMU_WRITE);
 	if (ret) {
-		LOG_ERROR("sram iommu_map error: %d\n", ret);
+		LOG_ERROR("cache iommu_map error: %d\n", ret);
 		goto free_iova;
 	}
 
 	rknpu_obj->dma_addr = rknpu_obj->iova_start;
 
 	if (rknpu_obj->size == 0) {
-		LOG_INFO("allocate sram size: %lu\n", rknpu_obj->sram_size);
+		LOG_INFO("allocate cache size: %lu\n", cache_size);
 		return 0;
 	}
 
@@ -460,7 +509,7 @@
 	if (IS_ERR(rknpu_obj->pages)) {
 		ret = PTR_ERR(rknpu_obj->pages);
 		LOG_ERROR("failed to get pages: %d\n", ret);
-		goto sram_unmap;
+		goto cache_unmap;
 	}
 
 	rknpu_obj->num_pages = rknpu_obj->size >> PAGE_SHIFT;
@@ -479,7 +528,7 @@
 	}
 
 	length = rknpu_obj->size;
-	offset = rknpu_obj->iova_start + rknpu_obj->sram_size;
+	offset = rknpu_obj->iova_start + cache_size;
 
 	for_each_sg(rknpu_obj->sgt->sgl, s, rknpu_obj->sgt->nents, i) {
 		size = (length < s->length) ? length : s->length;
@@ -498,13 +547,13 @@
 			break;
 	}
 
-	LOG_INFO("allocate size: %lu with sram size: %lu\n", rknpu_obj->size,
-		 rknpu_obj->sram_size);
+	LOG_INFO("allocate size: %lu with cache size: %lu\n", rknpu_obj->size,
+		 cache_size);
 
 	return 0;
 
 sgl_unmap:
-	iommu_unmap(domain, rknpu_obj->iova_start + rknpu_obj->sram_size,
+	iommu_unmap(domain, rknpu_obj->iova_start + cache_size,
 		    rknpu_obj->size - length);
 	sg_free_table(rknpu_obj->sgt);
 	kfree(rknpu_obj->sgt);
@@ -512,32 +561,43 @@
 put_pages:
 	drm_gem_put_pages(&rknpu_obj->base, rknpu_obj->pages, false, false);
 
-sram_unmap:
-	iommu_unmap(domain, rknpu_obj->iova_start, rknpu_obj->sram_size);
+cache_unmap:
+	iommu_unmap(domain, rknpu_obj->iova_start, cache_size);
 
 free_iova:
-	rknpu_iommu_dma_free_iova(domain->iova_cookie, rknpu_obj->iova_start,
-				  rknpu_obj->iova_size);
+	rknpu_iommu_dma_free_iova((void *)domain->iova_cookie,
+				  rknpu_obj->iova_start, rknpu_obj->iova_size);
 
 	return ret;
 }
 
-static void rknpu_gem_free_buf_with_sram(struct rknpu_gem_object *rknpu_obj)
+static void rknpu_gem_free_buf_with_cache(struct rknpu_gem_object *rknpu_obj,
+					  enum rknpu_cache_type cache_type)
 {
 	struct drm_device *drm = rknpu_obj->base.dev;
 	struct rknpu_device *rknpu_dev = drm->dev_private;
 	struct iommu_domain *domain = NULL;
+	unsigned long cache_size = 0;
+
+	switch (cache_type) {
+	case RKNPU_CACHE_SRAM:
+		cache_size = rknpu_obj->sram_size;
+		break;
+	case RKNPU_CACHE_NBUF:
+		cache_size = rknpu_obj->nbuf_size;
+		break;
+	default:
+		LOG_ERROR("Unknown rknpu_cache_type: %d", cache_type);
+		return;
+	}
 
 	domain = iommu_get_domain_for_dev(rknpu_dev->dev);
 	if (domain) {
-		iommu_unmap(domain, rknpu_obj->iova_start,
-			    rknpu_obj->sram_size);
+		iommu_unmap(domain, rknpu_obj->iova_start, cache_size);
 		if (rknpu_obj->size > 0)
-			iommu_unmap(domain,
-				    rknpu_obj->iova_start +
-					    rknpu_obj->sram_size,
+			iommu_unmap(domain, rknpu_obj->iova_start + cache_size,
 				    rknpu_obj->size);
-		rknpu_iommu_dma_free_iova(domain->iova_cookie,
+		rknpu_iommu_dma_free_iova((void *)domain->iova_cookie,
 					  rknpu_obj->iova_start,
 					  rknpu_obj->iova_size);
 	}
@@ -618,9 +678,35 @@
 		if (real_sram_size > 0) {
 			rknpu_obj->sram_size = real_sram_size;
 
-			ret = rknpu_gem_alloc_buf_with_sram(rknpu_obj);
+			ret = rknpu_gem_alloc_buf_with_cache(rknpu_obj,
+							     RKNPU_CACHE_SRAM);
 			if (ret < 0)
 				goto mm_free;
+			remain_ddr_size = 0;
+		}
+	} else if (IS_ENABLED(CONFIG_NO_GKI) &&
+		   (flags & RKNPU_MEM_TRY_ALLOC_NBUF) &&
+		   rknpu_dev->nbuf_size > 0) {
+		size_t nbuf_size = 0;
+
+		rknpu_obj = rknpu_gem_init(drm, remain_ddr_size);
+		if (IS_ERR(rknpu_obj))
+			return rknpu_obj;
+
+		nbuf_size = remain_ddr_size <= rknpu_dev->nbuf_size ?
+				    remain_ddr_size :
+				    rknpu_dev->nbuf_size;
+
+		/* set memory type and cache attribute from user side. */
+		rknpu_obj->flags = flags;
+
+		if (nbuf_size > 0) {
+			rknpu_obj->nbuf_size = nbuf_size;
+
+			ret = rknpu_gem_alloc_buf_with_cache(rknpu_obj,
+							     RKNPU_CACHE_NBUF);
+			if (ret < 0)
+				goto gem_release;
 			remain_ddr_size = 0;
 		}
 	}
@@ -640,9 +726,11 @@
 
 	if (rknpu_obj)
 		LOG_DEBUG(
-			"created dma addr: %pad, cookie: %p, ddr size: %lu, sram size: %lu, attrs: %#lx, flags: %#x\n",
-			&rknpu_obj->dma_addr, rknpu_obj->cookie, rknpu_obj->size,
-			rknpu_obj->sram_size, rknpu_obj->dma_attrs, rknpu_obj->flags);
+			"created dma addr: %pad, cookie: %p, ddr size: %lu, sram size: %lu, nbuf size: %lu, attrs: %#lx, flags: %#x\n",
+			&rknpu_obj->dma_addr, rknpu_obj->cookie,
+			rknpu_obj->size, rknpu_obj->sram_size,
+			rknpu_obj->nbuf_size, rknpu_obj->dma_attrs,
+			rknpu_obj->flags);
 
 	return rknpu_obj;
 
@@ -683,7 +771,12 @@
 			if (rknpu_obj->sram_obj != NULL)
 				rknpu_mm_free(rknpu_dev->sram_mm,
 					      rknpu_obj->sram_obj);
-			rknpu_gem_free_buf_with_sram(rknpu_obj);
+			rknpu_gem_free_buf_with_cache(rknpu_obj,
+						      RKNPU_CACHE_SRAM);
+		} else if (IS_ENABLED(CONFIG_NO_GKI) &&
+			   rknpu_obj->nbuf_size > 0) {
+			rknpu_gem_free_buf_with_cache(rknpu_obj,
+						      RKNPU_CACHE_NBUF);
 		} else {
 			rknpu_gem_free_buf(rknpu_obj);
 		}
@@ -808,6 +901,75 @@
 }
 #endif
 
+static int rknpu_gem_mmap_cache(struct rknpu_gem_object *rknpu_obj,
+				struct vm_area_struct *vma,
+				enum rknpu_cache_type cache_type)
+{
+	struct drm_device *drm = rknpu_obj->base.dev;
+#if RKNPU_GEM_ALLOC_FROM_PAGES
+	struct rknpu_device *rknpu_dev = drm->dev_private;
+#endif
+	unsigned long vm_size = 0;
+	int ret = -EINVAL;
+	unsigned long offset = 0;
+	unsigned long num_pages = 0;
+	int i = 0;
+	phys_addr_t cache_start = 0;
+	unsigned long cache_offset = 0;
+	unsigned long cache_size = 0;
+
+	switch (cache_type) {
+	case RKNPU_CACHE_SRAM:
+		cache_start = rknpu_dev->sram_start;
+		cache_offset = rknpu_obj->sram_obj->range_start *
+			       rknpu_dev->sram_mm->chunk_size;
+		cache_size = rknpu_obj->sram_size;
+		break;
+	case RKNPU_CACHE_NBUF:
+		cache_start = rknpu_dev->nbuf_start;
+		cache_offset = 0;
+		cache_size = rknpu_obj->nbuf_size;
+		break;
+	default:
+		LOG_ERROR("Unknown rknpu_cache_type: %d", cache_type);
+		return -EINVAL;
+	}
+
+	vma->vm_flags |= VM_MIXEDMAP;
+
+	vm_size = vma->vm_end - vma->vm_start;
+
+	/*
+	 * Convert a physical address in a cache area to a page frame number (PFN),
+	 * and store the resulting PFN in the vm_pgoff field of the given VMA.
+	 *
+	 * NOTE: This conversion carries a risk because the resulting PFN is not a true
+	 * page frame number and may not be valid or usable in all contexts.
+	 */
+	vma->vm_pgoff = __phys_to_pfn(cache_start + cache_offset);
+
+	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, cache_size,
+			      vma->vm_page_prot);
+	if (ret)
+		return -EAGAIN;
+
+	if (rknpu_obj->size == 0)
+		return 0;
+
+	offset = cache_size;
+
+	num_pages = (vm_size - cache_size) / PAGE_SIZE;
+	for (i = 0; i < num_pages; ++i) {
+		ret = vm_insert_page(vma, vma->vm_start + offset,
+				     rknpu_obj->pages[i]);
+		if (ret < 0)
+			return ret;
+		offset += PAGE_SIZE;
+	}
+
+	return 0;
+}
+
 static int rknpu_gem_mmap_buffer(struct rknpu_gem_object *rknpu_obj,
 				 struct vm_area_struct *vma)
 {
@@ -823,6 +985,7 @@
 	 * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
 	 * the whole buffer.
 	 */
+	vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
 	vma->vm_flags &= ~VM_PFNMAP;
 	vma->vm_pgoff = 0;
 
@@ -832,38 +995,10 @@
 	if (vm_size > rknpu_obj->size)
 		return -EINVAL;
 
-	if (rknpu_obj->sram_size > 0) {
-		unsigned long offset = 0;
-		unsigned long num_pages = 0;
-		int i = 0;
-
-		vma->vm_flags |= VM_MIXEDMAP;
-
-		offset = rknpu_obj->sram_obj->range_start *
-			 rknpu_dev->sram_mm->chunk_size;
-		vma->vm_pgoff = __phys_to_pfn(rknpu_dev->sram_start + offset);
-
-		ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-				      rknpu_obj->sram_size, vma->vm_page_prot);
-		if (ret)
-			return -EAGAIN;
-
-		if (rknpu_obj->size == 0)
-			return 0;
-
-		offset = rknpu_obj->sram_size;
-
-		num_pages = (vm_size - rknpu_obj->sram_size) / PAGE_SIZE;
-		for (i = 0; i < num_pages; ++i) {
-			ret = vm_insert_page(vma, vma->vm_start + offset,
-					     rknpu_obj->pages[i]);
-			if (ret < 0)
-				return ret;
-			offset += PAGE_SIZE;
-		}
-
-		return 0;
-	}
+	if (rknpu_obj->sram_size > 0)
+		return rknpu_gem_mmap_cache(rknpu_obj, vma, RKNPU_CACHE_SRAM);
+	else if (rknpu_obj->nbuf_size > 0)
+		return rknpu_gem_mmap_cache(rknpu_obj, vma, RKNPU_CACHE_NBUF);
 
 #if RKNPU_GEM_ALLOC_FROM_PAGES
 	if ((rknpu_obj->flags & RKNPU_MEM_NON_CONTIGUOUS) &&
@@ -1045,8 +1180,7 @@
 }
 #endif
 
-static int rknpu_gem_mmap_obj(struct drm_gem_object *obj,
-			      struct vm_area_struct *vma)
+int rknpu_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma)
 {
 	struct rknpu_gem_object *rknpu_obj = to_rknpu_obj(obj);
 	int ret = -EINVAL;
@@ -1143,8 +1277,12 @@
 		goto err;
 	}
 
+#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
 	ret = drm_prime_sg_to_page_addr_arrays(sgt, rknpu_obj->pages, NULL,
 					       npages);
+#else
+	ret = drm_prime_sg_to_page_array(sgt, rknpu_obj->pages, npages);
+#endif
 	if (ret < 0)
 		goto err_free_large;
 
@@ -1172,6 +1310,7 @@
 	return ERR_PTR(ret);
 }
 
+#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
 void *rknpu_gem_prime_vmap(struct drm_gem_object *obj)
 {
 	struct rknpu_gem_object *rknpu_obj = to_rknpu_obj(obj);
@@ -1187,6 +1326,35 @@
 {
 	vunmap(vaddr);
 }
+#else
+int rknpu_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
+{
+	struct rknpu_gem_object *rknpu_obj = to_rknpu_obj(obj);
+	void *vaddr = NULL;
+
+	if (!rknpu_obj->pages)
+		return -EINVAL;
+
+	vaddr = vmap(rknpu_obj->pages, rknpu_obj->num_pages, VM_MAP,
+			  PAGE_KERNEL);
+	if (!vaddr)
+		return -ENOMEM;
+
+	iosys_map_set_vaddr(map, vaddr);
+
+	return 0;
+}
+
+void rknpu_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
+{
+	struct rknpu_gem_object *rknpu_obj = to_rknpu_obj(obj);
+
+	if (rknpu_obj->pages) {
+		vunmap(map->vaddr);
+		map->vaddr = NULL;
+	}
+}
+#endif
 
 int rknpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
 {
@@ -1199,14 +1367,68 @@
 	return rknpu_gem_mmap_obj(obj, vma);
 }
 
+static int rknpu_cache_sync(struct rknpu_gem_object *rknpu_obj,
+			    unsigned long *length, unsigned long *offset,
+			    enum rknpu_cache_type cache_type)
+{
+#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
+	struct drm_gem_object *obj = &rknpu_obj->base;
+	struct rknpu_device *rknpu_dev = obj->dev->dev_private;
+	void __iomem *cache_base_io = NULL;
+	unsigned long cache_offset = 0;
+	unsigned long cache_size = 0;
+
+	switch (cache_type) {
+	case RKNPU_CACHE_SRAM:
+		cache_base_io = rknpu_dev->sram_base_io;
+		cache_offset = rknpu_obj->sram_obj->range_start *
+			       rknpu_dev->sram_mm->chunk_size;
+		cache_size = rknpu_obj->sram_size;
+		break;
+	case RKNPU_CACHE_NBUF:
+		cache_base_io = rknpu_dev->nbuf_base_io;
+		cache_offset = 0;
+		cache_size = rknpu_obj->nbuf_size;
+		break;
+	default:
+		LOG_ERROR("Unknown rknpu_cache_type: %d", cache_type);
+		return -EINVAL;
+	}
+
+	if ((*offset + *length) <= cache_size) {
+		__dma_map_area(cache_base_io + *offset + cache_offset, *length,
+			       DMA_TO_DEVICE);
+		__dma_unmap_area(cache_base_io + *offset + cache_offset,
+				 *length, DMA_FROM_DEVICE);
+		*length = 0;
+		*offset = 0;
+	} else if (*offset >= cache_size) {
+		*offset -= cache_size;
+	} else {
+		unsigned long cache_length = cache_size - *offset;
+
+		__dma_map_area(cache_base_io + *offset + cache_offset,
+			       cache_length, DMA_TO_DEVICE);
+		__dma_unmap_area(cache_base_io + *offset + cache_offset,
+				 cache_length, DMA_FROM_DEVICE);
+		*length -= cache_length;
+		*offset = 0;
+	}
+#endif
+
+	return 0;
+}
+
 int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv)
 {
 	struct rknpu_gem_object *rknpu_obj = NULL;
+	struct rknpu_device *rknpu_dev = dev->dev_private;
 	struct rknpu_mem_sync *args = data;
 	struct scatterlist *sg;
+	dma_addr_t sg_phys_addr;
 	unsigned long length, offset = 0;
-	unsigned long sg_left, size = 0;
+	unsigned long sg_offset, sg_left, size = 0;
 	unsigned long len = 0;
 	int i;
 
@@ -1230,38 +1452,20 @@
 						      DMA_FROM_DEVICE);
 		}
 	} else {
+		WARN_ON(!rknpu_dev->fake_dev);
+
 		length = args->size;
 		offset = args->offset;
 
-		if (IS_ENABLED(CONFIG_ROCKCHIP_RKNPU_SRAM) && rknpu_obj->sram_size > 0) {
-			struct drm_gem_object *obj = &rknpu_obj->base;
-			struct rknpu_device *rknpu_dev = obj->dev->dev_private;
-			unsigned long sram_offset =
-				rknpu_obj->sram_obj->range_start *
-				rknpu_dev->sram_mm->chunk_size;
-			if ((offset + length) <= rknpu_obj->sram_size) {
-				__dma_map_area(rknpu_dev->sram_base_io +
-						       offset + sram_offset,
-					       length, DMA_TO_DEVICE);
-				__dma_unmap_area(rknpu_dev->sram_base_io +
-							 offset + sram_offset,
-						 length, DMA_FROM_DEVICE);
-				length = 0;
-				offset = 0;
-			} else if (offset >= rknpu_obj->sram_size) {
-				offset -= rknpu_obj->sram_size;
-			} else {
-				unsigned long sram_length =
-					rknpu_obj->sram_size - offset;
-				__dma_map_area(rknpu_dev->sram_base_io +
-						       offset + sram_offset,
-					       sram_length, DMA_TO_DEVICE);
-				__dma_unmap_area(rknpu_dev->sram_base_io +
-							 offset + sram_offset,
-						 sram_length, DMA_FROM_DEVICE);
-				length -= sram_length;
-				offset = 0;
-			}
+		if (IS_ENABLED(CONFIG_NO_GKI) &&
+		    IS_ENABLED(CONFIG_ROCKCHIP_RKNPU_SRAM) &&
+		    rknpu_obj->sram_size > 0) {
+			rknpu_cache_sync(rknpu_obj, &length, &offset,
+					 RKNPU_CACHE_SRAM);
+		} else if (IS_ENABLED(CONFIG_NO_GKI) &&
+			   rknpu_obj->nbuf_size > 0) {
+			rknpu_cache_sync(rknpu_obj, &length, &offset,
+					 RKNPU_CACHE_NBUF);
 		}
 
 		for_each_sg(rknpu_obj->sgt->sgl, sg, rknpu_obj->sgt->nents,
@@ -1273,17 +1477,23 @@
 			if (len <= offset)
 				continue;
 
+			sg_phys_addr = sg_phys(sg);
+
 			sg_left = len - offset;
+			sg_offset = sg->length - sg_left;
+
 			size = (length < sg_left) ? length : sg_left;
 
 			if (args->flags & RKNPU_MEM_SYNC_TO_DEVICE) {
-				dma_sync_sg_for_device(dev->dev, sg, 1,
-						       DMA_TO_DEVICE);
+				dma_sync_single_range_for_device(
+					rknpu_dev->fake_dev, sg_phys_addr,
+					sg_offset, size, DMA_TO_DEVICE);
 			}
 
 			if (args->flags & RKNPU_MEM_SYNC_FROM_DEVICE) {
-				dma_sync_sg_for_cpu(dev->dev, sg, 1,
-						    DMA_FROM_DEVICE);
+				dma_sync_single_range_for_cpu(
+					rknpu_dev->fake_dev, sg_phys_addr,
+					sg_offset, size, DMA_FROM_DEVICE);
 			}
 
 			offset += size;

--
Gitblit v1.6.2