kernel/0213-feat-skip-the-user-memory-cache-flush.patch
2025-01-02 22:30:57 -05:00

205 lines
7.3 KiB
Diff

From f9190a55cf4c67fc69a5764a03f85eb53ea16b92 Mon Sep 17 00:00:00 2001
From: liusheng <liusheng@eswincomputing.com>
Date: Tue, 15 Oct 2024 10:25:20 +0800
Subject: [PATCH 213/222] feat:skip the user memory cache flush
Changelogs:
1. skip the user memory cache flush, the flush decide by user
2. fix the pfn type virtual memory import
3. skip cache flush if pfn type with noncached
Signed-off-by: liusheng <liusheng@eswincomputing.com>
---
.../gc_hal_kernel_allocator_user_memory.c | 57 +++++++++++--------
1 file changed, 34 insertions(+), 23 deletions(-)
diff --git a/drivers/staging/media/eswin/hae/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c b/drivers/staging/media/eswin/hae/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c
index 2fca3da9c727..151e006da98f 100644
--- a/drivers/staging/media/eswin/hae/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c
+++ b/drivers/staging/media/eswin/hae/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c
@@ -114,6 +114,7 @@ struct um_desc {
size_t pageCount;
size_t extraPage;
unsigned int alloc_from_res;
+ int noncached;
};
static void *alloc_memory(size_t bytes)
@@ -244,7 +245,7 @@ import_page_map(gckOS Os, struct device *dev, struct um_desc *um,
(flags & VM_WRITE) ? 1 : 0, 0,
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,6,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
pages);
#else
pages, NULL);
@@ -292,7 +293,7 @@ import_page_map(gckOS Os, struct device *dev, struct um_desc *um,
goto error;
}
- result = dma_map_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
+ result = dma_map_sg_attrs(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
if (unlikely(result != um->sgt.nents)) {
pr_warn("[galcore]: %s: dma_map_sg failed\n", __func__);
goto error;
@@ -301,7 +302,7 @@ import_page_map(gckOS Os, struct device *dev, struct um_desc *um,
if (Os->iommu)
um->dmaHandle = sg_dma_address(um->sgt.sgl);
- dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
+ /*dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);*/
}
um->type = UM_PAGE_MAP;
@@ -332,13 +333,13 @@ import_pfn_map(gckOS Os, struct device *dev, struct um_desc *um,
struct page **pages = gcvNULL;
int result = 0;
size_t pageCount = 0;
-
+ unsigned int data = 0;
if (!current->mm)
return -ENOTTY;
down_read(&current_mm_mmap_sem);
vma = find_vma(current->mm, addr);
-#if !gcdUSING_PFN_FOLLOW
+#if !gcdUSING_PFN_FOLLOW && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0))
up_read(&current_mm_mmap_sem);
#endif
@@ -365,25 +366,28 @@ import_pfn_map(gckOS Os, struct device *dev, struct um_desc *um,
}
for (i = 0; i < pfn_count; i++) {
-#if gcdUSING_PFN_FOLLOW
+#if gcdUSING_PFN_FOLLOW || (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
int ret = 0;
ret = follow_pfn(vma, addr, &pfns[i]);
if (ret < 0) {
+ ret = gckOS_ReadMappedPointer(Os, (gctPOINTER)addr, &data);
+ if (!ret)
+ ret = follow_pfn(vma, addr, &pfns[i]);
+ if (ret < 0) {
up_read(&current_mm_mmap_sem);
goto err;
+ }
}
#else
/* protect pfns[i] */
+ spinlock_t *ptl;
pgd_t *pgd;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
p4d_t *p4d;
# endif
pud_t *pud;
pmd_t *pmd;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
pte_t *pte;
- spinlock_t *ptl;
-#endif
pgd = pgd_offset(current->mm, addr);
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto err;
@@ -408,23 +412,25 @@ import_pfn_map(gckOS Os, struct device *dev, struct um_desc *um,
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto err;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
-
+ if (!pte_present(*pte)) {
+ if (pte)
+ pte_unmap_unlock(pte, ptl);
+ if (gcmIS_SUCCESS(gckOS_ReadMappedPointer(Os, (gctPOINTER)addr, &data)))
+ pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
if (!pte_present(*pte)) {
pte_unmap_unlock(pte, ptl);
goto err;
}
-
+ }
pfns[i] = pte_pfn(*pte);
pte_unmap_unlock(pte, ptl);
#endif
-#endif
/* Advance to next. */
addr += PAGE_SIZE;
}
-#if gcdUSING_PFN_FOLLOW
+#if gcdUSING_PFN_FOLLOW || (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
up_read(&current_mm_mmap_sem);
#endif
@@ -464,7 +470,7 @@ import_pfn_map(gckOS Os, struct device *dev, struct um_desc *um,
goto err;
}
- result = dma_map_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
+ result = dma_map_sg_attrs(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
if (unlikely(result != um->sgt.nents)) {
#if gcdUSE_LINUX_SG_TABLE_API
@@ -637,6 +643,10 @@ _Import(gckOS Os, PLINUX_MDL Mdl, gctPOINTER Memory,
UserMemory->pageCount = pageCount;
UserMemory->extraPage = extraPage;
+ if ((vm_flags & VM_PFNMAP) && pgprot_dmacoherent(vma->vm_page_prot).pgprot == vma->vm_page_prot.pgprot) {
+ UserMemory->noncached = 1;
+ }
+
/* Success. */
gcmkFOOTER();
return gcvSTATUS_OK;
@@ -706,11 +716,11 @@ release_page_map(gckOS Os, struct device *dev, struct um_desc *um)
{
int i;
- dma_sync_sg_for_device(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
+ /*dma_sync_sg_for_device(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
- dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
+ dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);*/
- dma_unmap_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
+ dma_unmap_sg_attrs(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
um->dmaHandle = 0;
@@ -740,7 +750,7 @@ release_pfn_map(gckOS Os, struct device *dev, struct um_desc *um)
int i;
if (um->pfns_valid) {
- dma_unmap_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
+ dma_unmap_sg_attrs(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
#if gcdUSE_LINUX_SG_TABLE_API
sg_free_table(&um->sgt);
@@ -759,11 +769,7 @@ release_pfn_map(gckOS Os, struct device *dev, struct um_desc *um)
SetPageDirty(page);
if (um->refs[i])
-#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 6, 0)
- unpin_user_page(page);
-#else
put_page(page);
-#endif
}
}
@@ -848,6 +854,11 @@ _UserMemoryCache(gckALLOCATOR Allocator, PLINUX_MDL Mdl, gctSIZE_T Offset,
return gcvSTATUS_OK;
}
+ if (um->type == UM_PFN_MAP && um->noncached == 1) {
+ _MemoryBarrier();
+ return gcvSTATUS_OK;
+ }
+
#ifdef CONFIG_ARM
/* coherent cache in case vivt or vipt-aliasing cache. */
__cpuc_flush_user_range(um->user_vaddr, um->user_vaddr + um->size, um->vm_flags);
--
2.47.0