1 /*
2 * Copyright 2018 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <sys/mman.h>
19
20 #include "mpp_mem.h"
21 #include "mpp_debug.h"
22
23 #include "allocator_ext_dma.h"
24
25 typedef struct {
26 size_t alignment;
27 } allocator_ctx;
28
allocator_ext_dma_open(void ** ctx,MppAllocatorCfg * cfg)29 static MPP_RET allocator_ext_dma_open(void **ctx, MppAllocatorCfg *cfg)
30 {
31 MPP_RET ret = MPP_OK;
32 allocator_ctx *p = NULL;
33
34 if (NULL == ctx) {
35 mpp_err_f("do not accept NULL input\n");
36 return MPP_ERR_NULL_PTR;
37 }
38
39 p = mpp_malloc(allocator_ctx, 1);
40 if (NULL == p) {
41 mpp_err_f("failed to allocate context\n");
42 ret = MPP_ERR_MALLOC;
43 } else {
44 p->alignment = cfg->alignment;
45 }
46
47 *ctx = p;
48 return ret;
49 }
50
allocator_ext_dma_alloc(void * ctx,MppBufferInfo * info)51 static MPP_RET allocator_ext_dma_alloc(void *ctx, MppBufferInfo *info)
52 {
53 if (!ctx || !info) {
54 mpp_err_f("found NULL context input\n");
55 return MPP_ERR_VALUE;
56 }
57
58 return MPP_ERR_PERM;
59 }
60
allocator_ext_dma_free(void * ctx,MppBufferInfo * info)61 static MPP_RET allocator_ext_dma_free(void *ctx, MppBufferInfo *info)
62 {
63 if (!ctx || !info) {
64 mpp_err_f("found NULL context input\n");
65 return MPP_ERR_VALUE;
66 }
67
68 return MPP_ERR_PERM;
69 }
70
allocator_ext_dma_import(void * ctx,MppBufferInfo * info)71 static MPP_RET allocator_ext_dma_import(void *ctx, MppBufferInfo *info)
72 {
73 allocator_ctx *p = (allocator_ctx *)ctx;
74 mpp_assert(p);
75 mpp_assert(info->size);
76
77 if (info->ptr) {
78 mpp_err_f("The ext_dma is not used for userptr\n");
79 return MPP_ERR_VALUE;
80 }
81
82 return ((info->fd < 0) ? MPP_ERR_VALUE : MPP_OK);
83 }
84
allocator_ext_dma_mmap(void * ctx,MppBufferInfo * info)85 static MPP_RET allocator_ext_dma_mmap(void *ctx, MppBufferInfo *info)
86 {
87 void *ptr = NULL;
88 unsigned long offset = 0L;
89 mpp_assert(ctx);
90 mpp_assert(info->size);
91 mpp_assert(info->fd >= 0);
92
93 if (info->ptr)
94 return MPP_OK;
95
96 /*
97 * It is insecure to access the first memory page,
98 * usually system doesn't allow this behavior.
99 */
100 ptr = mmap(NULL, info->size, PROT_READ | PROT_WRITE,
101 MAP_SHARED, info->fd, offset);
102 if (ptr == MAP_FAILED)
103 return MPP_ERR_NULL_PTR;
104
105 info->ptr = ptr;
106
107 return MPP_OK;
108 }
109
allocator_ext_dma_release(void * ctx,MppBufferInfo * info)110 static MPP_RET allocator_ext_dma_release(void *ctx, MppBufferInfo *info)
111 {
112 mpp_assert(ctx);
113 mpp_assert(info->size);
114
115 if (info->ptr)
116 munmap(info->ptr, info->size);
117
118 info->ptr = NULL;
119 info->hnd = NULL;
120 info->fd = -1;
121 info->size = 0;
122
123 return MPP_OK;
124 }
125
allocator_ext_dma_close(void * ctx)126 static MPP_RET allocator_ext_dma_close(void *ctx)
127 {
128 if (ctx) {
129 mpp_free(ctx);
130 return MPP_OK;
131 }
132
133 mpp_err_f("found NULL context input\n");
134 return MPP_ERR_VALUE;
135 }
136
137 os_allocator allocator_ext_dma = {
138 .type = MPP_BUFFER_TYPE_EXT_DMA,
139 .open = allocator_ext_dma_open,
140 .close = allocator_ext_dma_close,
141 .alloc = allocator_ext_dma_alloc,
142 .free = allocator_ext_dma_free,
143 .import = allocator_ext_dma_import,
144 .release = allocator_ext_dma_release,
145 .mmap = allocator_ext_dma_mmap,
146 };
147