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.
729 lines
23 KiB
729 lines
23 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2019. All rights reserved.
|
|
* Description: drv_rm
|
|
* Author: sdk_video
|
|
* Create: 2012-11-25
|
|
*/
|
|
#include "drv_rm.h"
|
|
#include "osal_ext.h"
|
|
#include "soc_errno.h"
|
|
|
|
#include "drv_rm_ext.h"
|
|
#include "drv_win_ext.h"
|
|
#include "drv_rm_define.h"
|
|
#include "drv_rm_proc.h"
|
|
#include "drv_rm_comm.h"
|
|
|
|
static rm_drv_golbal_ctx g_st_rm_drv_golbal_ctx;
|
|
static rm_drv_path_ctx g_st_rm_drv_path_ctx[RM_DRV_CHN_MAX_NUM + 1];
|
|
static td_u32 g_u32_reserve;
|
|
|
|
osal_semaphore g_rm_drv_mutex;
|
|
|
|
/* 初始化上下文 */
|
|
static td_void rm_drv_comm_de_init_path_ctx(td_u32 rm_path_id)
|
|
{
|
|
osal_wait_destroy(&g_st_rm_drv_path_ctx[rm_path_id].wait_queue);
|
|
return;
|
|
}
|
|
|
|
static td_void rm_drv_comm_de_init_golbal_ctx(td_void)
|
|
{
|
|
osal_wait_destroy(&g_st_rm_drv_golbal_ctx.wait_queue);
|
|
return;
|
|
}
|
|
|
|
static td_void rm_drv_comm_init_path_ctx(td_u32 rm_path_id)
|
|
{
|
|
errno_t err;
|
|
|
|
err = memset_s(&g_st_rm_drv_path_ctx[rm_path_id], sizeof(g_st_rm_drv_path_ctx), 0, sizeof(rm_drv_path_ctx));
|
|
if (err != EOK) {
|
|
soc_log_err("rm_drv_comm_init_path_ctx memset_s fail!\n");
|
|
return;
|
|
}
|
|
|
|
g_st_rm_drv_path_ctx[rm_path_id].rm_handle = TD_INVALID_HANDLE;
|
|
osal_wait_init(&g_st_rm_drv_path_ctx[rm_path_id].wait_queue);
|
|
return;
|
|
}
|
|
|
|
static td_void rm_drv_comm_init_golbal_ctx(td_void)
|
|
{
|
|
td_s32 i;
|
|
|
|
memset_s(&g_st_rm_drv_golbal_ctx, sizeof(g_st_rm_drv_golbal_ctx), 0, sizeof(rm_drv_golbal_ctx));
|
|
|
|
g_st_rm_drv_golbal_ctx.wake_up_cnt = 0;
|
|
g_st_rm_drv_golbal_ctx.path_recycle_cnt = 0;
|
|
g_st_rm_drv_golbal_ctx.normal_cnt = 0;
|
|
g_st_rm_drv_golbal_ctx.rm_path_count = 0;
|
|
g_st_rm_drv_golbal_ctx.rm_available_win_count = RM_DRV_WIN_MAX_COUNT;
|
|
g_st_rm_drv_golbal_ctx.wake_up_flags = TD_FALSE;
|
|
g_st_rm_drv_golbal_ctx.waiting_event = TD_FALSE;
|
|
g_st_rm_drv_golbal_ctx.wind_owner = EXT_DRV_WIN_OWNER_BUTT;
|
|
g_st_rm_drv_golbal_ctx.win_owner_id = 0;
|
|
|
|
for (i = 0; i < RM_DRV_CHN_MAX_NUM; i++) {
|
|
g_st_rm_drv_golbal_ctx.chn_create_cnt[i] = 0;
|
|
g_st_rm_drv_golbal_ctx.chn_destroy_cnt[i] = 0;
|
|
}
|
|
|
|
g_u32_reserve = 0;
|
|
osal_wait_init(&g_st_rm_drv_golbal_ctx.wait_queue);
|
|
return;
|
|
}
|
|
|
|
|
|
/* 获取上下文 */
|
|
td_void rm_drv_comm_get_path_ctx(td_u32 rm_path_id, rm_drv_path_ctx **rm_drv_path_ctx_p)
|
|
{
|
|
if (rm_drv_path_ctx_p == TD_NULL) {
|
|
soc_log_err("rm_drv_path_ctx_p is null!\n");
|
|
return;
|
|
}
|
|
*rm_drv_path_ctx_p = &g_st_rm_drv_path_ctx[rm_path_id];
|
|
return;
|
|
}
|
|
|
|
/* 获取上下文 */
|
|
td_void rm_drv_comm_get_golbal_ctx(rm_drv_golbal_ctx **rm_drv_golbal_ctx_p)
|
|
{
|
|
if (rm_drv_golbal_ctx_p == TD_NULL) {
|
|
soc_log_err("rm_drv_golbal_ctx_p is null!\n");
|
|
return;
|
|
}
|
|
*rm_drv_golbal_ctx_p = &g_st_rm_drv_golbal_ctx;
|
|
return;
|
|
}
|
|
|
|
/* get current time */
|
|
td_void rm_drv_comm_get_cur_time(td_u32 *cur_time_us_p)
|
|
{
|
|
osal_timeval time;
|
|
osal_gettimeofday(&time);
|
|
|
|
if (cur_time_us_p == TD_NULL) {
|
|
soc_log_err("cur_time_us_p is null!\n");
|
|
return;
|
|
}
|
|
if ((time.tv_sec * 1000000ULL + time.tv_usec) < 0xffffffff) {
|
|
*cur_time_us_p = time.tv_sec * 1000000 + time.tv_usec; /* 1000000 uesed convert second to microsecond */
|
|
} else {
|
|
*cur_time_us_p = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static td_s32 rm_drv_ctrl_put_win_event_to_list(ext_drv_rm_win_event win_event)
|
|
{
|
|
td_s32 ret;
|
|
td_s32 result = TD_SUCCESS;
|
|
td_u32 rm_path_id;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
ext_drv_rm_event rm_event;
|
|
|
|
for (rm_path_id = 0; rm_path_id < RM_DRV_CHN_MAX_NUM; rm_path_id++) {
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
if (rm_drv_path_ctx_p->rm_handle != TD_INVALID_HANDLE) {
|
|
rm_event.win_event = win_event;
|
|
ret = rm_drv_comm_put_event(rm_drv_path_ctx_p->rm_handle, rm_drv_path_ctx_p->event_handle_p, &rm_event);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_dbg("put event in list failed!\n");
|
|
soc_dbg_print_u32(win_event);
|
|
soc_dbg_print_u32(rm_path_id);
|
|
result = TD_FAILURE;
|
|
}
|
|
|
|
rm_drv_path_ctx_p->list_empty = TD_FALSE;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* 获取空闲RM path id */
|
|
static td_s32 rm_drv_ctrl_get_free_path_id(td_u32 *rm_path_id_p)
|
|
{
|
|
td_u32 rm_path_id;
|
|
rm_drv_path_ctx *rm_path_ctx_p = TD_NULL;
|
|
|
|
for (rm_path_id = 0; rm_path_id < RM_DRV_CHN_MAX_NUM; rm_path_id++) {
|
|
rm_path_ctx_p = &g_st_rm_drv_path_ctx[rm_path_id];
|
|
if (rm_path_ctx_p->rm_handle == TD_INVALID_HANDLE) {
|
|
*rm_path_id_p = rm_path_id;
|
|
return TD_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return SOC_ERR_RM_NOT_FREE_INST;
|
|
}
|
|
|
|
static td_s32 rm_drv_ctrl_wake_up_waiting_event(td_void)
|
|
{
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
|
|
check_rm_null_ptr(rm_drv_golbal_ctx_p);
|
|
|
|
rm_drv_golbal_ctx_p->wake_up_flags = TD_TRUE;
|
|
osal_wait_wakeup(&rm_drv_golbal_ctx_p->wait_queue);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_drv_ctrl_disable(td_handle rm_handle)
|
|
{
|
|
td_u32 rm_path_id = 0;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
|
|
if (rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
if (((rm_path_id) = (rm_handle) & 0xff) >= RM_DRV_CHN_MAX_NUM) {
|
|
soc_log_err("rm path id is over range.rm_id = 0x%08X\n", rm_path_id);
|
|
return SOC_ERR_RM_INST_OVER_RANGE;
|
|
}
|
|
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
check_rm_null_ptr(rm_drv_path_ctx_p);
|
|
if (rm_handle != rm_drv_path_ctx_p->rm_handle) {
|
|
soc_log_err("src_rm_handle is not equal dest_rm_handle.\n");
|
|
soc_err_print_h32(rm_handle);
|
|
soc_err_print_h32(rm_drv_path_ctx_p->rm_handle);
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
if (rm_drv_path_ctx_p->chn_enable != TD_FALSE) {
|
|
rm_drv_path_ctx_p->chn_enable = TD_FALSE;
|
|
} else {
|
|
soc_log_err("path is already disable!\n");
|
|
soc_err_print_u32(rm_path_id);
|
|
return SOC_ERR_RM_DISABLE_ERR;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 rm_drv_ctrl_destroy(td_handle rm_handle)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 rm_path_id = 0;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
td_handle tmp_rm_handle;
|
|
|
|
if (rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
if (((rm_path_id) = (rm_handle) & 0xff) >= RM_DRV_CHN_MAX_NUM) {
|
|
soc_log_err("rm path id is over range.rm_id = 0x%08X\n", rm_path_id);
|
|
return SOC_ERR_RM_INST_OVER_RANGE;
|
|
}
|
|
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
check_rm_null_ptr(rm_drv_path_ctx_p);
|
|
if (rm_handle != rm_drv_path_ctx_p->rm_handle) {
|
|
soc_log_err("src_rm_handle is not equal dest_rm_handle.\n");
|
|
soc_err_print_h32(rm_handle);
|
|
soc_err_print_h32(rm_drv_path_ctx_p->rm_handle);
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
tmp_rm_handle = rm_drv_path_ctx_p->rm_handle;
|
|
rm_drv_path_ctx_p->rm_handle = TD_INVALID_HANDLE;
|
|
|
|
ret = rm_drv_comm_de_init_event_list(rm_drv_path_ctx_p->event_handle_p);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("de_init event list failed.\n");
|
|
rm_drv_path_ctx_p->rm_handle = tmp_rm_handle;
|
|
return SOC_ERR_RM_DESTROY_ERR;
|
|
}
|
|
|
|
rm_drv_path_ctx_p->chn_enable = TD_FALSE;
|
|
rm_drv_path_ctx_p->event_handle_p = TD_NULL;
|
|
rm_drv_path_ctx_p->queue_cnt = 1;
|
|
rm_drv_path_ctx_p->try_queue_cnt = 0;
|
|
rm_drv_path_ctx_p->cur_pid = 0;
|
|
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
check_rm_null_ptr(rm_drv_golbal_ctx_p);
|
|
|
|
rm_drv_golbal_ctx_p->rm_path_count--;
|
|
rm_drv_golbal_ctx_p->chn_destroy_cnt[rm_path_id]++;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
/* avoid service crash cause path resource leak */
|
|
static td_void rm_drv_ctrl_recycle_path_resource(td_void)
|
|
{
|
|
td_s32 ret1;
|
|
td_s32 ret2;
|
|
td_u32 rm_path_id;
|
|
td_u32 available_rm_path;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
if (rm_drv_golbal_ctx_p == TD_NULL) {
|
|
soc_log_err("rm_drv_golbal_ctx_p is null ptr.\n");
|
|
return;
|
|
}
|
|
|
|
available_rm_path = RM_DRV_CHN_MAX_NUM - rm_drv_golbal_ctx_p->rm_path_count;
|
|
if (available_rm_path > 1) {
|
|
return;
|
|
}
|
|
|
|
soc_log_err("available rm path less than two!\n");
|
|
|
|
for (rm_path_id = 0; rm_path_id < RM_DRV_CHN_MAX_NUM; rm_path_id++) {
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
if (rm_drv_path_ctx_p->rm_handle == TD_INVALID_HANDLE) {
|
|
continue;
|
|
}
|
|
if (rm_drv_path_ctx_p->used_node == RM_DRV_LIST_NODE_NUM && rm_drv_path_ctx_p->free_node == 0) {
|
|
soc_log_err("path resource leak! recycle it \n");
|
|
soc_err_print_u32(rm_path_id);
|
|
soc_err_print_u32(rm_drv_path_ctx_p->cur_pid);
|
|
ret1 = rm_drv_ctrl_disable(rm_drv_path_ctx_p->rm_handle);
|
|
ret2 = rm_drv_ctrl_destroy(rm_drv_path_ctx_p->rm_handle);
|
|
if (ret1 != TD_SUCCESS || ret2 != TD_SUCCESS) {
|
|
soc_log_err("path resource leak! recycle failed\n");
|
|
soc_err_print_u32(rm_path_id);
|
|
} else {
|
|
rm_drv_path_ctx_p->rm_handle = TD_INVALID_HANDLE;
|
|
rm_drv_path_ctx_p->event_handle_p = TD_NULL;
|
|
rm_drv_path_ctx_p->chn_enable = TD_FALSE; /* default colse the channel */
|
|
rm_drv_path_ctx_p->queue_cnt = 1;
|
|
rm_drv_path_ctx_p->try_queue_cnt = 0;
|
|
rm_drv_path_ctx_p->free_node = RM_DRV_LIST_NODE_NUM;
|
|
rm_drv_path_ctx_p->used_node = 0;
|
|
rm_drv_path_ctx_p->cur_index = 0;
|
|
rm_drv_path_ctx_p->cur_pid = 0;
|
|
rm_drv_golbal_ctx_p->path_recycle_cnt++;
|
|
soc_log_dbg("path resource leak! recycle succeed!\n");
|
|
soc_dbg_print_u32(rm_path_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* check path is idle */
|
|
static td_void rm_drv_ctrl_check_idle_path(td_void)
|
|
{
|
|
td_u32 rm_path_id;
|
|
td_u32 cur_sys_time = 0;
|
|
td_u32 time_diff;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
|
|
rm_drv_comm_get_cur_time(&cur_sys_time);
|
|
|
|
for (rm_path_id = 0; rm_path_id < RM_DRV_CHN_MAX_NUM; rm_path_id++) {
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
if (rm_drv_path_ctx_p->rm_handle != TD_INVALID_HANDLE) {
|
|
time_diff = cur_sys_time - rm_drv_path_ctx_p->lst_query_time;
|
|
rm_drv_path_ctx_p->cur_query_time = cur_sys_time;
|
|
|
|
if (rm_drv_path_ctx_p->idle == TD_TRUE) {
|
|
continue;
|
|
}
|
|
|
|
if (time_diff > RM_DRV_IDLE_MAX_TIME_US && rm_drv_path_ctx_p->used_node >= RM_DRV_IDLE_MAX_USED_NODE) {
|
|
rm_drv_path_ctx_p->idle = TD_TRUE;
|
|
soc_warn_print_u32(rm_drv_path_ctx_p->cur_pid);
|
|
soc_warn_print_bool(rm_drv_path_ctx_p->idle);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* avoid service crash cause path resource leak */
|
|
static td_void rm_drv_ctrl_recycle_idle_path(td_void)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 rm_path_id;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
|
|
for (rm_path_id = 0; rm_path_id < RM_DRV_CHN_MAX_NUM; rm_path_id++) {
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
if (rm_drv_path_ctx_p->rm_handle == TD_INVALID_HANDLE) {
|
|
continue;
|
|
}
|
|
if (rm_drv_path_ctx_p->idle == TD_TRUE) {
|
|
soc_log_err("path is idle! recycle it\n");
|
|
soc_err_print_u32(rm_path_id);
|
|
soc_err_print_u32(rm_drv_path_ctx_p->cur_pid);
|
|
|
|
ret = rm_drv_ctrl_disable(rm_drv_path_ctx_p->rm_handle);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_drv_ctrl_disable, ret);
|
|
soc_err_print_u32(rm_path_id);
|
|
}
|
|
|
|
ret = rm_drv_ctrl_destroy(rm_drv_path_ctx_p->rm_handle);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(rm_drv_ctrl_destroy, ret);
|
|
soc_err_print_u32(rm_path_id);
|
|
} else {
|
|
rm_drv_path_ctx_p->rm_handle = TD_INVALID_HANDLE;
|
|
rm_drv_path_ctx_p->event_handle_p = TD_NULL;
|
|
rm_drv_path_ctx_p->chn_enable = TD_FALSE; /* default colse the channel */
|
|
rm_drv_path_ctx_p->queue_cnt = 1;
|
|
rm_drv_path_ctx_p->try_queue_cnt = 0;
|
|
rm_drv_path_ctx_p->free_node = RM_DRV_LIST_NODE_NUM;
|
|
rm_drv_path_ctx_p->used_node = 0;
|
|
rm_drv_path_ctx_p->cur_index = 0;
|
|
rm_drv_path_ctx_p->cur_pid = 0;
|
|
rm_drv_golbal_ctx_p->path_recycle_cnt++;
|
|
soc_log_dbg("path resource leak! recycle succeed!\n");
|
|
soc_dbg_print_u32(rm_path_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
td_s32 rm_drv_ctrl_query_event(td_handle rm_handle, ext_drv_rm_event *rm_event_p)
|
|
{
|
|
td_s32 ret = TD_FAILURE;
|
|
td_u32 rm_path_id = 0;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
ext_drv_rm_event rm_event;
|
|
|
|
if (rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
if (((rm_path_id) = (rm_handle) & 0xff) >= RM_DRV_CHN_MAX_NUM) {
|
|
soc_log_err("rm path id is over range.rm_id = 0x%08X\n", rm_path_id);
|
|
return SOC_ERR_RM_INST_OVER_RANGE;
|
|
}
|
|
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
check_rm_null_ptr(rm_drv_path_ctx_p);
|
|
if (rm_handle != rm_drv_path_ctx_p->rm_handle) {
|
|
soc_log_err("src_rm_handle[%d] is not equal dest_rm_handle[%d].\n", rm_handle, rm_drv_path_ctx_p->rm_handle);
|
|
soc_err_print_h32(rm_handle);
|
|
soc_err_print_h32(rm_drv_path_ctx_p->rm_handle);
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
rm_drv_path_ctx_p->try_queue_cnt++;
|
|
rm_drv_path_ctx_p->lst_query_time = rm_drv_path_ctx_p->cur_query_time;
|
|
rm_drv_comm_get_cur_time(&rm_drv_path_ctx_p->cur_query_time);
|
|
rm_drv_path_ctx_p->query_time_diff = rm_drv_path_ctx_p->cur_query_time - rm_drv_path_ctx_p->lst_query_time;
|
|
rm_drv_path_ctx_p->idle = TD_FALSE;
|
|
|
|
if ((rm_drv_path_ctx_p->list_empty == TD_FALSE) && (rm_drv_path_ctx_p->chn_enable == TD_TRUE)) {
|
|
ret = rm_drv_comm_get_event(rm_drv_path_ctx_p->rm_handle, rm_drv_path_ctx_p->event_handle_p, &rm_event);
|
|
if (ret == TD_SUCCESS) {
|
|
rm_drv_path_ctx_p->queue_cnt++;
|
|
ret = memcpy_s(rm_event_p, sizeof(ext_drv_rm_event), &rm_event, sizeof(rm_event));
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call memcpy_s err!\n");
|
|
return ret;
|
|
}
|
|
soc_log_info("RM event:%d!\n", rm_event_p->win_event);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_init(td_void)
|
|
{
|
|
td_u32 i;
|
|
|
|
soc_info_func_enter();
|
|
/* 初始化上下文 */
|
|
for (i = 0; i < RM_DRV_CHN_MAX_NUM; i++) {
|
|
rm_drv_comm_init_path_ctx(i);
|
|
}
|
|
|
|
rm_drv_comm_init_golbal_ctx();
|
|
(td_void)rm_drv_proc_add();
|
|
|
|
osal_sem_init(&g_rm_drv_mutex, 1);
|
|
soc_info_func_exit();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_void ext_drv_rm_de_init(td_void)
|
|
{
|
|
td_u32 i;
|
|
|
|
soc_info_func_enter();
|
|
/* 初始化上下文 */
|
|
for (i = 0; i < RM_DRV_CHN_MAX_NUM; i++) {
|
|
rm_drv_comm_de_init_path_ctx(i);
|
|
}
|
|
|
|
rm_drv_comm_de_init_golbal_ctx();
|
|
(td_void)rm_drv_proc_del();
|
|
|
|
osal_sem_destroy(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_create(td_handle *rm_handle, td_u32 pid)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 rm_path_id = 0;
|
|
td_void *list_handle_p = TD_NULL;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
rm_drv_list_attr list_attr;
|
|
|
|
soc_info_func_enter();
|
|
check_rm_null_ptr(rm_handle);
|
|
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
ret = rm_drv_ctrl_get_free_path_id(&rm_path_id); /* 检查是否满足创建条件 */
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("get free rm id failed\n");
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
return SOC_ERR_RM_NOT_FREE_INST;
|
|
}
|
|
list_attr.list_node_num = RM_DRV_LIST_NODE_NUM;
|
|
ret = rm_drv_comm_init_event_list(&list_attr, &list_handle_p);
|
|
if (ret == TD_SUCCESS) { /* 返回生成的handle号 */
|
|
*rm_handle = ((SOC_ID_RM << 8) | rm_path_id); /* 8 means letf sheft 8 bit */
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
check_rm_null_ptr(rm_drv_path_ctx_p);
|
|
rm_drv_path_ctx_p->rm_handle = *rm_handle;
|
|
rm_drv_path_ctx_p->event_handle_p = list_handle_p;
|
|
rm_drv_path_ctx_p->chn_enable = TD_FALSE; /* default colse the channel */
|
|
rm_drv_path_ctx_p->queue_cnt = 1;
|
|
rm_drv_path_ctx_p->try_queue_cnt = 0;
|
|
rm_drv_path_ctx_p->free_node = RM_DRV_LIST_NODE_NUM;
|
|
rm_drv_path_ctx_p->used_node = 0;
|
|
rm_drv_path_ctx_p->cur_index = 0;
|
|
rm_drv_path_ctx_p->cur_pid = pid;
|
|
rm_drv_path_ctx_p->list_empty = TD_TRUE;
|
|
rm_drv_path_ctx_p->idle = TD_FALSE;
|
|
rm_drv_path_ctx_p->cur_query_time = 0;
|
|
rm_drv_path_ctx_p->lst_query_time = 0;
|
|
rm_drv_path_ctx_p->query_time_diff = 0;
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
check_rm_null_ptr(rm_drv_golbal_ctx_p);
|
|
rm_drv_golbal_ctx_p->rm_path_count++;
|
|
rm_drv_golbal_ctx_p->chn_create_cnt[rm_path_id]++;
|
|
}
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_destroy(td_handle rm_handle)
|
|
{
|
|
td_s32 ret;
|
|
|
|
soc_info_func_enter();
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
ret = rm_drv_ctrl_destroy(rm_handle);
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_enable(td_handle rm_handle)
|
|
{
|
|
td_u32 rm_path_id = 0;
|
|
td_s32 ret = TD_SUCCESS;
|
|
rm_drv_path_ctx *rm_drv_path_ctx_p = TD_NULL;
|
|
|
|
soc_info_func_enter();
|
|
if (rm_handle == TD_INVALID_HANDLE) {
|
|
soc_log_err("rm handle is invalid.\n");
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
if (((rm_path_id) = (rm_handle) & 0xff) >= RM_DRV_CHN_MAX_NUM) {
|
|
soc_log_err("rm path id is over range.rm_id = 0x%08X\n", rm_path_id);
|
|
return SOC_ERR_RM_INST_OVER_RANGE;
|
|
}
|
|
|
|
rm_drv_comm_get_path_ctx(rm_path_id, &rm_drv_path_ctx_p);
|
|
check_rm_null_ptr(rm_drv_path_ctx_p);
|
|
if (rm_handle != rm_drv_path_ctx_p->rm_handle) {
|
|
soc_log_err("src_rm_handle[%d] is not equal dest_rm_handle[%d].\n", rm_handle, rm_drv_path_ctx_p->rm_handle);
|
|
soc_err_print_h32(rm_handle);
|
|
soc_err_print_h32(rm_drv_path_ctx_p->rm_handle);
|
|
return SOC_ERR_RM_INVALID_HANDLE;
|
|
}
|
|
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
|
|
if (rm_drv_path_ctx_p->chn_enable != TD_TRUE) {
|
|
rm_drv_path_ctx_p->chn_enable = TD_TRUE;
|
|
} else {
|
|
soc_log_err("path is already enable!\n");
|
|
soc_err_print_u32(rm_path_id);
|
|
ret = SOC_ERR_RM_ENABLE_ERR;
|
|
}
|
|
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_disable(td_handle rm_handle)
|
|
{
|
|
td_s32 ret;
|
|
|
|
soc_info_func_enter();
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
ret = rm_drv_ctrl_disable(rm_handle);
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_query_event(td_handle rm_handle, ext_drv_rm_event *rm_event_p)
|
|
{
|
|
td_s32 ret;
|
|
|
|
check_rm_null_ptr(rm_event_p);
|
|
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
ret = rm_drv_ctrl_query_event(rm_handle, rm_event_p);
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 rm_wait_condition(const void *data)
|
|
{
|
|
if (*(td_bool *)data == TD_TRUE) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_acquire_window_handle(td_u32 pid)
|
|
{
|
|
td_s32 remain_time = 10;
|
|
td_s32 ret;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
|
|
soc_info_func_enter();
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
check_rm_null_ptr(rm_drv_golbal_ctx_p);
|
|
rm_drv_ctrl_check_idle_path();
|
|
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
rm_drv_ctrl_recycle_idle_path();
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
|
|
if (rm_drv_golbal_ctx_p->rm_available_win_count > 0) {
|
|
rm_drv_golbal_ctx_p->normal_cnt++;
|
|
rm_drv_golbal_ctx_p->win_owner_id = pid;
|
|
soc_info_func_exit();
|
|
return TD_SUCCESS;
|
|
} else {
|
|
/* set waiting event flag true */
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
rm_drv_golbal_ctx_p->waiting_event = TD_TRUE;
|
|
ret = rm_drv_ctrl_put_win_event_to_list(EXT_DRV_RM_EVENT_WIN_LACK);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_dbg("put event to list error!\n");
|
|
rm_drv_ctrl_recycle_path_resource();
|
|
}
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
remain_time = osal_wait_timeout_interruptible(&rm_drv_golbal_ctx_p->wait_queue, rm_wait_condition,
|
|
&rm_drv_golbal_ctx_p->wake_up_flags, (HZ * 5)); /* (HZ * 5) means the max sleep time */
|
|
if (remain_time > 0) { /* 大于零表示非timeout */
|
|
rm_drv_golbal_ctx_p->wake_up_cnt++;
|
|
rm_drv_golbal_ctx_p->wake_up_time = remain_time;
|
|
rm_drv_golbal_ctx_p->wake_up_flags = TD_FALSE;
|
|
rm_drv_golbal_ctx_p->waiting_event = TD_FALSE;
|
|
rm_drv_golbal_ctx_p->win_owner_id = pid;
|
|
soc_info_func_exit();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
}
|
|
soc_log_err("acquire window resource failed,waiting time out.\n");
|
|
soc_err_print_u32(remain_time);
|
|
soc_info_func_exit();
|
|
|
|
return SOC_ERR_RM_NOT_RESOURCE;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_notify_wind_created(td_handle win_handle)
|
|
{
|
|
td_s32 ret;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
|
|
soc_info_func_enter();
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
check_rm_null_ptr(rm_drv_golbal_ctx_p);
|
|
rm_drv_golbal_ctx_p->rm_available_win_count--;
|
|
soc_info_print_s32(rm_drv_golbal_ctx_p->rm_available_win_count);
|
|
|
|
ret = rm_drv_ctrl_put_win_event_to_list(EXT_DRV_RM_EVENT_WIN_CREATED);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_dbg("put event to list error!\n");
|
|
rm_drv_ctrl_recycle_path_resource();
|
|
}
|
|
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_s32 ext_drv_rm_notify_wind_destroyed(td_handle win_handle)
|
|
{
|
|
td_s32 ret;
|
|
rm_drv_golbal_ctx *rm_drv_golbal_ctx_p = TD_NULL;
|
|
|
|
soc_info_func_enter();
|
|
osal_sem_down(&g_rm_drv_mutex);
|
|
|
|
rm_drv_comm_get_golbal_ctx(&rm_drv_golbal_ctx_p);
|
|
check_rm_null_ptr(rm_drv_golbal_ctx_p);
|
|
rm_drv_golbal_ctx_p->rm_available_win_count++;
|
|
soc_info_print_s32(rm_drv_golbal_ctx_p->rm_available_win_count);
|
|
rm_drv_golbal_ctx_p->wake_up_flags = TD_FALSE;
|
|
|
|
if (rm_drv_golbal_ctx_p->waiting_event) {
|
|
rm_drv_ctrl_wake_up_waiting_event();
|
|
}
|
|
|
|
ret = rm_drv_ctrl_put_win_event_to_list(EXT_DRV_RM_EVENT_WIN_DESTROYED);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_dbg("put event to list error!\n");
|
|
rm_drv_ctrl_recycle_path_resource();
|
|
}
|
|
|
|
osal_sem_up(&g_rm_drv_mutex);
|
|
soc_info_func_exit();
|
|
|
|
return ret;
|
|
}
|
|
|