/* Copyright 2020 Rockchip Electronics Co. LTD
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#undef DBG_MOD_ID
|
#define DBG_MOD_ID RK_ID_MB
|
|
#include <stdio.h>
|
#include <unistd.h>
|
#include <cstring>
|
#include <vector>
|
|
#include "rk_debug.h"
|
#include "rk_mpi_mb.h"
|
#include "argparse.h"
|
|
#define MB_POOL_COUNT 10
|
#define MB_POOL_MB_COUNT 10
|
#define MB_POOL_MB_SIZE 1280 * 720 * 2
|
|
typedef struct _rkTestMbCtx {
|
RK_S32 s32MbCount;
|
RK_S32 s32MbSize;
|
RK_S32 s32PoolCount;
|
RK_S32 s32LoopCount;
|
RK_BOOL bExternal;
|
RK_BOOL bPreAlloc;
|
RK_S32 s32RemapMode;
|
RK_S32 s32AllocType;
|
} TEST_MB_CTX_S;
|
|
RK_S32 unit_test_mpi_mb(const TEST_MB_CTX_S *pstCtx) {
|
MB_POOL_CONFIG_S pstMbPoolCfg;
|
std::vector<MB_BLK> vector;
|
std::vector<MB_BLK>::iterator iter;
|
RK_S32 s32Ret = RK_SUCCESS;
|
RK_S32 loopCount = pstCtx->s32LoopCount;
|
|
memset(&pstMbPoolCfg, 0, sizeof(MB_POOL_CONFIG_S));
|
pstMbPoolCfg.u64MBSize = pstCtx->s32MbSize;
|
pstMbPoolCfg.u32MBCnt = pstCtx->s32MbCount;
|
pstMbPoolCfg.bPreAlloc = pstCtx->bPreAlloc;
|
pstMbPoolCfg.enRemapMode = (MB_REMAP_MODE_E)pstCtx->s32RemapMode;
|
pstMbPoolCfg.enAllocType = (MB_ALLOC_TYPE_E)pstCtx->s32AllocType;
|
|
do {
|
for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
|
MB_POOL pool = RK_MPI_MB_CreatePool(&pstMbPoolCfg);
|
if (pool == MB_INVALID_POOLID) {
|
s32Ret = RK_ERR_MB_2MPOOLS;
|
goto __FAILED;
|
}
|
RK_LOGI("pool id %d", pool);
|
}
|
|
for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
|
vector.clear();
|
for (RK_S32 j = 0; j < pstCtx->s32MbCount; j++) {
|
MB_BLK mb = RK_MPI_MB_GetMB(i, pstMbPoolCfg.u64MBSize, RK_FALSE);
|
if (mb == MB_INVALID_HANDLE) {
|
s32Ret = RK_ERR_MB_NOBUF;
|
goto __FAILED;
|
}
|
RK_U64 phyAddr = RK_MPI_MB_Handle2PhysAddr(mb);
|
if (pstMbPoolCfg.enDmaType == MB_DMA_TYPE_CMA
|
&& pstMbPoolCfg.enAllocType == MB_ALLOC_TYPE_DMA
|
&& phyAddr == 0) {
|
s32Ret = RK_ERR_MB_BUSY;
|
RK_MPI_MB_ReleaseMB(mb);
|
goto __FAILED;
|
}
|
MB_POOL poolId = RK_MPI_MB_Handle2PoolId(mb);
|
if (poolId != i) {
|
s32Ret = RK_ERR_MB_BUSY;
|
RK_MPI_MB_ReleaseMB(mb);
|
goto __FAILED;
|
}
|
RK_S32 refsCount = RK_MPI_MB_InquireUserCnt(mb);
|
if (refsCount != 1) {
|
s32Ret = RK_ERR_MB_BUSY;
|
RK_MPI_MB_ReleaseMB(mb);
|
goto __FAILED;
|
}
|
RK_VOID *virAddr = RK_MPI_MB_Handle2VirAddr(mb);
|
if (virAddr == RK_NULL) {
|
s32Ret = RK_ERR_MB_BUSY;
|
RK_MPI_MB_ReleaseMB(mb);
|
goto __FAILED;
|
}
|
RK_S32 fd = RK_MPI_MB_Handle2Fd(mb);
|
if (pstMbPoolCfg.enAllocType == MB_ALLOC_TYPE_DMA
|
&& fd < 0) {
|
s32Ret = RK_ERR_MB_BUSY;
|
RK_MPI_MB_ReleaseMB(mb);
|
goto __FAILED;
|
}
|
if (pstMbPoolCfg.enAllocType == MB_ALLOC_TYPE_DMA) {
|
if (RK_MPI_MB_VirAddr2Handle(virAddr) != mb) {
|
s32Ret = RK_ERR_MB_BUSY;
|
RK_MPI_MB_ReleaseMB(mb);
|
goto __FAILED;
|
}
|
}
|
RK_LOGI("get pool id %d from mb %p refsCount %d. phy addr %p, vir addr %p, fd %d",
|
poolId, mb, refsCount, phyAddr, virAddr, fd);
|
vector.emplace_back(mb);
|
}
|
iter = vector.begin();
|
for (; iter != vector.end(); ++iter) {
|
s32Ret = RK_MPI_MB_ReleaseMB(*iter);
|
if (s32Ret != RK_SUCCESS) {
|
goto __FAILED;
|
}
|
}
|
}
|
|
for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
|
s32Ret = RK_MPI_MB_DestroyPool(i);
|
if (s32Ret != RK_SUCCESS) {
|
goto __FAILED;
|
}
|
}
|
loopCount--;
|
RK_LOGI("looping times %d", pstCtx->s32LoopCount - loopCount);
|
} while (loopCount > 0);
|
|
return RK_SUCCESS;
|
__FAILED:
|
iter = vector.begin();
|
for (; iter != vector.end(); ++iter) {
|
RK_MPI_MB_ReleaseMB(*iter);
|
}
|
for (RK_S32 i = 0; i < pstCtx->s32PoolCount; i++) {
|
RK_MPI_MB_DestroyPool(i);
|
}
|
return s32Ret;
|
}
|
|
static const char *const usages[] = {
|
"./rk_mpi_mb_test [-c MB_COUNT] [-s MB_SIZE]...",
|
NULL,
|
};
|
|
RK_S32 main(RK_S32 argc, const char **argv) {
|
RK_S32 s32Ret = RK_SUCCESS;
|
TEST_MB_CTX_S stMbCtx;
|
|
memset(&stMbCtx, 0, sizeof(TEST_MB_CTX_S));
|
stMbCtx.s32MbCount = 1;
|
stMbCtx.s32MbSize = 4 * 1024 * 1024;
|
stMbCtx.s32LoopCount = 1;
|
stMbCtx.s32PoolCount = 1;
|
stMbCtx.bPreAlloc = RK_FALSE;
|
stMbCtx.s32RemapMode = MB_REMAP_MODE_CACHED;
|
stMbCtx.s32AllocType = MB_ALLOC_TYPE_DMA;
|
|
struct argparse_option options[] = {
|
OPT_HELP(),
|
OPT_GROUP("basic options:"),
|
OPT_INTEGER('n', "loop", &(stMbCtx.s32LoopCount), "the count of looping. default(1).", NULL, 0, 0),
|
OPT_INTEGER('c', "mb_count", &(stMbCtx.s32MbCount), "the count of mb. default(1).", NULL, 0, 0),
|
OPT_INTEGER('s', "mb_size", &(stMbCtx.s32MbSize), "mb size. default(4MB).", NULL, 0, 0),
|
OPT_INTEGER('p', "pool_count", &(stMbCtx.s32PoolCount), "the count of pool. default(1).", NULL, 0, 0),
|
OPT_INTEGER('a', "pre_alloc", &(stMbCtx.bPreAlloc), "pre alloc or not. default(0). 0: no 1: yes.", NULL, 0, 0),
|
OPT_INTEGER('r', "remap_mode", &(stMbCtx.s32RemapMode),
|
"remapping mode. default(2). 0: none, 256: no cache, 512: cached", NULL, 0, 0),
|
OPT_INTEGER('t', "alloc_type", &(stMbCtx.s32AllocType),
|
"alloc type. default(0). 0: DMA, 1: malloc", NULL, 0, 0),
|
OPT_END(),
|
};
|
|
struct argparse argparse;
|
argparse_init(&argparse, options, usages, 0);
|
argparse_describe(&argparse, "\nselect a test case to run.",
|
"\nuse --help for details.");
|
|
argc = argparse_parse(&argparse, argc, argv);
|
|
s32Ret = unit_test_mpi_mb(&stMbCtx);
|
if (s32Ret != RK_SUCCESS) {
|
goto __FAILED;
|
}
|
|
RK_LOGI("test running ok.");
|
return RK_SUCCESS;
|
__FAILED:
|
RK_LOGE("test running failed!");
|
return RK_ERR_MB_BUSY;
|
}
|