From ea08eeccae9297f7aabd2ef7f0c2517ac4549acc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:18:26 +0000
Subject: [PATCH] write in 30M
---
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