xref: /OK3568_Linux_fs/external/mpp/osal/allocator/allocator_ion.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2015 Rockchip Electronics Co. LTD
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun  * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun  * You may obtain a copy of the License at
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *      http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun  * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun  * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun  * limitations under the License.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define MODULE_TAG "mpp_ion"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <unistd.h>
20*4882a593Smuzhiyun #include <string.h>
21*4882a593Smuzhiyun #include <errno.h>
22*4882a593Smuzhiyun #include <fcntl.h>
23*4882a593Smuzhiyun #include <sys/ioctl.h>
24*4882a593Smuzhiyun #include <sys/mman.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #if defined(ARMLINUX)
27*4882a593Smuzhiyun #include <ion.h>
28*4882a593Smuzhiyun #else
29*4882a593Smuzhiyun #include "ion.h"
30*4882a593Smuzhiyun #endif
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "os_mem.h"
33*4882a593Smuzhiyun #include "allocator_ion.h"
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include "mpp_env.h"
36*4882a593Smuzhiyun #include "mpp_mem.h"
37*4882a593Smuzhiyun #include "mpp_debug.h"
38*4882a593Smuzhiyun #include "mpp_common.h"
39*4882a593Smuzhiyun #include "mpp_thread.h"
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun static RK_U32 ion_debug = 0;
42*4882a593Smuzhiyun static pthread_once_t once = PTHREAD_ONCE_INIT;
43*4882a593Smuzhiyun static pthread_mutex_t scandir_lock;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #define ION_FUNCTION                (0x00000001)
46*4882a593Smuzhiyun #define ION_DEVICE                  (0x00000002)
47*4882a593Smuzhiyun #define ION_CLINET                  (0x00000004)
48*4882a593Smuzhiyun #define ION_IOCTL                   (0x00000008)
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define ION_DETECT_IOMMU_DISABLE    (0x0)   /* use ION_HEAP_TYPE_DMA */
51*4882a593Smuzhiyun #define ION_DETECT_IOMMU_ENABLE     (0x1)   /* use ION_HEAP_TYPE_SYSTEM */
52*4882a593Smuzhiyun #define ION_DETECT_NO_DTS           (0x2)   /* use ION_HEAP_TYPE_CARVEOUT */
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define ion_dbg(flag, fmt, ...)     _mpp_dbg(ion_debug, flag, fmt, ## __VA_ARGS__)
55*4882a593Smuzhiyun #define ion_dbg_f(flag, fmt, ...)   _mpp_dbg_f(ion_debug, flag, fmt, ## __VA_ARGS__)
56*4882a593Smuzhiyun #define ion_dbg_func(fmt, ...)      ion_dbg_f(ION_FUNCTION, fmt, ## __VA_ARGS__)
57*4882a593Smuzhiyun 
ion_ioctl(int fd,int req,void * arg)58*4882a593Smuzhiyun static int ion_ioctl(int fd, int req, void *arg)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun     int ret = ioctl(fd, req, arg);
61*4882a593Smuzhiyun     if (ret < 0) {
62*4882a593Smuzhiyun         mpp_err("ion_ioctl %x failed with code %d: %s\n", req,
63*4882a593Smuzhiyun                 ret, strerror(errno));
64*4882a593Smuzhiyun         return -errno;
65*4882a593Smuzhiyun     }
66*4882a593Smuzhiyun     return ret;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
ion_alloc(int fd,size_t len,size_t align,unsigned int heap_mask,unsigned int flags,ion_user_handle_t * handle)69*4882a593Smuzhiyun static int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
70*4882a593Smuzhiyun                      unsigned int flags, ion_user_handle_t *handle)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun     int ret = -EINVAL;
73*4882a593Smuzhiyun     struct ion_allocation_data data = {
74*4882a593Smuzhiyun         .len = len,
75*4882a593Smuzhiyun         .align = align,
76*4882a593Smuzhiyun         .heap_id_mask = heap_mask,
77*4882a593Smuzhiyun         .flags = flags,
78*4882a593Smuzhiyun     };
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun     ion_dbg_func("enter: fd %d len %d align %d heap_mask %x flags %x",
81*4882a593Smuzhiyun                  fd, len, align, heap_mask, flags);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun     if (handle) {
84*4882a593Smuzhiyun         ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
85*4882a593Smuzhiyun         if (ret >= 0)
86*4882a593Smuzhiyun             *handle = data.handle;
87*4882a593Smuzhiyun     }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun     ion_dbg_func("leave: ret %d\n", ret);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun     return ret;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
ion_free(int fd,ion_user_handle_t handle)94*4882a593Smuzhiyun static int ion_free(int fd, ion_user_handle_t handle)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun     int ret;
97*4882a593Smuzhiyun     struct ion_handle_data data = {
98*4882a593Smuzhiyun         .handle = handle,
99*4882a593Smuzhiyun     };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun     ion_dbg_func("enter: fd %d\n", fd);
102*4882a593Smuzhiyun     ret = ion_ioctl(fd, ION_IOC_FREE, &data);
103*4882a593Smuzhiyun     ion_dbg_func("leave: ret %d\n", ret);
104*4882a593Smuzhiyun     return ret;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
ion_map_fd(int fd,ion_user_handle_t handle,int * map_fd)107*4882a593Smuzhiyun static int ion_map_fd(int fd, ion_user_handle_t handle, int *map_fd)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun     int ret;
110*4882a593Smuzhiyun     struct ion_fd_data data = {
111*4882a593Smuzhiyun         .handle = handle,
112*4882a593Smuzhiyun     };
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun     if (map_fd == NULL)
115*4882a593Smuzhiyun         return -EINVAL;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun     ret = ion_ioctl(fd, ION_IOC_MAP, &data);
118*4882a593Smuzhiyun     if (ret < 0)
119*4882a593Smuzhiyun         return ret;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun     *map_fd = data.fd;
122*4882a593Smuzhiyun     if (*map_fd < 0) {
123*4882a593Smuzhiyun         mpp_err("map ioctl returned negative fd\n");
124*4882a593Smuzhiyun         return -EINVAL;
125*4882a593Smuzhiyun     }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     return 0;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
ion_mmap(int fd,size_t length,int prot,int flags,off_t offset,void ** ptr)130*4882a593Smuzhiyun static int ion_mmap(int fd, size_t length, int prot, int flags, off_t offset,
131*4882a593Smuzhiyun                     void **ptr)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun     static unsigned long pagesize_mask = 0;
134*4882a593Smuzhiyun     if (ptr == NULL)
135*4882a593Smuzhiyun         return -EINVAL;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     if (!pagesize_mask)
138*4882a593Smuzhiyun         pagesize_mask = sysconf(_SC_PAGESIZE) - 1;
139*4882a593Smuzhiyun     offset = offset & (~pagesize_mask);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun     *ptr = mmap(NULL, length, prot, flags, fd, offset);
142*4882a593Smuzhiyun     if (*ptr == MAP_FAILED) {
143*4882a593Smuzhiyun         mpp_err("mmap failed: %s\n", strerror(errno));
144*4882a593Smuzhiyun         *ptr = NULL;
145*4882a593Smuzhiyun         return -errno;
146*4882a593Smuzhiyun     }
147*4882a593Smuzhiyun     return 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun #include <dirent.h>
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static const char *search_name = NULL;
153*4882a593Smuzhiyun 
_compare_name(const struct dirent * dir)154*4882a593Smuzhiyun static int _compare_name(const struct dirent *dir)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun     if (search_name && strstr(dir->d_name, search_name))
157*4882a593Smuzhiyun         return 1;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun     return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
scandir_lock_init(void)162*4882a593Smuzhiyun static void scandir_lock_init(void)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun     pthread_mutexattr_t attr;
165*4882a593Smuzhiyun     pthread_mutexattr_init(&attr);
166*4882a593Smuzhiyun     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
167*4882a593Smuzhiyun     pthread_mutex_init(&scandir_lock, &attr);
168*4882a593Smuzhiyun     pthread_mutexattr_destroy(&attr);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun /*
172*4882a593Smuzhiyun  * directory search function:
173*4882a593Smuzhiyun  * search directory with dir_name on path.
174*4882a593Smuzhiyun  * if found match dir append name on path and return
175*4882a593Smuzhiyun  *
176*4882a593Smuzhiyun  * return 0 for failure
177*4882a593Smuzhiyun  * return positive value for length of new path
178*4882a593Smuzhiyun  */
find_dir_in_path(char * path,const char * dir_name,size_t max_length)179*4882a593Smuzhiyun static RK_S32 find_dir_in_path(char *path, const char *dir_name,
180*4882a593Smuzhiyun                                size_t max_length)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun     struct dirent **dir;
183*4882a593Smuzhiyun     RK_S32 path_len = strnlen(path, max_length);
184*4882a593Smuzhiyun     RK_S32 new_path_len = 0;
185*4882a593Smuzhiyun     RK_S32 n;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun     pthread_once(&once, scandir_lock_init);
188*4882a593Smuzhiyun     pthread_mutex_lock(&scandir_lock);
189*4882a593Smuzhiyun     search_name = dir_name;
190*4882a593Smuzhiyun     n = scandir(path, &dir, _compare_name, alphasort);
191*4882a593Smuzhiyun     if (n <= 0) {
192*4882a593Smuzhiyun         mpp_log("scan %s for %s return %d\n", path, dir_name, n);
193*4882a593Smuzhiyun     } else {
194*4882a593Smuzhiyun         mpp_assert(n == 1);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun         new_path_len = path_len;
197*4882a593Smuzhiyun         new_path_len += snprintf(path + path_len, max_length - path_len - 1,
198*4882a593Smuzhiyun                                  "/%s", dir[0]->d_name);
199*4882a593Smuzhiyun         free(dir[0]);
200*4882a593Smuzhiyun         free(dir);
201*4882a593Smuzhiyun     }
202*4882a593Smuzhiyun     search_name = NULL;
203*4882a593Smuzhiyun     pthread_mutex_unlock(&scandir_lock);
204*4882a593Smuzhiyun     return new_path_len;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun #define MAX_PATH_NAME_SIZE  256
208*4882a593Smuzhiyun 
check_sysfs_iommu()209*4882a593Smuzhiyun static RK_S32 check_sysfs_iommu()
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun     RK_U32 i = 0;
212*4882a593Smuzhiyun     RK_U32 dts_info_found = 0;
213*4882a593Smuzhiyun     RK_U32 ion_info_found = 0;
214*4882a593Smuzhiyun     RK_S32 ret = ION_DETECT_IOMMU_DISABLE;
215*4882a593Smuzhiyun     char path[MAX_PATH_NAME_SIZE];
216*4882a593Smuzhiyun     static char *dts_devices[] = {
217*4882a593Smuzhiyun         "vpu_service",
218*4882a593Smuzhiyun         "hevc_service",
219*4882a593Smuzhiyun         "rkvdec",
220*4882a593Smuzhiyun         "rkvenc",
221*4882a593Smuzhiyun         "vpu_combo",
222*4882a593Smuzhiyun     };
223*4882a593Smuzhiyun     static char *system_heaps[] = {
224*4882a593Smuzhiyun         "vmalloc",
225*4882a593Smuzhiyun         "system-heap",
226*4882a593Smuzhiyun     };
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun     mpp_env_get_u32("ion_debug", &ion_debug, 0);
229*4882a593Smuzhiyun #ifdef SOFIA_3GR_LINUX
230*4882a593Smuzhiyun     return ret;
231*4882a593Smuzhiyun #endif
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun     for (i = 0; i < MPP_ARRAY_ELEMS(dts_devices); i++) {
234*4882a593Smuzhiyun         snprintf(path, sizeof(path), "/proc/device-tree");
235*4882a593Smuzhiyun         if (find_dir_in_path(path, dts_devices[i], sizeof(path))) {
236*4882a593Smuzhiyun             if (find_dir_in_path(path, "iommu_enabled", sizeof(path))) {
237*4882a593Smuzhiyun                 FILE *iommu_fp = fopen(path, "rb");
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun                 if (iommu_fp) {
240*4882a593Smuzhiyun                     RK_U32 iommu_enabled = 0;
241*4882a593Smuzhiyun                     if (fread(&iommu_enabled, sizeof(RK_U32), 1, iommu_fp))
242*4882a593Smuzhiyun                         mpp_log("%s iommu_enabled %d\n", dts_devices[i],
243*4882a593Smuzhiyun                                 (iommu_enabled > 0));
244*4882a593Smuzhiyun                     fclose(iommu_fp);
245*4882a593Smuzhiyun                     if (iommu_enabled)
246*4882a593Smuzhiyun                         ret = ION_DETECT_IOMMU_ENABLE;
247*4882a593Smuzhiyun                 }
248*4882a593Smuzhiyun                 dts_info_found = 1;
249*4882a593Smuzhiyun                 break;
250*4882a593Smuzhiyun             }
251*4882a593Smuzhiyun         }
252*4882a593Smuzhiyun     }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun     if (!dts_info_found) {
255*4882a593Smuzhiyun         for (i = 0; i < MPP_ARRAY_ELEMS(system_heaps); i++) {
256*4882a593Smuzhiyun             snprintf(path, sizeof(path), "/sys/kernel/debug/ion/heaps");
257*4882a593Smuzhiyun             if (find_dir_in_path(path, system_heaps[i], sizeof(path))) {
258*4882a593Smuzhiyun                 mpp_log("%s found\n", system_heaps[i]);
259*4882a593Smuzhiyun                 ret = ION_DETECT_IOMMU_ENABLE;
260*4882a593Smuzhiyun                 ion_info_found = 1;
261*4882a593Smuzhiyun                 break;
262*4882a593Smuzhiyun             }
263*4882a593Smuzhiyun         }
264*4882a593Smuzhiyun     }
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun     if (!dts_info_found && !ion_info_found) {
267*4882a593Smuzhiyun         mpp_err("can not find any hint from all possible devices\n");
268*4882a593Smuzhiyun         ret = ION_DETECT_NO_DTS;
269*4882a593Smuzhiyun     }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun     return ret;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun typedef struct {
275*4882a593Smuzhiyun     RK_U32  alignment;
276*4882a593Smuzhiyun     RK_S32  ion_device;
277*4882a593Smuzhiyun } allocator_ctx_ion;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun static const char *dev_ion = "/dev/ion";
280*4882a593Smuzhiyun static RK_S32 ion_heap_id = -1;
281*4882a593Smuzhiyun static RK_U32 ion_heap_mask = (1 << ION_HEAP_TYPE_SYSTEM);
282*4882a593Smuzhiyun static pthread_mutex_t lock;
283*4882a593Smuzhiyun 
allocator_ion_open(void ** ctx,MppAllocatorCfg * cfg)284*4882a593Smuzhiyun static MPP_RET allocator_ion_open(void **ctx, MppAllocatorCfg *cfg)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun     RK_S32 fd;
287*4882a593Smuzhiyun     allocator_ctx_ion *p;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun     if (NULL == ctx) {
290*4882a593Smuzhiyun         mpp_err("os_allocator_open Android do not accept NULL input\n");
291*4882a593Smuzhiyun         return MPP_ERR_NULL_PTR;
292*4882a593Smuzhiyun     }
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun     *ctx = NULL;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun     fd = open(dev_ion, O_RDWR | O_CLOEXEC);
297*4882a593Smuzhiyun     if (fd < 0) {
298*4882a593Smuzhiyun         mpp_err("open %s failed!\n", dev_ion);
299*4882a593Smuzhiyun         return MPP_ERR_UNKNOW;
300*4882a593Smuzhiyun     }
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun     ion_dbg(ION_DEVICE, "open ion dev fd %d\n", fd);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun     p = mpp_malloc(allocator_ctx_ion, 1);
305*4882a593Smuzhiyun     if (NULL == p) {
306*4882a593Smuzhiyun         close(fd);
307*4882a593Smuzhiyun         mpp_err("os_allocator_open Android failed to allocate context\n");
308*4882a593Smuzhiyun         return MPP_ERR_MALLOC;
309*4882a593Smuzhiyun     } else {
310*4882a593Smuzhiyun         /*
311*4882a593Smuzhiyun          * do heap id detection here:
312*4882a593Smuzhiyun          * if there is no vpu_service use default ION_HEAP_TYPE_SYSTEM_CONTIG
313*4882a593Smuzhiyun          * if there is vpu_service then check the iommu_enable status
314*4882a593Smuzhiyun          */
315*4882a593Smuzhiyun         pthread_mutex_lock(&lock);
316*4882a593Smuzhiyun         if (ion_heap_id < 0) {
317*4882a593Smuzhiyun             int detect_result = check_sysfs_iommu();
318*4882a593Smuzhiyun             const char *heap_name = NULL;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun             switch (detect_result) {
321*4882a593Smuzhiyun             case ION_DETECT_IOMMU_DISABLE : {
322*4882a593Smuzhiyun                 ion_heap_mask   = (1 << ION_HEAP_TYPE_DMA);
323*4882a593Smuzhiyun                 ion_heap_id     = ION_HEAP_TYPE_DMA;
324*4882a593Smuzhiyun                 heap_name = "ION_HEAP_TYPE_DMA";
325*4882a593Smuzhiyun             } break;
326*4882a593Smuzhiyun             case ION_DETECT_IOMMU_ENABLE : {
327*4882a593Smuzhiyun                 ion_heap_mask   = (1 << ION_HEAP_TYPE_SYSTEM);
328*4882a593Smuzhiyun                 ion_heap_id     = ION_HEAP_TYPE_SYSTEM;
329*4882a593Smuzhiyun                 heap_name = "ION_HEAP_TYPE_SYSTEM";
330*4882a593Smuzhiyun             } break;
331*4882a593Smuzhiyun             case ION_DETECT_NO_DTS : {
332*4882a593Smuzhiyun                 ion_heap_mask   = (1 << ION_HEAP_TYPE_CARVEOUT);
333*4882a593Smuzhiyun                 ion_heap_id     = ION_HEAP_TYPE_CARVEOUT;
334*4882a593Smuzhiyun                 heap_name = "ION_HEAP_TYPE_CARVEOUT";
335*4882a593Smuzhiyun             } break;
336*4882a593Smuzhiyun             default : {
337*4882a593Smuzhiyun                 mpp_err("invalid detect result %d\n", detect_result);
338*4882a593Smuzhiyun                 ion_heap_mask   = (1 << ION_HEAP_TYPE_DMA);
339*4882a593Smuzhiyun                 ion_heap_id     = ION_HEAP_TYPE_DMA;
340*4882a593Smuzhiyun                 heap_name = "ION_HEAP_TYPE_DMA";
341*4882a593Smuzhiyun             } break;
342*4882a593Smuzhiyun             }
343*4882a593Smuzhiyun             mpp_log("using ion heap %s\n", heap_name);
344*4882a593Smuzhiyun         }
345*4882a593Smuzhiyun         pthread_mutex_unlock(&lock);
346*4882a593Smuzhiyun         p->alignment    = cfg->alignment;
347*4882a593Smuzhiyun         p->ion_device   = fd;
348*4882a593Smuzhiyun         *ctx = p;
349*4882a593Smuzhiyun     }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun     return MPP_OK;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
allocator_ion_alloc(void * ctx,MppBufferInfo * info)354*4882a593Smuzhiyun static MPP_RET allocator_ion_alloc(void *ctx, MppBufferInfo *info)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun     MPP_RET ret = MPP_OK;
357*4882a593Smuzhiyun     int fd = -1;
358*4882a593Smuzhiyun     ion_user_handle_t hnd = -1;
359*4882a593Smuzhiyun     allocator_ctx_ion *p = NULL;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun     if (NULL == ctx) {
362*4882a593Smuzhiyun         mpp_err("os_allocator_close Android do not accept NULL input\n");
363*4882a593Smuzhiyun         return MPP_ERR_NULL_PTR;
364*4882a593Smuzhiyun     }
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun     ion_dbg_func("enter: ctx %p size %d\n", ctx, info->size);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun     p = (allocator_ctx_ion *)ctx;
369*4882a593Smuzhiyun     ret = ion_alloc(p->ion_device, info->size, p->alignment, ion_heap_mask,
370*4882a593Smuzhiyun                     0, &hnd);
371*4882a593Smuzhiyun     if (ret)
372*4882a593Smuzhiyun         mpp_err_f("ion_alloc failed ret %d\n", ret);
373*4882a593Smuzhiyun     else {
374*4882a593Smuzhiyun         ret = ion_map_fd(p->ion_device, hnd, &fd);
375*4882a593Smuzhiyun         if (ret)
376*4882a593Smuzhiyun             mpp_err_f("ion_map_fd failed ret %d\n", ret);
377*4882a593Smuzhiyun     }
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun     info->fd  = fd;
380*4882a593Smuzhiyun     info->ptr = NULL;
381*4882a593Smuzhiyun     info->hnd = (void *)(intptr_t)hnd;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun     ion_dbg_func("leave: ret %d handle %d fd %d\n", ret, hnd, fd);
384*4882a593Smuzhiyun     return ret;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
allocator_ion_import(void * ctx,MppBufferInfo * data)387*4882a593Smuzhiyun static MPP_RET allocator_ion_import(void *ctx, MppBufferInfo *data)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun     MPP_RET ret = MPP_NOK;
390*4882a593Smuzhiyun     allocator_ctx_ion *p = (allocator_ctx_ion *)ctx;
391*4882a593Smuzhiyun     struct ion_fd_data fd_data;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     ion_dbg_func("enter: ctx %p dev %d fd %d size %d\n",
394*4882a593Smuzhiyun                  ctx, p->ion_device, data->fd, data->size);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun     fd_data.fd = data->fd;
397*4882a593Smuzhiyun     ret = ion_ioctl(p->ion_device, ION_IOC_IMPORT, &fd_data);
398*4882a593Smuzhiyun     if (0 > fd_data.handle) {
399*4882a593Smuzhiyun         mpp_err_f("fd %d import failed for %s\n", data->fd, strerror(errno));
400*4882a593Smuzhiyun         goto RET;
401*4882a593Smuzhiyun     }
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun     data->hnd = (void *)(intptr_t)fd_data.handle;
404*4882a593Smuzhiyun     ret = ion_map_fd(p->ion_device, fd_data.handle, &data->fd);
405*4882a593Smuzhiyun     data->ptr = NULL;
406*4882a593Smuzhiyun RET:
407*4882a593Smuzhiyun     ion_dbg_func("leave: ret %d handle %d\n", ret, data->hnd);
408*4882a593Smuzhiyun     return ret;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
allocator_ion_mmap(void * ctx,MppBufferInfo * data)411*4882a593Smuzhiyun static MPP_RET allocator_ion_mmap(void *ctx, MppBufferInfo *data)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun     MPP_RET ret = MPP_OK;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun     if (NULL == ctx) {
416*4882a593Smuzhiyun         mpp_err_f("do not accept NULL input\n");
417*4882a593Smuzhiyun         return MPP_ERR_NULL_PTR;
418*4882a593Smuzhiyun     }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     ion_dbg_func("enter: ctx %p fd %d size %d\n", ctx, data->fd, data->size);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun     if (NULL == data->ptr)
423*4882a593Smuzhiyun         ret = ion_mmap(data->fd, data->size, PROT_READ | PROT_WRITE,
424*4882a593Smuzhiyun                        MAP_SHARED, 0, &data->ptr);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun     ion_dbg_func("leave: ret %d ptr %p\n", ret, data->ptr);
427*4882a593Smuzhiyun     return ret;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun 
allocator_ion_free(void * ctx,MppBufferInfo * data)430*4882a593Smuzhiyun static MPP_RET allocator_ion_free(void *ctx, MppBufferInfo *data)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun     allocator_ctx_ion *p = NULL;
433*4882a593Smuzhiyun     if (NULL == ctx) {
434*4882a593Smuzhiyun         mpp_err_f("do not accept NULL input\n");
435*4882a593Smuzhiyun         return MPP_ERR_NULL_PTR;
436*4882a593Smuzhiyun     }
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun     ion_dbg_func("enter: ctx %p fd %d ptr %p size %d\n",
439*4882a593Smuzhiyun                  ctx, data->fd, data->ptr, data->size);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun     p = (allocator_ctx_ion *)ctx;
442*4882a593Smuzhiyun     if (data->ptr) {
443*4882a593Smuzhiyun         munmap(data->ptr, data->size);
444*4882a593Smuzhiyun         data->ptr = NULL;
445*4882a593Smuzhiyun     }
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun     if (data->fd > 0) {
448*4882a593Smuzhiyun         close(data->fd);
449*4882a593Smuzhiyun         data->fd = -1;
450*4882a593Smuzhiyun     }
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun     if (data->hnd) {
453*4882a593Smuzhiyun         ion_free(p->ion_device, (ion_user_handle_t)((intptr_t)data->hnd));
454*4882a593Smuzhiyun         data->hnd = NULL;
455*4882a593Smuzhiyun     }
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun     ion_dbg_func("leave\n");
458*4882a593Smuzhiyun     return MPP_OK;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
allocator_ion_close(void * ctx)461*4882a593Smuzhiyun static MPP_RET allocator_ion_close(void *ctx)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun     int ret;
464*4882a593Smuzhiyun     allocator_ctx_ion *p;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun     if (NULL == ctx) {
467*4882a593Smuzhiyun         mpp_err("os_allocator_close Android do not accept NULL input\n");
468*4882a593Smuzhiyun         return MPP_ERR_NULL_PTR;
469*4882a593Smuzhiyun     }
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun     ion_dbg_func("enter: ctx\n", ctx);
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun     p = (allocator_ctx_ion *)ctx;
474*4882a593Smuzhiyun     ret = close(p->ion_device);
475*4882a593Smuzhiyun     mpp_free(p);
476*4882a593Smuzhiyun     if (ret < 0)
477*4882a593Smuzhiyun         ret = (MPP_RET) - errno;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun     ion_dbg_func("leave: ret %d\n", ret);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun     return ret;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun os_allocator allocator_ion = {
485*4882a593Smuzhiyun     .type = MPP_BUFFER_TYPE_ION,
486*4882a593Smuzhiyun     .open = allocator_ion_open,
487*4882a593Smuzhiyun     .close = allocator_ion_close,
488*4882a593Smuzhiyun     .alloc = allocator_ion_alloc,
489*4882a593Smuzhiyun     .free = allocator_ion_free,
490*4882a593Smuzhiyun     .import = allocator_ion_import,
491*4882a593Smuzhiyun     .release = allocator_ion_free,
492*4882a593Smuzhiyun     .mmap = allocator_ion_mmap,
493*4882a593Smuzhiyun };
494*4882a593Smuzhiyun 
495