1 /* Copyright 2020 Rockchip Electronics Co. LTD
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #undef DBG_MOD_ID
17 #define DBG_MOD_ID RK_ID_MB
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <cstring>
22 #include <vector>
23
24 #include "rk_debug.h"
25 #include "rk_mpi_mb.h"
26 #include "rk_mpi_sys.h"
27
28 #include "test_comm_argparse.h"
29
30 #define MB_POOL_COUNT 10
31 #define MB_POOL_MB_COUNT 10
32 #define MB_POOL_MB_SIZE 1280 * 720 * 2
33
34 typedef struct _rkTestMbCtx {
35 RK_S32 s32MbCount;
36 RK_S32 s32MbSize;
37 RK_S32 s32PoolCount;
38 RK_S32 s32LoopCount;
39 RK_BOOL bExternal;
40 RK_BOOL bPreAlloc;
41 RK_S32 s32RemapMode;
42 RK_S32 s32AllocType;
43 } TEST_MB_CTX_S;
44
unit_test_mpi_mb(const TEST_MB_CTX_S * pstCtx)45 RK_S32 unit_test_mpi_mb(const TEST_MB_CTX_S *pstCtx) {
46 MB_POOL_CONFIG_S pstMbPoolCfg;
47 std::vector<MB_BLK> vector;
48 std::vector<MB_BLK>::iterator iter;
49 RK_S32 s32Ret = RK_SUCCESS;
50 RK_S32 loopCount = pstCtx->s32LoopCount;
51 RK_S32 s32UniqueId = -1;
52 RK_S32 s32DupFd = -1;
53
54 memset(&pstMbPoolCfg, 0, sizeof(MB_POOL_CONFIG_S));
55 pstMbPoolCfg.u64MBSize = pstCtx->s32MbSize;
56 pstMbPoolCfg.u32MBCnt = pstCtx->s32MbCount;
57 pstMbPoolCfg.bPreAlloc = pstCtx->bPreAlloc;
58 pstMbPoolCfg.enRemapMode = (MB_REMAP_MODE_E)pstCtx->s32RemapMode;
59 pstMbPoolCfg.enAllocType = (MB_ALLOC_TYPE_E)pstCtx->s32AllocType;
60
61 do {
62 for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
63 MB_POOL pool = RK_MPI_MB_CreatePool(&pstMbPoolCfg);
64 if (pool == MB_INVALID_POOLID) {
65 s32Ret = RK_ERR_MB_2MPOOLS;
66 goto __FAILED;
67 }
68 RK_LOGI("pool id %d", pool);
69 }
70
71 for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
72 vector.clear();
73 for (RK_S32 j = 0; j < pstCtx->s32MbCount; j++) {
74 MB_BLK mb = RK_MPI_MB_GetMB(i, pstMbPoolCfg.u64MBSize, RK_FALSE);
75 if (mb == MB_INVALID_HANDLE) {
76 s32Ret = RK_ERR_MB_NOBUF;
77 goto __FAILED;
78 }
79 RK_U64 phyAddr = RK_MPI_MB_Handle2PhysAddr(mb);
80 if (pstMbPoolCfg.enDmaType == MB_DMA_TYPE_CMA
81 && pstMbPoolCfg.enAllocType == MB_ALLOC_TYPE_DMA
82 && phyAddr == 0) {
83 s32Ret = RK_ERR_MB_BUSY;
84 RK_MPI_MB_ReleaseMB(mb);
85 goto __FAILED;
86 }
87 MB_POOL poolId = RK_MPI_MB_Handle2PoolId(mb);
88 if (poolId != i) {
89 s32Ret = RK_ERR_MB_BUSY;
90 RK_MPI_MB_ReleaseMB(mb);
91 goto __FAILED;
92 }
93 RK_S32 refsCount = RK_MPI_MB_InquireUserCnt(mb);
94 if (refsCount != 1) {
95 s32Ret = RK_ERR_MB_BUSY;
96 RK_MPI_MB_ReleaseMB(mb);
97 goto __FAILED;
98 }
99 RK_VOID *virAddr = RK_MPI_MB_Handle2VirAddr(mb);
100 if (virAddr == RK_NULL) {
101 s32Ret = RK_ERR_MB_BUSY;
102 RK_MPI_MB_ReleaseMB(mb);
103 goto __FAILED;
104 }
105 RK_S32 fd = RK_MPI_MB_Handle2Fd(mb);
106 if (pstMbPoolCfg.enAllocType == MB_ALLOC_TYPE_DMA
107 && fd < 0) {
108 s32Ret = RK_ERR_MB_BUSY;
109 RK_MPI_MB_ReleaseMB(mb);
110 goto __FAILED;
111 }
112 if (pstMbPoolCfg.enAllocType == MB_ALLOC_TYPE_DMA) {
113 if (RK_MPI_MB_VirAddr2Handle(virAddr) != mb) {
114 s32Ret = RK_ERR_MB_BUSY;
115 RK_MPI_MB_ReleaseMB(mb);
116 goto __FAILED;
117 }
118 s32UniqueId = RK_MPI_MB_Handle2UniqueId(mb);
119 if (s32UniqueId < 0) {
120 s32Ret = RK_ERR_MB_BUSY;
121 RK_MPI_MB_ReleaseMB(mb);
122 goto __FAILED;
123 }
124 s32DupFd = RK_MPI_MB_UniqueId2Fd(s32UniqueId);
125 }
126
127 RK_LOGI("get poolId(%d) from mb(%p) refsCount(%d) phyAddr(%p) virAddr(%p) "
128 "fd(%d) uniqueId(%d) dupFd(%d)",
129 poolId, mb, refsCount, phyAddr, virAddr, fd, s32UniqueId, s32DupFd);
130 if (s32DupFd >= 0) {
131 close(s32DupFd);
132 s32DupFd = -1;
133 }
134 vector.emplace_back(mb);
135 }
136 iter = vector.begin();
137 for (; iter != vector.end(); ++iter) {
138 s32Ret = RK_MPI_MB_ReleaseMB(*iter);
139 if (s32Ret != RK_SUCCESS) {
140 goto __FAILED;
141 }
142 }
143 }
144
145 for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
146 s32Ret = RK_MPI_MB_DestroyPool(i);
147 if (s32Ret != RK_SUCCESS) {
148 goto __FAILED;
149 }
150 }
151 loopCount--;
152 RK_LOGI("looping times %d", pstCtx->s32LoopCount - loopCount);
153 } while (loopCount > 0);
154
155 return RK_SUCCESS;
156 __FAILED:
157 iter = vector.begin();
158 for (; iter != vector.end(); ++iter) {
159 RK_MPI_MB_ReleaseMB(*iter);
160 }
161 for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
162 RK_MPI_MB_DestroyPool(i);
163 }
164 return s32Ret;
165 }
166
167 static const char *const usages[] = {
168 "./rk_mpi_mb_test [-c MB_COUNT] [-s MB_SIZE]...",
169 NULL,
170 };
171
main(RK_S32 argc,const char ** argv)172 RK_S32 main(RK_S32 argc, const char **argv) {
173 RK_S32 s32Ret = RK_SUCCESS;
174 TEST_MB_CTX_S stMbCtx;
175
176 memset(&stMbCtx, 0, sizeof(TEST_MB_CTX_S));
177 stMbCtx.s32MbCount = 1;
178 stMbCtx.s32MbSize = 4 * 1024 * 1024;
179 stMbCtx.s32LoopCount = 1;
180 stMbCtx.s32PoolCount = 1;
181 stMbCtx.bPreAlloc = RK_FALSE;
182 stMbCtx.s32RemapMode = MB_REMAP_MODE_CACHED;
183 stMbCtx.s32AllocType = MB_ALLOC_TYPE_DMA;
184
185 struct argparse_option options[] = {
186 OPT_HELP(),
187 OPT_GROUP("basic options:"),
188 OPT_INTEGER('n', "loop", &(stMbCtx.s32LoopCount), "the count of looping. default(1).", NULL, 0, 0),
189 OPT_INTEGER('c', "mb_count", &(stMbCtx.s32MbCount), "the count of mb. default(1).", NULL, 0, 0),
190 OPT_INTEGER('s', "mb_size", &(stMbCtx.s32MbSize), "mb size. default(4MB).", NULL, 0, 0),
191 OPT_INTEGER('p', "pool_count", &(stMbCtx.s32PoolCount), "the count of pool. default(1).", NULL, 0, 0),
192 OPT_INTEGER('a', "pre_alloc", &(stMbCtx.bPreAlloc), "pre alloc or not. default(0). 0: no 1: yes.", NULL, 0, 0),
193 OPT_INTEGER('r', "remap_mode", &(stMbCtx.s32RemapMode),
194 "remapping mode. default(2). 0: none, 256: no cache, 512: cached", NULL, 0, 0),
195 OPT_INTEGER('t', "alloc_type", &(stMbCtx.s32AllocType),
196 "alloc type. default(0). 0: DMA, 1: malloc", NULL, 0, 0),
197 OPT_END(),
198 };
199
200 struct argparse argparse;
201 argparse_init(&argparse, options, usages, 0);
202 argparse_describe(&argparse, "\nselect a test case to run.",
203 "\nuse --help for details.");
204
205 argc = argparse_parse(&argparse, argc, argv);
206
207 s32Ret = unit_test_mpi_mb(&stMbCtx);
208 if (s32Ret != RK_SUCCESS) {
209 goto __FAILED;
210 }
211
212 RK_LOGI("test running ok.");
213 return RK_SUCCESS;
214 __FAILED:
215 RK_LOGE("test running failed!");
216 return RK_ERR_MB_BUSY;
217 }
218