You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
823 lines
23 KiB
823 lines
23 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2019. All rights reserved.
|
|
* Description: mpi_rm.c
|
|
* Author: sm_rm
|
|
* Create: 2012-12-01
|
|
*/
|
|
|
|
#include <sys/ioctl.h>
|
|
#include "securec.h"
|
|
#include "soc_errno.h"
|
|
#include "mpi_rm_ext.h"
|
|
#include "drv_ioctl_rm.h"
|
|
#include "mpi_rm_define.h"
|
|
#include "mpi_rm.h"
|
|
|
|
/********************************************************************************/
|
|
/* Global */
|
|
/********************************************************************************/
|
|
static td_s32 g_rm_dev_fd = -1;
|
|
static td_u32 g_rm_dev_init_cnt = 0;
|
|
static td_bool g_rm_check_open = TD_FALSE;
|
|
|
|
#define SOC_DEV_RM_NAME "soc_rm"
|
|
static const td_char g_rm_dev_name[] = "/dev/" SOC_DEV_RM_NAME;
|
|
|
|
static ext_rm_ctx g_rm_ctx;
|
|
static pthread_mutex_t g_rm_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
static pthread_mutex_t g_rm_cb_inst_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
static ext_rm_cb_instance g_rm_cb_instance[MAX_CALLBACK_NUM];
|
|
|
|
/********************************************************************************/
|
|
/* Define */
|
|
/********************************************************************************/
|
|
#define ext_rm_lock() (td_void)pthread_mutex_lock(&g_rm_mutex)
|
|
#define ext_rm_unlock() (td_void)pthread_mutex_unlock(&g_rm_mutex)
|
|
|
|
#define ext_rm_list_lock() (td_void)pthread_mutex_lock(&g_rm_cb_inst_mutex)
|
|
#define ext_rm_list_unlock() (td_void)pthread_mutex_unlock(&g_rm_cb_inst_mutex)
|
|
|
|
/********************************************************************************/
|
|
/* Array */
|
|
/********************************************************************************/
|
|
td_char *g_pen_rm_event[EXT_RM_EVENT_MAX + 1] = {
|
|
"undefine",
|
|
"LACK",
|
|
"CREATED",
|
|
"undefine",
|
|
"DESTROYED",
|
|
"BUTT"
|
|
};
|
|
|
|
/* Private API */
|
|
static td_s32 rm_mpi_convert_event_drv_to_iapi(ext_drv_rm_win_event drv_rm_event, ext_rm_event *pen_iapi_rm_event)
|
|
{
|
|
if (pen_iapi_rm_event == NULL) {
|
|
soc_log_err("rm_mpi_convert_event_drv_to_iapi pen_iapi_rm_event is null pointer.\n");
|
|
return SOC_ERR_RM_NULL_PTR;
|
|
}
|
|
|
|
switch (drv_rm_event) {
|
|
case EXT_DRV_RM_EVENT_WIN_LACK:
|
|
*pen_iapi_rm_event = EXT_RM_EVENT_WIN_LACK;
|
|
break;
|
|
|
|
case EXT_DRV_RM_EVENT_WIN_CREATED:
|
|
*pen_iapi_rm_event = EXT_RM_EVENT_WIN_CREATED;
|
|
break;
|
|
|
|
case EXT_DRV_RM_EVENT_WIN_DESTROYED:
|
|
*pen_iapi_rm_event = EXT_RM_EVENT_WIN_DESTROYED;
|
|
break;
|
|
|
|
default:
|
|
*pen_iapi_rm_event = EXT_RM_EVENT_MAX;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_create_event_path(td_u32 pid)
|
|
{
|
|
td_s32 ret;
|
|
rm_create create;
|
|
|
|
create.rm_handle = TD_INVALID_HANDLE;
|
|
create.pid = pid;
|
|
|
|
ret = ioctl(g_rm_dev_fd, CMD_RM_CREATE, &create);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call RM ioctl CMD:CMD_RM_CREATE failed, ret: [0x%08X].\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
if (create.rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("create.rm_handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
g_rm_ctx.rm_handle = create.rm_handle;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_destroy_event_path(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (g_rm_ctx.rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
ret = ioctl(g_rm_dev_fd, CMD_RM_DESTROY, &g_rm_ctx.rm_handle);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call RM ioctl CMD:CMD_RM_DESTROY failed, ret: [0x%08X].\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_enable_event_path(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (g_rm_ctx.rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
ret = ioctl(g_rm_dev_fd, CMD_RM_ENABLE, &g_rm_ctx.rm_handle);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call RM ioctl CMD:CMD_RM_ENABLE failed, ret: [0x%08X].\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_disable_event_path(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (g_rm_ctx.rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
ret = ioctl(g_rm_dev_fd, CMD_RM_DISABLE, &g_rm_ctx.rm_handle);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call RM ioctl CMD:CMD_RM_DISABLE failed, ret: [0x%08X].\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_query_event(ext_rm_event *pen_iapi_rm_event)
|
|
{
|
|
td_s32 ret;
|
|
rm_event rm_query;
|
|
ext_drv_rm_win_event drv_rm_event;
|
|
|
|
g_rm_ctx.event_querying = TD_TRUE;
|
|
if (g_rm_ctx.rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
memset_s(&rm_query, sizeof(rm_query), 0x0, sizeof(rm_event));
|
|
rm_query.rm_handle = g_rm_ctx.rm_handle;
|
|
|
|
ret = ioctl(g_rm_dev_fd, CMD_RM_QUERY, &rm_query);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_func_trace_low_freq_cnt_begin(LOW_FREQ_CNT);
|
|
soc_log_dbg("query event is failed.\n");
|
|
soc_func_trace_low_freq_cnt_end();
|
|
g_rm_ctx.event_querying = TD_FALSE;
|
|
return ret;
|
|
}
|
|
|
|
drv_rm_event = rm_query.rm_event.win_event;
|
|
ret = rm_mpi_convert_event_drv_to_iapi(drv_rm_event, pen_iapi_rm_event);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("rm_mpi_convert_event_drv_to_iapi error, %d!\n", ret);
|
|
}
|
|
|
|
g_rm_ctx.event_querying = TD_FALSE;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void rm_mpi_event_call_back(ext_rm_event iapi_rm_event)
|
|
{
|
|
td_u32 i;
|
|
td_s32 ret;
|
|
td_u32 event = 0;
|
|
ext_rm_cb_instance rm_cb_instance[MAX_CALLBACK_NUM];
|
|
|
|
soc_dbg_func_enter();
|
|
ext_rm_list_lock();
|
|
g_rm_ctx.instance_copying = TD_TRUE;
|
|
for (i = 0; i < MAX_CALLBACK_NUM; i++) {
|
|
rm_cb_instance[i].client = g_rm_cb_instance[i].client;
|
|
rm_cb_instance[i].event = g_rm_cb_instance[i].event;
|
|
rm_cb_instance[i].pid = g_rm_cb_instance[i].pid;
|
|
rm_cb_instance[i].pfn_rm_event_callback = g_rm_cb_instance[i].pfn_rm_event_callback;
|
|
}
|
|
g_rm_ctx.instance_copying = TD_FALSE;
|
|
ext_rm_list_unlock();
|
|
|
|
soc_dbg_func_enter();
|
|
for (i = 0; i < MAX_CALLBACK_NUM; i++) {
|
|
event = rm_cb_instance[i].event;
|
|
if ((rm_cb_instance[i].pfn_rm_event_callback == TD_NULL) ||
|
|
(iapi_rm_event == EXT_RM_EVENT_MAX)) {
|
|
soc_log_err("rm_event_callback is NULL or iapi_rm_event(%d) invalid.\n", iapi_rm_event);
|
|
continue;
|
|
}
|
|
if (((event & (td_u32)EXT_RM_EVENT_WIN_LACK) == iapi_rm_event) ||
|
|
((event & (td_u32)EXT_RM_EVENT_WIN_CREATED) == iapi_rm_event) ||
|
|
((event & (td_u32)EXT_RM_EVENT_WIN_DESTROYED) == iapi_rm_event)) {
|
|
soc_log_info("***not a bug,only for debug.***\n");
|
|
soc_info_print_u32(g_rm_ctx.pid);
|
|
soc_notice_print_u32(rm_cb_instance[i].pid);
|
|
soc_notice_print_str(g_pen_rm_event[iapi_rm_event]);
|
|
g_rm_ctx.call_backing = TD_TRUE;
|
|
ret = rm_cb_instance[i].pfn_rm_event_callback(rm_cb_instance[i].client, iapi_rm_event, 0);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call_back function execute error!\n");
|
|
}
|
|
g_rm_ctx.call_backing = TD_FALSE;
|
|
}
|
|
}
|
|
soc_dbg_func_exit();
|
|
|
|
return;
|
|
}
|
|
|
|
static td_void *rm_mpi_event_process_thread(td_void *arg)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 cnt = 0;
|
|
td_u32 pid = 0;
|
|
ext_rm_event rm_event = EXT_RM_EVENT_MAX;
|
|
|
|
TD_UNUSED(arg);
|
|
TD_UNUSED(pid);
|
|
|
|
while (g_rm_ctx.thread_run) {
|
|
if (g_rm_ctx.task_start == TD_TRUE) {
|
|
ret = rm_mpi_query_event(&rm_event);
|
|
if (ret != TD_SUCCESS) {
|
|
ext_usleep(THREAT_SLEEP_TIME);
|
|
} else {
|
|
rm_mpi_event_call_back(rm_event);
|
|
}
|
|
|
|
cnt++;
|
|
if (cnt >= 500) { /* 500 uesd to reduce print freq */
|
|
pid = (td_u32)getpid();
|
|
soc_dbg_print_u32(pid);
|
|
soc_dbg_print_str(g_pen_rm_event[rm_event]);
|
|
cnt = 0;
|
|
}
|
|
|
|
g_rm_ctx.task_status = EXT_RM_TASK_STATUS_RUNNING;
|
|
} else {
|
|
g_rm_ctx.task_status = EXT_RM_TASK_STATUS_PAUSED;
|
|
ext_usleep(THREAT_SLEEP_TIME);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return TD_NULL;
|
|
}
|
|
|
|
static td_s32 rm_mpi_create_query_thread(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
g_rm_ctx.thread_run = TD_TRUE;
|
|
|
|
(td_void)pthread_attr_init(&g_rm_ctx.rm_query_thread_attr);
|
|
(td_void)pthread_attr_setschedpolicy(&g_rm_ctx.rm_query_thread_attr, SCHED_OTHER);
|
|
|
|
/* create rm event query process thread */
|
|
ret = pthread_create(&g_rm_ctx.rm_query_thd_inst, &g_rm_ctx.rm_query_thread_attr,
|
|
rm_mpi_event_process_thread, TD_NULL);
|
|
if (ret != TD_SUCCESS) {
|
|
pthread_attr_destroy(&g_rm_ctx.rm_query_thread_attr);
|
|
soc_err_print_call_fun_err(pthread_create, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void rm_mpi_destroy_query_thread(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
g_rm_ctx.thread_run = TD_FALSE;
|
|
ret = pthread_join(g_rm_ctx.rm_query_thd_inst, TD_NULL);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(pthread_join, ret);
|
|
}
|
|
|
|
ret = pthread_attr_destroy(&g_rm_ctx.rm_query_thread_attr);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(pthread_attr_destroy, ret);
|
|
}
|
|
|
|
g_rm_ctx.rm_query_thd_inst = 0;
|
|
}
|
|
|
|
static td_void rm_mpi_task_suspend(td_void)
|
|
{
|
|
td_u32 suspend_time = 0;
|
|
|
|
if (g_rm_ctx.thread_run == TD_TRUE) {
|
|
g_rm_ctx.task_start = TD_FALSE;
|
|
|
|
while (g_rm_ctx.task_status != EXT_RM_TASK_STATUS_PAUSED) {
|
|
ext_usleep(THREAT_SLEEP_TIME); /* wait task paused */
|
|
suspend_time += THREAT_SLEEP_TIME;
|
|
/* THREAT_SLEEP_TIME * 1000 means dead lock */
|
|
if (suspend_time > (THREAT_SLEEP_TIME * 1000)) {
|
|
soc_func_trace_low_freq_cnt_begin(LOW_FREQ_CNT);
|
|
soc_log_err("dead lock, prohibit calling other RM interfaces in callback function!!!\n");
|
|
soc_err_print_bool(g_rm_ctx.call_backing);
|
|
soc_err_print_bool(g_rm_ctx.instance_copying);
|
|
soc_err_print_bool(g_rm_ctx.event_querying);
|
|
soc_err_print_bool(g_rm_ctx.task_start);
|
|
soc_err_print_u32(g_rm_ctx.pid);
|
|
soc_func_trace_low_freq_cnt_end();
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
soc_log_dbg("suspend_time = %u(us)\n", suspend_time);
|
|
return;
|
|
}
|
|
|
|
static td_void rm_mpi_task_resume(td_void)
|
|
{
|
|
if (g_rm_ctx.thread_run == TD_TRUE && g_rm_ctx.query_path_exist == TD_TRUE) {
|
|
g_rm_ctx.task_start = TD_TRUE;
|
|
soc_info_print_bool(g_rm_ctx.task_start);
|
|
}
|
|
|
|
soc_log_dbg("task resume ok\n");
|
|
return;
|
|
}
|
|
|
|
static td_void rm_mpi_init_instance(td_void)
|
|
{
|
|
td_u32 i;
|
|
|
|
ext_rm_list_lock();
|
|
for (i = 0; i < MAX_CALLBACK_NUM; i++) {
|
|
g_rm_cb_instance[i].client = TD_NULL;
|
|
g_rm_cb_instance[i].pfn_rm_event_callback = TD_NULL;
|
|
g_rm_cb_instance[i].event = 0;
|
|
g_rm_cb_instance[i].pid = 0;
|
|
}
|
|
ext_rm_list_unlock();
|
|
|
|
return;
|
|
}
|
|
|
|
static td_void rm_mpi_init_ctx(td_void)
|
|
{
|
|
g_rm_ctx.rm_handle = TD_INVALID_HANDLE;
|
|
g_rm_ctx.task_start = TD_FALSE;
|
|
g_rm_ctx.thread_run = TD_FALSE;
|
|
g_rm_ctx.task_status = EXT_RM_TASK_STATUS_PAUSED;
|
|
g_rm_ctx.query_path_exist = TD_FALSE;
|
|
g_rm_ctx.rm_query_thd_inst = 0;
|
|
g_rm_ctx.pid = 0;
|
|
g_rm_ctx.call_backing = TD_FALSE;
|
|
return;
|
|
}
|
|
|
|
static td_s32 rm_mpi_create_query_path(td_void)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 pid;
|
|
|
|
pid = (td_u32)getpid();
|
|
g_rm_ctx.pid = pid;
|
|
|
|
ret = rm_mpi_create_event_path(pid);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_mpi_create_event_path, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
ret = rm_mpi_create_query_thread();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_mpi_create_query_thread, ret);
|
|
goto DESTROY_PATH;
|
|
}
|
|
|
|
ret = rm_mpi_enable_event_path();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_mpi_enable_event_path, ret);
|
|
goto DESTROY_THREAD;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
|
|
DESTROY_THREAD:
|
|
rm_mpi_destroy_query_thread();
|
|
DESTROY_PATH:
|
|
ret = rm_mpi_destroy_event_path();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_mpi_destroy_event_path, ret);
|
|
}
|
|
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
static td_s32 rm_mpi_destroy_query_path(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
rm_mpi_destroy_query_thread();
|
|
ret = rm_mpi_disable_event_path();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_mpi_disable_event_path, ret);
|
|
}
|
|
|
|
ret = rm_mpi_destroy_event_path();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_mpi_destroy_event_path, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
rm_mpi_init_instance();
|
|
g_rm_ctx.query_path_exist = TD_FALSE;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_get_free_instance(td_u32 *instance_id_p)
|
|
{
|
|
td_u32 i;
|
|
|
|
ext_rm_list_lock();
|
|
for (i = 0; i < MAX_CALLBACK_NUM; i++) {
|
|
if (g_rm_cb_instance[i].pfn_rm_event_callback == TD_NULL) {
|
|
*instance_id_p = i;
|
|
break;
|
|
}
|
|
}
|
|
ext_rm_list_unlock();
|
|
|
|
if (i == MAX_CALLBACK_NUM) {
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_bool rm_mpi_find_instance_by_client(const td_void *client, td_u32 *instance_id_p)
|
|
{
|
|
td_u32 i;
|
|
|
|
ext_rm_list_lock();
|
|
for (i = 0; i < MAX_CALLBACK_NUM; i++) {
|
|
if (client == g_rm_cb_instance[i].client) {
|
|
*instance_id_p = i;
|
|
break;
|
|
}
|
|
}
|
|
ext_rm_list_unlock();
|
|
|
|
if (i == MAX_CALLBACK_NUM) {
|
|
return TD_FALSE;
|
|
}
|
|
|
|
return TD_TRUE;
|
|
}
|
|
|
|
static td_bool rm_mpi_need_destroy_path(td_void)
|
|
{
|
|
td_u32 i;
|
|
|
|
ext_rm_list_lock();
|
|
for (i = 0; i < MAX_CALLBACK_NUM; i++) {
|
|
if (g_rm_cb_instance[i].pfn_rm_event_callback != TD_NULL) {
|
|
break;
|
|
}
|
|
}
|
|
ext_rm_list_unlock();
|
|
|
|
if (i == MAX_CALLBACK_NUM) {
|
|
return TD_TRUE;
|
|
}
|
|
|
|
return TD_FALSE;
|
|
}
|
|
|
|
static td_s32 rm_mpi_check_and_open(td_void)
|
|
{
|
|
td_char path[PATH_MAX] = {0};
|
|
|
|
if (g_rm_dev_fd < 0) {
|
|
soc_log_info("current RM not open, open it\n");
|
|
|
|
if (realpath(g_rm_dev_name, path) == TD_NULL) {
|
|
soc_log_err("get realpath error!\n");
|
|
return TD_FAILURE;
|
|
}
|
|
g_rm_dev_fd = open(path, O_RDWR | O_NONBLOCK, 0);
|
|
if (g_rm_dev_fd < 0) {
|
|
soc_log_err("open RM err.\n");
|
|
return SOC_ERR_RM_DEV_OPEN_ERR;
|
|
}
|
|
|
|
g_rm_check_open = TD_TRUE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_mpi_reg_callback(const td_void *client, ext_rm_event_cb_fn fn, td_u32 event)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
td_u32 instance = 0;
|
|
td_bool instance_exist;
|
|
|
|
if (g_rm_ctx.query_path_exist == TD_FALSE) {
|
|
ret = rm_mpi_create_query_path();
|
|
if (ret == TD_FAILURE) {
|
|
soc_err_print_call_fun_err(rm_mpi_create_query_path, ret);
|
|
rm_mpi_task_resume();
|
|
return SOC_ERR_RM_CREATE_ERR;
|
|
}
|
|
|
|
ret = rm_mpi_get_free_instance(&instance);
|
|
if (ret == TD_FAILURE) {
|
|
soc_err_print_call_fun_err(rm_mpi_get_free_instance, ret);
|
|
ret = rm_mpi_destroy_query_path();
|
|
if (ret == TD_FAILURE) {
|
|
soc_err_print_call_fun_err(rm_mpi_destroy_query_path, ret);
|
|
} else {
|
|
g_rm_ctx.query_path_exist = TD_FALSE;
|
|
}
|
|
rm_mpi_task_resume();
|
|
return SOC_ERR_RM_NOT_FREE_CB_INST;
|
|
}
|
|
|
|
g_rm_ctx.query_path_exist = TD_TRUE;
|
|
soc_log_dbg("register callback succeed\n");
|
|
} else {
|
|
instance_exist = rm_mpi_find_instance_by_client(client, &instance);
|
|
if (instance_exist != TD_TRUE) {
|
|
ret = rm_mpi_get_free_instance(&instance);
|
|
if (ret == TD_FAILURE) {
|
|
soc_err_print_call_fun_err(rm_mpi_get_free_instance, ret);
|
|
rm_mpi_task_resume();
|
|
return SOC_ERR_RM_NOT_FREE_CB_INST;
|
|
}
|
|
}
|
|
soc_log_dbg("repeat register succeed.\n");
|
|
}
|
|
|
|
soc_log_notice("g_rm_ctx.pid = %u, event = %d \n", g_rm_ctx.pid, event);
|
|
|
|
ext_rm_list_lock();
|
|
g_rm_cb_instance[instance].pfn_rm_event_callback = fn;
|
|
g_rm_cb_instance[instance].client = (td_void *)client;
|
|
g_rm_cb_instance[instance].event = event;
|
|
g_rm_cb_instance[instance].pid = (td_u32)getpid();
|
|
ext_rm_list_unlock();
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 rm_mpi_unregister_callback_pre_check(const td_void *client, ext_rm_event_cb_fn fn)
|
|
{
|
|
if (client == NULL) {
|
|
soc_log_err("ext_mpi_rm_un_register_callback client_p is null pointer.\n");
|
|
return SOC_ERR_RM_NULL_PTR;
|
|
}
|
|
|
|
if (fn == NULL) {
|
|
soc_log_err("ext_mpi_rm_un_register_callback fn is null pointer.\n");
|
|
return SOC_ERR_RM_NULL_PTR;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void rm_mpi_reset_callback_instance(td_u32 cb_index)
|
|
{
|
|
g_rm_cb_instance[cb_index].event = 0;
|
|
g_rm_cb_instance[cb_index].pid = 0;
|
|
g_rm_cb_instance[cb_index].client = TD_NULL;
|
|
g_rm_cb_instance[cb_index].pfn_rm_event_callback = TD_NULL;
|
|
return;
|
|
}
|
|
|
|
/* Public API */
|
|
td_s32 ext_mpi_rm_init(td_void)
|
|
{
|
|
td_char path[PATH_MAX] = {0};
|
|
|
|
soc_info_func_enter();
|
|
ext_rm_lock();
|
|
if (g_rm_dev_fd > 0) {
|
|
g_rm_dev_init_cnt++;
|
|
soc_log_warn("RM be inited, query path be exist.\n");
|
|
soc_info_print_u32(g_rm_dev_init_cnt);
|
|
soc_info_func_exit();
|
|
ext_rm_unlock();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if (realpath(g_rm_dev_name, path) == TD_NULL) {
|
|
soc_log_err("get realpath error!\n");
|
|
ext_rm_unlock();
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
g_rm_dev_fd = open(path, O_RDWR | O_NONBLOCK, 0);
|
|
if (g_rm_dev_fd < 0) {
|
|
soc_log_err("open RM err.\n");
|
|
ext_rm_unlock();
|
|
return SOC_ERR_RM_DEV_OPEN_ERR;
|
|
}
|
|
rm_mpi_init_ctx();
|
|
rm_mpi_init_instance();
|
|
g_rm_dev_init_cnt++;
|
|
soc_info_print_u32(g_rm_dev_init_cnt);
|
|
ext_rm_unlock();
|
|
soc_info_func_exit();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 ext_mpi_rm_deinit(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
soc_info_func_enter();
|
|
if (g_rm_ctx.call_backing == TD_TRUE) {
|
|
soc_log_warn("the callback function is not finished\n");
|
|
}
|
|
|
|
ext_rm_lock();
|
|
rm_mpi_task_suspend();
|
|
|
|
if (g_rm_dev_init_cnt > 1) {
|
|
soc_log_warn("RM reference count not zero.\n");
|
|
soc_info_func_exit();
|
|
g_rm_dev_init_cnt--;
|
|
soc_info_print_u32(g_rm_dev_init_cnt);
|
|
ext_rm_unlock();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if ((g_rm_dev_fd < 0) || (g_rm_dev_init_cnt == 0)) {
|
|
ext_rm_unlock();
|
|
soc_log_warn("RM be de_inited.\n");
|
|
soc_info_func_exit();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
if (g_rm_ctx.query_path_exist == TD_TRUE) {
|
|
soc_log_warn("query path is exist,destroy it.\n");
|
|
ret = rm_mpi_destroy_query_path();
|
|
if (ret != TD_SUCCESS) {
|
|
ext_rm_unlock();
|
|
soc_err_print_call_fun_err(rm_mpi_destroy_query_path, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
} else {
|
|
rm_mpi_init_instance();
|
|
}
|
|
|
|
close(g_rm_dev_fd);
|
|
g_rm_dev_fd = -1;
|
|
g_rm_dev_init_cnt--;
|
|
soc_info_print_u32(g_rm_dev_init_cnt);
|
|
rm_mpi_init_ctx();
|
|
ext_rm_unlock();
|
|
soc_info_func_exit();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 ext_mpi_rm_register_callback(const td_void *client, ext_rm_event_cb_fn fn, td_u32 event_mask)
|
|
{
|
|
td_s32 ret;
|
|
|
|
soc_info_func_enter();
|
|
if (client == NULL) {
|
|
soc_log_err("ext_mpi_rm_register_callback client_p is null pointer.\n");
|
|
return SOC_ERR_RM_NULL_PTR;
|
|
}
|
|
|
|
if (fn == NULL) {
|
|
soc_log_err("ext_mpi_rm_register_callback fn is null pointer.\n");
|
|
return SOC_ERR_RM_NULL_PTR;
|
|
}
|
|
|
|
if ((event_mask &
|
|
(td_u32)(EXT_RM_EVENT_WIN_LACK | EXT_RM_EVENT_WIN_CREATED | EXT_RM_EVENT_WIN_DESTROYED)) == 0) {
|
|
soc_log_err("event:%d is invalid.\n", event_mask);
|
|
return SOC_ERR_RM_INVALID_PARA;
|
|
}
|
|
|
|
if (g_rm_ctx.call_backing == TD_TRUE) {
|
|
soc_log_warn("the callback function is not finished\n");
|
|
}
|
|
|
|
ext_rm_lock();
|
|
rm_mpi_task_suspend();
|
|
if (g_rm_dev_fd < 0) {
|
|
rm_mpi_task_resume();
|
|
ext_rm_unlock();
|
|
soc_log_err("please init firstly.\n");
|
|
return SOC_ERR_RM_DEV_NOT_INIT;
|
|
}
|
|
|
|
ret = rm_mpi_reg_callback(client, fn, event_mask);
|
|
if (ret != TD_SUCCESS) {
|
|
ext_rm_unlock();
|
|
soc_err_print_call_fun_err(rm_mpi_reg_callback, ret);
|
|
return ret;
|
|
}
|
|
|
|
rm_mpi_task_resume();
|
|
ext_rm_unlock();
|
|
soc_info_func_exit();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 ext_mpi_rm_unregister_callback(const td_void *client, ext_rm_event_cb_fn fn)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 cb_index;
|
|
td_bool need_destroy_path;
|
|
td_bool instance_exist;
|
|
|
|
soc_info_func_enter();
|
|
ret = rm_mpi_unregister_callback_pre_check(client, fn);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
ext_rm_lock();
|
|
rm_mpi_task_suspend();
|
|
if (g_rm_dev_fd < 0) {
|
|
rm_mpi_task_resume();
|
|
ext_rm_unlock();
|
|
soc_log_err("please init firstly.\n");
|
|
return SOC_ERR_RM_DEV_NO_INIT;
|
|
}
|
|
|
|
instance_exist = rm_mpi_find_instance_by_client(client, &cb_index);
|
|
if (instance_exist == TD_FALSE) {
|
|
soc_log_err("find instance by client_p error!\n");
|
|
rm_mpi_task_resume();
|
|
ext_rm_unlock();
|
|
return SOC_ERR_RM_INVALID_PARA;
|
|
}
|
|
|
|
soc_log_info("try to un_register callback.\n");
|
|
soc_dbg_print_u32(g_rm_ctx.pid);
|
|
soc_dbg_print_void(client);
|
|
ext_rm_list_lock();
|
|
rm_mpi_reset_callback_instance(cb_index);
|
|
ext_rm_list_unlock();
|
|
|
|
need_destroy_path = rm_mpi_need_destroy_path();
|
|
if (need_destroy_path == TD_TRUE) {
|
|
ret = rm_mpi_destroy_query_path();
|
|
if (ret != TD_SUCCESS) {
|
|
rm_mpi_task_resume();
|
|
ext_rm_unlock();
|
|
soc_err_print_call_fun_err(rm_mpi_destroy_query_path, ret);
|
|
return SOC_ERR_RM_DESTROY_ERR;
|
|
}
|
|
}
|
|
|
|
rm_mpi_task_resume();
|
|
ext_rm_unlock();
|
|
soc_log_info("un_register callback OK.\n");
|
|
soc_info_func_exit();
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 ext_mpi_rm_acquire_window_handle(td_void)
|
|
{
|
|
td_s32 ret;
|
|
rm_win_info rm_win_info = {TD_INVALID_HANDLE, 0};
|
|
|
|
soc_info_func_enter();
|
|
ext_rm_lock();
|
|
ret = rm_mpi_check_and_open();
|
|
if (ret != TD_SUCCESS) {
|
|
ext_rm_unlock();
|
|
soc_log_err("this instance is not init,please init firstly.\n");
|
|
return SOC_ERR_RM_DEV_NOT_INIT;
|
|
}
|
|
ext_rm_unlock();
|
|
|
|
rm_win_info.win_handle = TD_INVALID_HANDLE;
|
|
rm_win_info.pid = (td_u32)getpid();
|
|
soc_log_notice("try to acquire window resource, current acquire window PID:%u\n", rm_win_info.pid);
|
|
ret = ioctl(g_rm_dev_fd, CMD_RM_ACQUIREWIN, &rm_win_info);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call RM ioctl CMD:CMD_RM_ACQUIREWIN failed, ret: [0x%08X].\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
soc_log_notice("current process check_open:%s\n", g_rm_check_open == TD_TRUE ? "true" : "false");
|
|
soc_info_func_exit();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|