1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2018 Rockchip Electronics Co., Ltd.
4 */
5
6 #include <stdio.h>
7 #include <sys/mman.h>
8
9 #include "mpp_mem.h"
10 #include "mpp_debug.h"
11 #include "mpp_common.h"
12
13 #include "allocator_ext_dma.h"
14
15 typedef struct {
16 size_t alignment;
17 MppAllocFlagType flags;
18 } allocator_ctx;
19
allocator_ext_dma_open(void ** ctx,size_t alignment,MppAllocFlagType flags)20 static MPP_RET allocator_ext_dma_open(void **ctx, size_t alignment, MppAllocFlagType flags)
21 {
22 MPP_RET ret = MPP_OK;
23 allocator_ctx *p = NULL;
24
25 if (NULL == ctx) {
26 mpp_err_f("do not accept NULL input\n");
27 return MPP_ERR_NULL_PTR;
28 }
29
30 p = mpp_malloc(allocator_ctx, 1);
31 if (NULL == p) {
32 mpp_err_f("failed to allocate context\n");
33 ret = MPP_ERR_MALLOC;
34 } else {
35 p->alignment = alignment;
36 p->flags = flags;
37 }
38
39 *ctx = p;
40 return ret;
41 }
42
allocator_ext_dma_alloc(void * ctx,MppBufferInfo * info)43 static MPP_RET allocator_ext_dma_alloc(void *ctx, MppBufferInfo *info)
44 {
45 if (!ctx || !info) {
46 mpp_err_f("found NULL context input\n");
47 return MPP_ERR_VALUE;
48 }
49
50 return MPP_ERR_PERM;
51 }
52
allocator_ext_dma_free(void * ctx,MppBufferInfo * info)53 static MPP_RET allocator_ext_dma_free(void *ctx, MppBufferInfo *info)
54 {
55 if (!ctx || !info) {
56 mpp_err_f("found NULL context input\n");
57 return MPP_ERR_VALUE;
58 }
59
60 return MPP_ERR_PERM;
61 }
62
allocator_ext_dma_import(void * ctx,MppBufferInfo * info)63 static MPP_RET allocator_ext_dma_import(void *ctx, MppBufferInfo *info)
64 {
65 allocator_ctx *p = (allocator_ctx *)ctx;
66 mpp_assert(p);
67 mpp_assert(info->size);
68
69 if (info->ptr) {
70 mpp_err_f("The ext_dma is not used for userptr\n");
71 return MPP_ERR_VALUE;
72 }
73
74 return ((info->fd < 0) ? MPP_ERR_VALUE : MPP_OK);
75 }
76
allocator_ext_dma_mmap(void * ctx,MppBufferInfo * info)77 static MPP_RET allocator_ext_dma_mmap(void *ctx, MppBufferInfo *info)
78 {
79 void *ptr = NULL;
80 int flags = 0;
81 unsigned long offset = 0L;
82 mpp_assert(ctx);
83 mpp_assert(info->size);
84 mpp_assert(info->fd >= 0);
85
86 if (info->ptr)
87 return MPP_OK;
88
89 /*
90 * It is insecure to access the first memory page,
91 * usually system doesn't allow this behavior.
92 */
93 flags = PROT_READ;
94 if (fcntl(info->fd, F_GETFL) & O_RDWR)
95 flags |= PROT_WRITE;
96
97 ptr = mmap(NULL, info->size, flags, MAP_SHARED, info->fd, offset);
98 if (ptr == MAP_FAILED)
99 return MPP_ERR_NULL_PTR;
100
101 info->ptr = ptr;
102
103 return MPP_OK;
104 }
105
allocator_ext_dma_release(void * ctx,MppBufferInfo * info)106 static MPP_RET allocator_ext_dma_release(void *ctx, MppBufferInfo *info)
107 {
108 mpp_assert(ctx);
109 mpp_assert(info->size);
110
111 if (info->ptr)
112 munmap(info->ptr, info->size);
113
114 info->ptr = NULL;
115 info->hnd = NULL;
116 info->fd = -1;
117 info->size = 0;
118
119 return MPP_OK;
120 }
121
allocator_ext_dma_close(void * ctx)122 static MPP_RET allocator_ext_dma_close(void *ctx)
123 {
124 if (ctx) {
125 mpp_free(ctx);
126 return MPP_OK;
127 }
128
129 mpp_err_f("found NULL context input\n");
130 return MPP_ERR_VALUE;
131 }
132
os_allocator_ext_dma_flags(void * ctx)133 static MppAllocFlagType os_allocator_ext_dma_flags(void *ctx)
134 {
135 allocator_ctx *p = (allocator_ctx *)ctx;
136
137 return p ? (MppAllocFlagType)p->flags : MPP_ALLOC_FLAG_NONE;
138 }
139
140 os_allocator allocator_ext_dma = {
141 .type = MPP_BUFFER_TYPE_EXT_DMA,
142 .name = "ext_dma",
143 .open = allocator_ext_dma_open,
144 .close = allocator_ext_dma_close,
145 .alloc = allocator_ext_dma_alloc,
146 .free = allocator_ext_dma_free,
147 .import = allocator_ext_dma_import,
148 .release = allocator_ext_dma_release,
149 .mmap = allocator_ext_dma_mmap,
150 .flags = os_allocator_ext_dma_flags,
151 };
152