1111 lines
31 KiB
Diff
1111 lines
31 KiB
Diff
From 4887b2b5ad0bcd7fdea8f21a94e6e3851d7b2741 Mon Sep 17 00:00:00 2001
|
|
From: tangdaoyong <tangdaoyong@eswincomputing.com>
|
|
Date: Fri, 20 Sep 2024 17:54:03 +0800
|
|
Subject: [PATCH 182/219] feat:decode with user space buffer
|
|
|
|
Changelogs:
|
|
1. decode with user space buffer.
|
|
pin_user_pages -> sg_alloc_table_from_pages -> dma_map_sg
|
|
|
|
Signed-off-by: tangdaoyong <tangdaoyong@eswincomputing.com>
|
|
---
|
|
drivers/staging/media/eswin/vdec/Makefile | 3 +-
|
|
drivers/staging/media/eswin/vdec/hantro_dec.c | 69 ++
|
|
drivers/staging/media/eswin/vdec/hantrodec.h | 19 +-
|
|
.../staging/media/eswin/vdec/vdec_allocator.c | 887 ++++++++++++++++++
|
|
.../staging/media/eswin/vdec/vdec_allocator.h | 20 +
|
|
5 files changed, 996 insertions(+), 2 deletions(-)
|
|
create mode 100644 drivers/staging/media/eswin/vdec/vdec_allocator.c
|
|
create mode 100644 drivers/staging/media/eswin/vdec/vdec_allocator.h
|
|
|
|
diff --git a/drivers/staging/media/eswin/vdec/Makefile b/drivers/staging/media/eswin/vdec/Makefile
|
|
index 3983ec82f153..0788e1021086 100644
|
|
--- a/drivers/staging/media/eswin/vdec/Makefile
|
|
+++ b/drivers/staging/media/eswin/vdec/Makefile
|
|
@@ -8,6 +8,7 @@ es_vdec-objs := hantro_dec.o \
|
|
vcmdswhwregisters.o \
|
|
subsys.o \
|
|
hantro_afbc.o \
|
|
- dts_parser.o
|
|
+ dts_parser.o \
|
|
+ vdec_allocator.o
|
|
|
|
obj-$(CONFIG_VIDEO_ESWIN_VDEC) += es_vdec.o
|
|
\ No newline at end of file
|
|
diff --git a/drivers/staging/media/eswin/vdec/hantro_dec.c b/drivers/staging/media/eswin/vdec/hantro_dec.c
|
|
index 88adf1bd86d6..cc4e04b3c5c3 100644
|
|
--- a/drivers/staging/media/eswin/vdec/hantro_dec.c
|
|
+++ b/drivers/staging/media/eswin/vdec/hantro_dec.c
|
|
@@ -104,6 +104,7 @@
|
|
#include "hantroaxife.h"
|
|
#include "hantroafbc.h"
|
|
#include "dts_parser.h"
|
|
+#include "vdec_allocator.h"
|
|
|
|
#define LOG_TAG DEC_DEV_NAME ":main"
|
|
#include "vc_drv_log.h"
|
|
@@ -547,6 +548,8 @@ static char *IoctlCmdStr(unsigned int cmd)
|
|
#ifdef SUPPORT_DMA_HEAP
|
|
IOCTL_CMD_STR_CASE(HANTRODEC_IOC_DMA_HEAP_GET_IOVA);
|
|
#endif
|
|
+ IOCTL_CMD_STR_CASE(HANTRODEC_IOC_ATTACH_USER_MEM);
|
|
+ IOCTL_CMD_STR_CASE(HANTRODEC_IOC_DETACH_USER_MEM);
|
|
default:
|
|
return "Invalid ioctl cmd";
|
|
}
|
|
@@ -2509,6 +2512,70 @@ static long hantrodec_ioctl(struct file *filp, unsigned int cmd,
|
|
return 0;
|
|
}
|
|
#endif
|
|
+ case HANTRODEC_IOC_ATTACH_USER_MEM: {
|
|
+ user_memory_desc desc;
|
|
+ struct device *dev = NULL;
|
|
+
|
|
+ if (copy_from_user(&desc, (void __user *)arg, sizeof(desc)) != 0) {
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ LOG_DBG("attach user memory: memory %px, size: %lu, nid: %u\n", desc.memory, desc.size, desc.nid);
|
|
+ if (!desc.memory || !desc.size) {
|
|
+ LOG_ERR("invalid param, addr=%px, size=%lu\n", desc.memory, desc.size);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ do {
|
|
+ if (desc.nid == 1) {
|
|
+ if (platformdev_d1) {
|
|
+ dev = &platformdev_d1->dev;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ } else if (!desc.nid) {
|
|
+ if (platformdev) {
|
|
+ dev = &platformdev->dev;
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ } while (0);
|
|
+ if (!dev) {
|
|
+ LOG_ERR("%d::invalid nid: %u\n", __LINE__, desc.nid);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ LOG_DBG("%d: nid: %u, dev: %px\n", __LINE__, desc.nid, dev);
|
|
+
|
|
+ if (vdec_attach_user_memory(filp, dev, &desc)) {
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ tmp = copy_to_user((u32 __user *)arg, &desc, sizeof(desc));
|
|
+ if (tmp) {
|
|
+ LOG_ERR("%s %d: copy_from_user failed, returned %li\n", __func__, __LINE__, tmp);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ } break;
|
|
+ case HANTRODEC_IOC_DETACH_USER_MEM: {
|
|
+ user_memory_desc desc;
|
|
+ if (copy_from_user(&desc, (void __user *)arg, sizeof(desc)) != 0) {
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (vdec_detach_user_memory(filp, &desc)) {
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ } break;
|
|
+ case HANTRODEC_IOC_SYNC_USER_MEM_CACHE: {
|
|
+ user_memory_desc desc;
|
|
+ if (copy_from_user(&desc, (void __user *)arg, sizeof(desc)) != 0) {
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ if (vdec_sync_user_memory_cache(filp, &desc, ES_CACHE_CLEAN)) {
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ } break;
|
|
default: {
|
|
if (_IOC_TYPE(cmd) == HANTRO_IOC_MMU) {
|
|
volatile u8 *mmu_hwregs[MAX_SUBSYS_NUM][2];
|
|
@@ -2560,6 +2627,7 @@ static int hantrodec_open(struct inode *inode, struct file *filp)
|
|
for (u32 core_id = 0; core_id < DEC_CORE_NUM; core_id ++) {
|
|
atomic_set(&(fp_priv->core_tasks[core_id]), 0);
|
|
}
|
|
+ init_bi_list((bi_list*)&fp_priv->user_memory_list);
|
|
filp->private_data = (void *)fp_priv;
|
|
LOG_DBG("dev opened\n");
|
|
|
|
@@ -2604,6 +2672,7 @@ static int hantrodec_release(struct inode *inode,
|
|
ReleasePostProcessor(dev, n);
|
|
}
|
|
}
|
|
+ vdec_clean_user_memory(&fp_priv->user_memory_list);
|
|
|
|
MMURelease(filp, hantrodec_data.hwregs[0][HW_MMU]);
|
|
|
|
diff --git a/drivers/staging/media/eswin/vdec/hantrodec.h b/drivers/staging/media/eswin/vdec/hantrodec.h
|
|
index 4f597b740eb2..da90216883cc 100644
|
|
--- a/drivers/staging/media/eswin/vdec/hantrodec.h
|
|
+++ b/drivers/staging/media/eswin/vdec/hantrodec.h
|
|
@@ -74,6 +74,7 @@
|
|
#endif
|
|
|
|
#include "hantrovcmd.h"
|
|
+#include "bidirect_list.h"
|
|
|
|
enum CoreType {
|
|
/* Decoder */
|
|
@@ -165,9 +166,16 @@ struct filp_priv {
|
|
#endif
|
|
void *dev;
|
|
atomic_t core_tasks[DEC_CORE_NUM]; /** for task count of 4 cores*/
|
|
+ bi_list user_memory_list;
|
|
};
|
|
#endif
|
|
|
|
+typedef struct {
|
|
+ void *memory; /* user space memory addr */
|
|
+ size_t size; /* memory size */
|
|
+ __u32 nid; /* numa id */
|
|
+} user_memory_desc;
|
|
+
|
|
/* Use 'k' as magic number */
|
|
#define HANTRODEC_IOC_MAGIC 'k'
|
|
|
|
@@ -251,6 +259,15 @@ struct filp_priv {
|
|
#define HANTRODEC_IOC_DMA_HEAP_FD_SPLIT \
|
|
_IOR(HANTRODEC_IOC_MAGIC, 35, struct dmabuf_split *)
|
|
|
|
-#define HANTRODEC_IOC_MAXNR 35
|
|
+#define HANTRODEC_IOC_ATTACH_USER_MEM \
|
|
+ _IOWR(HANTRODEC_IOC_MAGIC, 36, user_memory_desc *)
|
|
+
|
|
+#define HANTRODEC_IOC_DETACH_USER_MEM \
|
|
+ _IOR(HANTRODEC_IOC_MAGIC, 37, user_memory_desc *)
|
|
+
|
|
+#define HANTRODEC_IOC_SYNC_USER_MEM_CACHE \
|
|
+ _IOR(HANTRODEC_IOC_MAGIC, 38, user_memory_desc *)
|
|
+
|
|
+#define HANTRODEC_IOC_MAXNR 38
|
|
|
|
#endif /* !_HANTRODEC_H_ */
|
|
diff --git a/drivers/staging/media/eswin/vdec/vdec_allocator.c b/drivers/staging/media/eswin/vdec/vdec_allocator.c
|
|
new file mode 100644
|
|
index 000000000000..f4a27d2e3894
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/eswin/vdec/vdec_allocator.c
|
|
@@ -0,0 +1,887 @@
|
|
+#include "vdec_allocator.h"
|
|
+#include <linux/version.h>
|
|
+#include <linux/scatterlist.h>
|
|
+
|
|
+#include <linux/slab.h>
|
|
+#include <linux/pagemap.h>
|
|
+#include <linux/cache.h>
|
|
+#include <linux/dma-mapping.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/errno.h>
|
|
+#include "hantrodec.h"
|
|
+#include "bidirect_list.h"
|
|
+
|
|
+#define LOG_TAG DEC_DEV_NAME ":alloc"
|
|
+#include "vc_drv_log.h"
|
|
+
|
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 20, 17) && \
|
|
+ !defined(CONFIG_ARCH_NO_SG_CHAIN)) || \
|
|
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) && \
|
|
+ (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN)))
|
|
+# define gcdUSE_LINUX_SG_TABLE_API 1
|
|
+#else
|
|
+# define gcdUSE_LINUX_SG_TABLE_API 0
|
|
+#endif
|
|
+
|
|
+#define gcdSUPPRESS_OOM_MESSAGE 1
|
|
+
|
|
+#if gcdSUPPRESS_OOM_MESSAGE
|
|
+# define gcdNOWARN __GFP_NOWARN
|
|
+#else
|
|
+# define gcdNOWARN 0
|
|
+#endif
|
|
+
|
|
+#define gcdUSING_PFN_FOLLOW 0
|
|
+
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
|
+# define current_mm_mmap_sem current->mm->mmap_lock
|
|
+#else
|
|
+# define current_mm_mmap_sem current->mm->mmap_sem
|
|
+#endif
|
|
+
|
|
+#ifndef untagged_addr
|
|
+# define untagged_addr(addr) (addr)
|
|
+#endif
|
|
+
|
|
+const static int g_iommu = 1;
|
|
+
|
|
+enum um_desc_type {
|
|
+ UM_PHYSICAL_MAP,
|
|
+ UM_PAGE_MAP,
|
|
+ UM_PFN_MAP,
|
|
+};
|
|
+
|
|
+/* Descriptor of a user memory imported. */
|
|
+struct um_desc {
|
|
+ int type;
|
|
+
|
|
+ union {
|
|
+ /* UM_PHYSICAL_MAP. */
|
|
+ unsigned long physical;
|
|
+
|
|
+ /* UM_PAGE_MAP. */
|
|
+ struct {
|
|
+ struct page **pages;
|
|
+ };
|
|
+
|
|
+ /* UM_PFN_MAP. */
|
|
+ struct {
|
|
+ unsigned long *pfns;
|
|
+ int *refs;
|
|
+ int pfns_valid;
|
|
+ };
|
|
+ };
|
|
+
|
|
+ struct sg_table sgt;
|
|
+
|
|
+ /* contiguous chunks, does not include padding pages. */
|
|
+ int chunk_count;
|
|
+
|
|
+ unsigned long vm_flags;
|
|
+ unsigned long user_vaddr;
|
|
+ size_t size;
|
|
+ unsigned long offset;
|
|
+ dma_addr_t dmaHandle;
|
|
+
|
|
+ size_t pageCount;
|
|
+ size_t extraPage;
|
|
+ unsigned int alloc_from_res;
|
|
+ struct device *dev;
|
|
+};
|
|
+
|
|
+static int _UserMemoryCache(struct um_desc *um, ES_CACHE_OPERATION Operation);
|
|
+
|
|
+static void *alloc_memory(size_t bytes)
|
|
+{
|
|
+ if (bytes > PAGE_SIZE)
|
|
+ return vzalloc(bytes);
|
|
+ else
|
|
+ return kzalloc(bytes, GFP_KERNEL | __GFP_NOWARN);
|
|
+}
|
|
+
|
|
+static void free_memory(void *ptr)
|
|
+{
|
|
+ if (is_vmalloc_addr(ptr))
|
|
+ vfree(ptr);
|
|
+ else
|
|
+ kfree(ptr);
|
|
+}
|
|
+
|
|
+#if 0
|
|
+static int import_physical_map(int iommu, struct device *dev,
|
|
+ struct um_desc *um, unsigned long phys)
|
|
+{
|
|
+ um->type = UM_PHYSICAL_MAP;
|
|
+ um->physical = phys & PAGE_MASK;
|
|
+ um->chunk_count = 1;
|
|
+
|
|
+ if (iommu) {
|
|
+ dma_addr_t dmaHandle;
|
|
+ size_t size = um->size + (phys & (~PAGE_MASK));
|
|
+ unsigned long pfn = phys >> PAGE_SHIFT;
|
|
+
|
|
+ if (pfn_valid(pfn))
|
|
+ dmaHandle = dma_map_page(dev, pfn_to_page(pfn),
|
|
+ 0, size, DMA_BIDIRECTIONAL);
|
|
+ else
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
|
|
+ dmaHandle = dma_map_resource(dev, pfn << PAGE_SHIFT,
|
|
+ size, DMA_BIDIRECTIONAL, 0);
|
|
+#else
|
|
+ dmaHandle = dma_map_page(dev, pfn_to_page(pfn),
|
|
+ 0, size, DMA_BIDIRECTIONAL);
|
|
+#endif
|
|
+
|
|
+ if (dma_mapping_error(dev, dmaHandle))
|
|
+ return -ENOMEM;
|
|
+
|
|
+ um->dmaHandle = dmaHandle;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static int
|
|
+import_page_map(struct device *dev, struct um_desc *um,
|
|
+ unsigned long addr, size_t page_count, size_t size, unsigned long flags)
|
|
+{
|
|
+ int i;
|
|
+ int result;
|
|
+ struct page **pages;
|
|
+#if 0
|
|
+ if ((addr & (cache_line_size() - 1)) || (size & (cache_line_size() - 1))) {
|
|
+ /* Not cpu cacheline size aligned, can not support. */
|
|
+ LOG_ERR("Not cpu cacheline size aligned, can not support. addr: %lx, size: %lu, cache_line_size: %d\n",
|
|
+ addr, size, cache_line_size());
|
|
+ return -EINVAL;
|
|
+ }
|
|
+#endif
|
|
+ pages = alloc_memory(page_count * sizeof(void *));
|
|
+ if (!pages)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ down_read(¤t_mm_mmap_sem);
|
|
+
|
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 6, 0)
|
|
+ result = pin_user_pages(addr & PAGE_MASK, page_count,
|
|
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
|
|
+ result = get_user_pages(current, current->mm, addr & PAGE_MASK, page_count,
|
|
+#else
|
|
+ result = get_user_pages(addr & PAGE_MASK, page_count,
|
|
+#endif
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) || defined(CONFIG_PPC)
|
|
+ (flags & VM_WRITE) ? FOLL_WRITE : 0,
|
|
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 1)
|
|
+ (flags & VM_WRITE) ? 1 : 0, 0,
|
|
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 168)
|
|
+ (flags & VM_WRITE) ? FOLL_WRITE : 0,
|
|
+#else
|
|
+ (flags & VM_WRITE) ? 1 : 0, 0,
|
|
+#endif
|
|
+
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
|
|
+ pages);
|
|
+#else
|
|
+ pages, NULL);
|
|
+#endif
|
|
+
|
|
+
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+
|
|
+ if (result < page_count) {
|
|
+ for (i = 0; i < result; i++) {
|
|
+ if (pages[i])
|
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 6, 0)
|
|
+ unpin_user_page(pages[i]);
|
|
+#else
|
|
+ put_page(pages[i]);
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ LOG_ERR("%s:%d:: result: %d, page count: %lu, addr: %lx\n", __func__, __LINE__, result, page_count, addr);
|
|
+ free_memory(pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ um->chunk_count = 1;
|
|
+ for (i = 1; i < page_count; i++) {
|
|
+ if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
|
|
+ ++um->chunk_count;
|
|
+ }
|
|
+
|
|
+ if (!um->alloc_from_res) {
|
|
+#if gcdUSE_LINUX_SG_TABLE_API
|
|
+ result = sg_alloc_table_from_pages(&um->sgt, pages, page_count,
|
|
+ addr & ~PAGE_MASK, size, GFP_KERNEL | gcdNOWARN);
|
|
+
|
|
+#else
|
|
+ result = alloc_sg_list_from_pages(&um->sgt.sgl, pages, page_count,
|
|
+ addr & ~PAGE_MASK, size, &um->sgt.nents);
|
|
+
|
|
+ um->sgt.orig_nents = um->sgt.nents;
|
|
+#endif
|
|
+ if (unlikely(result < 0)) {
|
|
+ LOG_WARN("%s: sg_alloc_table_from_pages failed\n", __func__);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ //result = dma_map_sgtable(dev, &um->sgt, DMA_BIDIRECTIONAL, 0);
|
|
+ result = dma_map_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_BIDIRECTIONAL);
|
|
+ if (g_iommu) {
|
|
+ um->dmaHandle = sg_dma_address(um->sgt.sgl);
|
|
+ }
|
|
+
|
|
+ dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
|
|
+ }
|
|
+
|
|
+ um->type = UM_PAGE_MAP;
|
|
+ um->pages = pages;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+error:
|
|
+ for (i = 0; i < page_count; i++) {
|
|
+ if (pages[i]) {
|
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 6, 0)
|
|
+ unpin_user_page(pages[i]);
|
|
+#else
|
|
+ put_page(pages[i]);
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+#if gcdUSE_LINUX_SG_TABLE_API
|
|
+ sg_free_table(&um->sgt);
|
|
+#else
|
|
+ kfree(um->sgt.sgl);
|
|
+#endif
|
|
+
|
|
+ free_memory(pages);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+import_pfn_map(struct device *dev, struct um_desc *um,
|
|
+ unsigned long addr, size_t pfn_count)
|
|
+{
|
|
+ int i;
|
|
+ struct vm_area_struct *vma;
|
|
+ unsigned long *pfns;
|
|
+ int *refs;
|
|
+ struct page **pages = NULL;
|
|
+ int result = 0;
|
|
+ size_t pageCount = 0;
|
|
+ unsigned int data = 0;
|
|
+
|
|
+ if (!current->mm)
|
|
+ return -ENOTTY;
|
|
+
|
|
+ down_read(¤t_mm_mmap_sem);
|
|
+ vma = find_vma(current->mm, addr);
|
|
+#if !gcdUSING_PFN_FOLLOW && (LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0))
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+#endif
|
|
+
|
|
+ if (!vma)
|
|
+ return -ENOTTY;
|
|
+
|
|
+ pfns = (unsigned long *)alloc_memory(pfn_count * sizeof(unsigned long));
|
|
+
|
|
+ if (!pfns)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ refs = (int *)alloc_memory(pfn_count * sizeof(int));
|
|
+
|
|
+ if (!refs) {
|
|
+ free_memory(pfns);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ pages = alloc_memory(pfn_count * sizeof(void *));
|
|
+ if (!pages) {
|
|
+ free_memory(pfns);
|
|
+ free_memory(refs);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < pfn_count; i++) {
|
|
+#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) {
|
|
+ /* Case maybe provides unmapped addr. */
|
|
+ data = *(unsigned int *)addr;
|
|
+ ret = follow_pfn(vma, addr, &pfns[i]);
|
|
+
|
|
+ if (ret < 0) {
|
|
+ up_read(¤t_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;
|
|
+ pte_t *pte;
|
|
+
|
|
+ pgd = pgd_offset(current->mm, addr);
|
|
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
|
|
+ goto err;
|
|
+
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
|
+ p4d = p4d_offset(pgd, addr);
|
|
+ if (p4d_none(READ_ONCE(*p4d)))
|
|
+ goto err;
|
|
+
|
|
+ pud = pud_offset(p4d, addr);
|
|
+# elif (defined(CONFIG_X86)) && LINUX_VERSION_CODE >= KERNEL_VERSION (4, 12, 0)
|
|
+ pud = pud_offset((p4d_t *)pgd, addr);
|
|
+# elif (defined(CONFIG_CPU_CSKYV2)) && LINUX_VERSION_CODE >= KERNEL_VERSION (4, 11, 0)
|
|
+ pud = pud_offset((p4d_t *)pgd, addr);
|
|
+# else
|
|
+ pud = pud_offset(pgd, addr);
|
|
+# endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) */
|
|
+ if (pud_none(*pud) || pud_bad(*pud))
|
|
+ goto err;
|
|
+
|
|
+ pmd = pmd_offset(pud, addr);
|
|
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
|
|
+ goto err;
|
|
+
|
|
+ //TODO: cannot be compiled for ko
|
|
+ pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
|
|
+
|
|
+ if (!pte_present(*pte)) {
|
|
+ if (pte)
|
|
+ pte_unmap_unlock(pte, ptl);
|
|
+
|
|
+ /* Case maybe provides unmapped addr. */
|
|
+ data = *(unsigned int*)addr;
|
|
+ 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
|
|
+ /* Advance to next. */
|
|
+ addr += PAGE_SIZE;
|
|
+ }
|
|
+#if gcdUSING_PFN_FOLLOW || (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+#endif
|
|
+
|
|
+ for (i = 0; i < pfn_count; i++) {
|
|
+ if (pfn_valid(pfns[i])) {
|
|
+ struct page *page = pfn_to_page(pfns[i]);
|
|
+
|
|
+ refs[i] = get_page_unless_zero(page);
|
|
+ pages[i] = page;
|
|
+ pageCount++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ um->chunk_count = 1;
|
|
+ for (i = 1; i < pfn_count; i++) {
|
|
+ if (pfns[i] != pfns[i - 1] + 1)
|
|
+ ++um->chunk_count;
|
|
+ }
|
|
+
|
|
+ um->pfns_valid = 0;
|
|
+ if (pageCount == pfn_count && !um->alloc_from_res) {
|
|
+#if gcdUSE_LINUX_SG_TABLE_API
|
|
+ result = sg_alloc_table_from_pages(&um->sgt, pages, pfn_count, addr & ~PAGE_MASK,
|
|
+ pfn_count * PAGE_SIZE, GFP_KERNEL | gcdNOWARN);
|
|
+
|
|
+#else
|
|
+ result = alloc_sg_list_from_pages(&um->sgt.sgl, pages, pfn_count, addr & ~PAGE_MASK,
|
|
+ pfn_count * PAGE_SIZE, &um->sgt.nents);
|
|
+
|
|
+ um->sgt.orig_nents = um->sgt.nents;
|
|
+#endif
|
|
+ if (unlikely(result < 0)) {
|
|
+ LOG_WARN("%s: sg_alloc_table_from_pages failed\n", __func__);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ result = dma_map_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
|
|
+
|
|
+ if (unlikely(result != um->sgt.nents)) {
|
|
+#if gcdUSE_LINUX_SG_TABLE_API
|
|
+ sg_free_table(&um->sgt);
|
|
+#else
|
|
+ kfree(um->sgt.sgl);
|
|
+#endif
|
|
+ LOG_WARN("%s: dma_map_sg failed\n", __func__);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ if (g_iommu)
|
|
+ um->dmaHandle = sg_dma_address(um->sgt.sgl);
|
|
+
|
|
+ um->pfns_valid = 1;
|
|
+ }
|
|
+
|
|
+ free_memory(pages);
|
|
+ pages = NULL;
|
|
+
|
|
+ um->type = UM_PFN_MAP;
|
|
+ um->pfns = pfns;
|
|
+ um->refs = refs;
|
|
+ return 0;
|
|
+
|
|
+err:
|
|
+ free_memory(pfns);
|
|
+ free_memory(refs);
|
|
+ free_memory(pages);
|
|
+
|
|
+ return -ENOTTY;
|
|
+}
|
|
+
|
|
+static int
|
|
+_Import(void* Memory, struct device *dev, size_t Size, struct um_desc *UserMemory)
|
|
+{
|
|
+ int status = 0;
|
|
+ unsigned long vm_flags = 0;
|
|
+ struct vm_area_struct *vma = NULL;
|
|
+ size_t start, end, memory;
|
|
+ int result = 0;
|
|
+ size_t extraPage, pageCount;
|
|
+
|
|
+ /* Verify the arguments. */
|
|
+ if (Memory == NULL || Size == 0) {
|
|
+ LOG_ERR("invalid param, Memory=%px, Size=%lu\n", Memory, Size);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ memory = untagged_addr((size_t)Memory);
|
|
+
|
|
+ /* Get the number of required pages. */
|
|
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
+ start = memory >> PAGE_SHIFT;
|
|
+ pageCount = end - start;
|
|
+
|
|
+ /* Allocate extra page to avoid cache overflow */
|
|
+ extraPage = 2;
|
|
+
|
|
+ LOG_DBG("%s(%d): pageCount: %lu. extraPage: %lu, Memory=%px Size=%lu\n",
|
|
+ __func__, __LINE__, pageCount, extraPage, Memory, Size);
|
|
+
|
|
+ /* Overflow. */
|
|
+ if ((memory + Size) < memory) {
|
|
+ LOG_ERR("overflow, %d", __LINE__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (memory) {
|
|
+ size_t vaddr = memory;
|
|
+
|
|
+ down_read(¤t_mm_mmap_sem);
|
|
+ vma = find_vma(current->mm, memory);
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+
|
|
+ if (!vma) {
|
|
+ /* No such memory, or across vmas. */
|
|
+ status = -EINVAL;
|
|
+ LOG_ERR("No such memory, or across vmas\n");
|
|
+ goto OnError;
|
|
+ }
|
|
+
|
|
+#ifdef CONFIG_ARM
|
|
+ /* coherent cache in case vivt or vipt-aliasing cache. */
|
|
+ __cpuc_flush_user_range(memory, memory + Size, vma->vm_flags);
|
|
+#endif
|
|
+
|
|
+ vm_flags = vma->vm_flags;
|
|
+ vaddr = vma->vm_end;
|
|
+
|
|
+ down_read(¤t_mm_mmap_sem);
|
|
+ while (vaddr < memory + Size) {
|
|
+ vma = find_vma(current->mm, vaddr);
|
|
+
|
|
+ if (!vma) {
|
|
+ /* No such memory. */
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+ status = -EINVAL;
|
|
+ LOG_ERR("No such memory\n");
|
|
+ goto OnError;
|
|
+ }
|
|
+
|
|
+ if ((vma->vm_flags & VM_PFNMAP) != (vm_flags & VM_PFNMAP)) {
|
|
+ /*
|
|
+ * Can not support different map type:
|
|
+ * both PFN and PAGE detected.
|
|
+ */
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+ status = -1;
|
|
+ LOG_ERR("Can not support different map type\n");
|
|
+ goto OnError;
|
|
+ }
|
|
+
|
|
+ vaddr = vma->vm_end;
|
|
+ }
|
|
+ up_read(¤t_mm_mmap_sem);
|
|
+ }
|
|
+
|
|
+ if (vm_flags & VM_PFNMAP)
|
|
+ result = import_pfn_map(dev, UserMemory, memory, pageCount);
|
|
+ else
|
|
+ result = import_page_map(dev, UserMemory, memory, pageCount, Size, vm_flags);
|
|
+
|
|
+
|
|
+ if (result < 0) {
|
|
+ status = result;
|
|
+ goto OnError;
|
|
+ }
|
|
+
|
|
+ UserMemory->vm_flags = vm_flags;
|
|
+ UserMemory->user_vaddr = (unsigned long)Memory;
|
|
+ UserMemory->size = Size;
|
|
+ UserMemory->offset = (memory & ~PAGE_MASK);
|
|
+ UserMemory->pageCount = pageCount;
|
|
+ UserMemory->extraPage = extraPage;
|
|
+ UserMemory->dev = dev;
|
|
+
|
|
+ /* Success. */
|
|
+ LOG_DBG("%s: success, user memory: %px, size: %lu, dma handle: %px, dev: %px\n",
|
|
+ __func__, Memory, Size, (void*)UserMemory->dmaHandle, dev);
|
|
+ return 0;
|
|
+
|
|
+OnError:
|
|
+ LOG_ERR("%s: return %d, user memory: %px, size: %lu, dev: %px\n",
|
|
+ __func__, status, Memory, Size, dev);
|
|
+ return status;
|
|
+}
|
|
+
|
|
+#if 0
|
|
+static int _GetUserMemroyPages(struct um_desc *userMemory) {
|
|
+ return userMemory->pageCount + userMemory->extraPage;
|
|
+}
|
|
+
|
|
+static int _UserMemoryContiguous(struct um_desc *userMemory) {
|
|
+ return (userMemory->chunk_count == 1) ? 1 : 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static int
|
|
+_UserMemoryAttach(struct device *dev, void* memory, size_t size, struct um_desc** umd)
|
|
+{
|
|
+ int status;
|
|
+ struct um_desc *userMemory = NULL;
|
|
+
|
|
+ /* Handle is meangless for this importer. */
|
|
+ if (!memory || !size || !umd) {
|
|
+ LOG_ERR("%s: invalid parameters\n", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ userMemory = alloc_memory(sizeof(struct um_desc));
|
|
+ if (!userMemory) {
|
|
+ status = -ENOMEM;
|
|
+ LOG_ERR("alloc memory um_desc failed\n");
|
|
+ goto OnError;
|
|
+ }
|
|
+
|
|
+ status = _Import(memory, dev, size, userMemory);
|
|
+ if (status) {
|
|
+ goto OnError;
|
|
+ }
|
|
+
|
|
+ *umd = userMemory;
|
|
+ return 0;
|
|
+
|
|
+OnError:
|
|
+ if (userMemory != NULL)
|
|
+ free_memory(userMemory);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+release_physical_map(struct um_desc *um)
|
|
+{
|
|
+ struct device *dev = um->dev;
|
|
+ if (g_iommu) {
|
|
+ unsigned long pfn = um->physical >> PAGE_SHIFT;
|
|
+ size_t size = um->size + um->offset;
|
|
+
|
|
+ if (pfn_valid(pfn))
|
|
+ dma_unmap_page(dev, um->dmaHandle, size, DMA_BIDIRECTIONAL);
|
|
+ else
|
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
|
|
+ dma_unmap_resource(dev, um->dmaHandle, size, DMA_BIDIRECTIONAL, 0);
|
|
+#else
|
|
+ dma_unmap_page(dev, um->dmaHandle, size, DMA_BIDIRECTIONAL);
|
|
+#endif
|
|
+
|
|
+ um->dmaHandle = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+release_page_map(struct um_desc *um)
|
|
+{
|
|
+ int i;
|
|
+ struct device *dev = um->dev;
|
|
+
|
|
+ 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_unmap_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
|
|
+
|
|
+ um->dmaHandle = 0;
|
|
+
|
|
+#if gcdUSE_LINUX_SG_TABLE_API
|
|
+ sg_free_table(&um->sgt);
|
|
+#else
|
|
+ kfree(um->sgt.sgl);
|
|
+#endif
|
|
+
|
|
+ for (i = 0; i < um->pageCount; i++) {
|
|
+ if (!PageReserved(um->pages[i]))
|
|
+ SetPageDirty(um->pages[i]);
|
|
+
|
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 6, 0)
|
|
+ unpin_user_page(um->pages[i]);
|
|
+#else
|
|
+ put_page(um->pages[i]);
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ free_memory(um->pages);
|
|
+}
|
|
+
|
|
+static void
|
|
+release_pfn_map(struct um_desc *um)
|
|
+{
|
|
+ int i;
|
|
+ struct device *dev = um->dev;
|
|
+
|
|
+ if (um->pfns_valid) {
|
|
+ dma_unmap_sg(dev, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
|
|
+
|
|
+#if gcdUSE_LINUX_SG_TABLE_API
|
|
+ sg_free_table(&um->sgt);
|
|
+#else
|
|
+ kfree(um->sgt.sgl);
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ um->dmaHandle = 0;
|
|
+
|
|
+ for (i = 0; i < um->pageCount; i++) {
|
|
+ if (pfn_valid(um->pfns[i])) {
|
|
+ struct page *page = pfn_to_page(um->pfns[i]);
|
|
+
|
|
+ if (!PageReserved(page))
|
|
+ SetPageDirty(page);
|
|
+
|
|
+ if (um->refs[i])
|
|
+ put_page(page);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ free_memory(um->pfns);
|
|
+ free_memory(um->refs);
|
|
+}
|
|
+
|
|
+static void
|
|
+_UserMemoryFree(struct um_desc* userMemory)
|
|
+{
|
|
+ if (userMemory) {
|
|
+ switch (userMemory->type) {
|
|
+ case UM_PHYSICAL_MAP:
|
|
+ release_physical_map(userMemory);
|
|
+ break;
|
|
+ case UM_PAGE_MAP:
|
|
+ release_page_map(userMemory);
|
|
+ break;
|
|
+ case UM_PFN_MAP:
|
|
+ release_pfn_map(userMemory);
|
|
+ break;
|
|
+ }
|
|
+ LOG_DBG("%s: dmaHandle %llx, size %lu\n", __func__, userMemory->dmaHandle, userMemory->size);
|
|
+ free_memory(userMemory);
|
|
+ }
|
|
+}
|
|
+
|
|
+int vdec_attach_user_memory(struct file *filp, struct device *dev, user_memory_desc *desc) {
|
|
+ int ret = 0;
|
|
+ bi_list_node* node = NULL;
|
|
+ struct um_desc* userMemory = NULL;
|
|
+ struct filp_priv *fp_priv = NULL;
|
|
+
|
|
+ if (!filp || !filp->private_data) {
|
|
+ LOG_ERR("%s:%d:: invalid param\n", __func__, __LINE__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ node = bi_list_create_node();
|
|
+ if (!node) {
|
|
+ LOG_ERR("create list node failed\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ ret = _UserMemoryAttach(dev, desc->memory, desc->size, &userMemory);
|
|
+ if (!ret) {
|
|
+ node->data = (void*)userMemory;
|
|
+ fp_priv = (struct filp_priv*)filp->private_data;
|
|
+ bi_list_insert_node_tail(&fp_priv->user_memory_list, node);
|
|
+
|
|
+ LOG_DBG("attach success, user memory: %px, size: %lu; output dmaHandle: %llx, size: %lu, dev: %px\n",
|
|
+ desc->memory, desc->size, userMemory->dmaHandle, userMemory->size, userMemory->dev);
|
|
+ desc->memory = (void*)userMemory->dmaHandle;
|
|
+ desc->size = userMemory->size;
|
|
+ } else {
|
|
+ bi_list_free_node(node);
|
|
+ LOG_ERR("%s failed, ret=%d\n", __func__, ret);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+bi_list_node *vdec_find_node(bi_list *list, user_memory_desc *desc) {
|
|
+ bi_list_node *node = NULL;
|
|
+ struct um_desc* userMemory = NULL;
|
|
+
|
|
+ node = list->head;
|
|
+ while (node) {
|
|
+ userMemory = (struct um_desc*)node->data;
|
|
+ if (userMemory->user_vaddr == (unsigned long)desc->memory) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ node = node->next;
|
|
+ }
|
|
+ return node;
|
|
+}
|
|
+
|
|
+int vdec_detach_user_memory(struct file *filp, user_memory_desc *desc) {
|
|
+ bi_list_node* node = NULL;
|
|
+ struct filp_priv *fp_priv = NULL;
|
|
+
|
|
+ if (!filp || !filp->private_data) {
|
|
+ LOG_ERR("%s:%d:: invalid param\n", __func__, __LINE__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ fp_priv = (struct filp_priv*)filp->private_data;
|
|
+ node = vdec_find_node(&fp_priv->user_memory_list, desc);
|
|
+ if (node) {
|
|
+ _UserMemoryFree((struct um_desc*)node->data);
|
|
+ bi_list_remove_node(&fp_priv->user_memory_list, node);
|
|
+ return 0;
|
|
+ } else {
|
|
+ LOG_DBG("%d: no memory node found, addr: %px, size: %lu\n", __LINE__, desc->memory, desc->size);
|
|
+ }
|
|
+
|
|
+ return -EFAULT;
|
|
+}
|
|
+
|
|
+void vdec_clean_user_memory(bi_list *list) {
|
|
+ bi_list_node *node = NULL;
|
|
+ bi_list_node *cur_node;
|
|
+
|
|
+ if (!list) {
|
|
+ LOG_ERR("%s:%d:: invalid param\n", __func__, __LINE__);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ node = list->head;
|
|
+ while (node) {
|
|
+ _UserMemoryFree((struct um_desc*)node->data);
|
|
+ cur_node = node;
|
|
+ node = node->next;
|
|
+ bi_list_free_node(cur_node);
|
|
+ }
|
|
+ list->head = list->tail = NULL;
|
|
+}
|
|
+
|
|
+static inline void
|
|
+_MemoryBarrier(void)
|
|
+{
|
|
+#if defined(CONFIG_ARM) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
|
|
+ dsb();
|
|
+#else
|
|
+ /* memory barrier */
|
|
+ mb();
|
|
+#endif
|
|
+}
|
|
+
|
|
+static int
|
|
+_UserMemoryCache(struct um_desc *um, ES_CACHE_OPERATION Operation)
|
|
+{
|
|
+ enum dma_data_direction dir;
|
|
+ struct device *dev = um->dev;
|
|
+
|
|
+ if (um->type == UM_PHYSICAL_MAP || um->alloc_from_res) {
|
|
+ _MemoryBarrier();
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (um->type == UM_PFN_MAP && um->pfns_valid == 0) {
|
|
+ _MemoryBarrier();
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+#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);
|
|
+#endif
|
|
+
|
|
+ LOG_DBG("sync cache, dev: %px, dmaHandle: %px, size: %lu, alloc: %u, opr: %d\n",
|
|
+ um->dev, (void*)um->dmaHandle, um->size, um->alloc_from_res, Operation);
|
|
+ switch (Operation) {
|
|
+ case ES_CACHE_CLEAN:
|
|
+ dir = DMA_TO_DEVICE;
|
|
+ dma_sync_sg_for_device(dev, um->sgt.sgl, um->sgt.nents, dir);
|
|
+ break;
|
|
+ case ES_CACHE_FLUSH:
|
|
+ dir = DMA_TO_DEVICE;
|
|
+ dma_sync_sg_for_device(dev, um->sgt.sgl, um->sgt.nents, dir);
|
|
+ dir = DMA_FROM_DEVICE;
|
|
+ dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, dir);
|
|
+ break;
|
|
+ case ES_CACHE_INVALIDATE:
|
|
+ dir = DMA_FROM_DEVICE;
|
|
+ dma_sync_sg_for_cpu(dev, um->sgt.sgl, um->sgt.nents, dir);
|
|
+ break;
|
|
+ default:
|
|
+ LOG_WARN("%d: invalid operatoin %d\n", __LINE__, Operation);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int vdec_sync_user_memory_cache(struct file *filp, user_memory_desc *desc, ES_CACHE_OPERATION opr) {
|
|
+ bi_list_node* node = NULL;
|
|
+ struct filp_priv *fp_priv = NULL;
|
|
+ int ret = -EFAULT;
|
|
+
|
|
+ if (!filp || !filp->private_data) {
|
|
+ LOG_ERR("%s:%d:: invalid param\n", __func__, __LINE__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ LOG_DBG("%s: memory=%px, size=%lu, nid: %u\n", __func__, desc->memory, desc->size, desc->nid);
|
|
+ fp_priv = (struct filp_priv*)filp->private_data;
|
|
+ node = vdec_find_node(&fp_priv->user_memory_list, desc);
|
|
+ if (node) {
|
|
+ ret = _UserMemoryCache((struct um_desc*)node->data, opr);
|
|
+ } else {
|
|
+ LOG_DBG("%d: no memory node found, addr: %px, size: %lu\n", __LINE__, desc->memory, desc->size);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/drivers/staging/media/eswin/vdec/vdec_allocator.h b/drivers/staging/media/eswin/vdec/vdec_allocator.h
|
|
new file mode 100644
|
|
index 000000000000..a41252b2f632
|
|
--- /dev/null
|
|
+++ b/drivers/staging/media/eswin/vdec/vdec_allocator.h
|
|
@@ -0,0 +1,20 @@
|
|
+#ifndef __VDEC_ALLOCATOR__H
|
|
+#define __VDEC_ALLOCATOR__H
|
|
+
|
|
+#include <linux/fs.h>
|
|
+#include "hantrodec.h"
|
|
+
|
|
+/* CPU cache operations */
|
|
+typedef enum _ES_CACHE_OPERATION {
|
|
+ ES_CACHE_CLEAN = 0x01, /* Flush CPU cache to mem */
|
|
+ ES_CACHE_INVALIDATE = 0x02, /* Invalidte CPU cache */
|
|
+ ES_CACHE_FLUSH = ES_CACHE_CLEAN | ES_CACHE_INVALIDATE, /* Both flush & invalidate */
|
|
+ ES_CACHE_MEMORY_BARRIER = 0x04,
|
|
+} ES_CACHE_OPERATION;
|
|
+
|
|
+int vdec_attach_user_memory(struct file *filp, struct device *dev, user_memory_desc *desc);
|
|
+int vdec_detach_user_memory(struct file *filp, user_memory_desc *desc);
|
|
+void vdec_clean_user_memory(bi_list *list);
|
|
+int vdec_sync_user_memory_cache(struct file *filp, user_memory_desc *desc, ES_CACHE_OPERATION opr);
|
|
+
|
|
+#endif
|
|
--
|
|
2.47.0
|
|
|