760 lines
21 KiB
C
760 lines
21 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2019 Realtek Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
*****************************************************************************/
|
|
#define _TEST_MODULE_C_
|
|
|
|
#ifdef CONFIG_PHL_TEST_SUITE
|
|
#include "../phl_headers.h"
|
|
|
|
#define MAX_TEST_OBJ_NUM 128
|
|
#define THREAD_SLEEP_UNIT 1000 /* ms */
|
|
#define MAX_TEST_CMD_BUF 2000
|
|
|
|
#define TEST_MGNT_ALREADY_INIT(_test_mgnt) \
|
|
((_test_mgnt) && TEST_STATUS_FLAG((_test_mgnt)->status,TM_STATUS_INIT))
|
|
#define IS_TEST_MGNT_ALLOC(_phl_com) ((_phl_com) && ((_phl_com)->test_mgnt))
|
|
|
|
enum TEST_MGNT_STATUS_FALGS{
|
|
TM_STATUS_INIT = BIT0,
|
|
TM_STATUS_FORCE_STOP = BIT1,
|
|
TM_STATUS_THREAD_START = BIT2
|
|
};
|
|
|
|
enum TEST_OBJ_STATUS_FALGS{
|
|
/* regular status*/
|
|
TO_STATUS_PASS = BIT0,
|
|
TO_STATUS_FAIL = BIT1,
|
|
TO_STATUS_ENQ = BIT2,
|
|
TO_STATUS_RUNNING = BIT3,
|
|
/* process error status*/
|
|
TO_STATUS_RUN_THREAD_FAIL = BIT24,
|
|
TO_STATUS_TIMEOUT = BIT25,
|
|
};
|
|
|
|
struct test_object_ex {
|
|
struct test_object test_obj;
|
|
u32 start_time;
|
|
u32 end_time;
|
|
u32 status;
|
|
struct rtw_phl_handler handler;
|
|
void* test_mgnt;
|
|
_os_thread objthread;
|
|
u8 submd_obj_id;
|
|
u8 submd_test_mode;
|
|
};
|
|
|
|
struct test_obj_queue {
|
|
_os_list q;
|
|
_os_mutex lock;
|
|
};
|
|
|
|
struct test_mgnt_info{
|
|
struct test_obj_queue idle_queue;
|
|
struct test_obj_queue busy_queue;
|
|
struct test_obj_queue rpt_queue;
|
|
struct test_obj_queue err_queue;
|
|
struct test_object_ex test_obj_pool[MAX_TEST_OBJ_NUM];
|
|
struct test_object_ex *cur_test_obj;
|
|
s32 max_run_time[TEST_LVL_MAX];
|
|
_os_thread thread;
|
|
u32 status;
|
|
_os_sema busy_chk;
|
|
struct rtw_phl_com_t *phl_com;
|
|
struct phl_info_t *phl;
|
|
void *hal;
|
|
|
|
/* test module context root */
|
|
void *mp_ctx;
|
|
void *ver_ctx;
|
|
};
|
|
|
|
struct test_module_cmd {
|
|
u8 type;
|
|
u8 buf[MAX_TEST_CMD_BUF];
|
|
u16 len;
|
|
};
|
|
|
|
struct test_module_info {
|
|
u8 tm_type;
|
|
u8 tm_mode;
|
|
};
|
|
|
|
static void _init_test_obj_queue(void *d, struct test_obj_queue *queue)
|
|
{
|
|
INIT_LIST_HEAD(&queue->q);
|
|
_os_mutex_init(d, &queue->lock);
|
|
}
|
|
|
|
static void _deinit_test_obj_queue(void *d, struct test_obj_queue *queue)
|
|
{
|
|
_os_mutex_deinit(d, &queue->lock);
|
|
}
|
|
|
|
static int _enqueue_obj(void *d,
|
|
struct test_obj_queue *queue, struct test_object_ex *obj)
|
|
{
|
|
_os_mutex_lock(d, &queue->lock);
|
|
list_add_tail(&(obj->test_obj.list), &queue->q);
|
|
_os_mutex_unlock(d, &queue->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static u8 _dequeue_head_obj(void *d,
|
|
struct test_obj_queue *queue, struct test_object_ex **obj)
|
|
{
|
|
(*obj) = NULL;
|
|
if(list_empty(&(queue->q)))
|
|
return false;
|
|
_os_mutex_lock(d, &queue->lock);
|
|
(*obj) = list_first_entry(&(queue->q),
|
|
struct test_object_ex, test_obj.list);
|
|
list_del(&((*obj)->test_obj.list));
|
|
_os_mutex_unlock(d, &queue->lock);
|
|
return ((*obj) == NULL|| ((struct list_head*)(*obj)) == &(queue->q)) ? \
|
|
(false) : (true);
|
|
}
|
|
|
|
int run_test(void *testobj)
|
|
{
|
|
struct test_object_ex *obj = (struct test_object_ex *)testobj;
|
|
struct test_mgnt_info *test_mgnt = obj->test_mgnt;
|
|
u8 ret = false;
|
|
u32 start_time = 0;
|
|
u32 end_time = 0;
|
|
void *d = test_mgnt->phl_com->drv_priv;
|
|
/* -1: no limit, 0: not set use default value */
|
|
s32 limit = obj->test_obj.total_time_ms;
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
|
|
if (obj->test_obj.total_time_ms != -1) {
|
|
limit = (obj->test_obj.total_time_ms) ? \
|
|
(obj->test_obj.total_time_ms) : \
|
|
(test_mgnt->max_run_time[obj->test_obj.run_lvl]);
|
|
}
|
|
|
|
SET_STATUS_FLAG(obj->status, TO_STATUS_RUNNING);
|
|
|
|
pstatus = phl_schedule_handler(test_mgnt->phl_com, &(obj->handler));
|
|
|
|
if (RTW_PHL_STATUS_SUCCESS != pstatus) {
|
|
SET_STATUS_FLAG(obj->status, TO_STATUS_RUN_THREAD_FAIL);
|
|
CLEAR_STATUS_FLAG(obj->status, TO_STATUS_RUNNING);
|
|
return 0;
|
|
}
|
|
start_time = _os_get_cur_time_us();
|
|
/*wait test end*/
|
|
while (!(obj->test_obj.ctrl.is_test_end(obj->test_obj.priv))) {
|
|
end_time = _os_get_cur_time_us();
|
|
if ((limit >= 0) && ((s32)((end_time-start_time)/1000) >= limit)) {
|
|
SET_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT);
|
|
obj->end_time = end_time;
|
|
break;
|
|
}
|
|
_os_sleep_us(test_mgnt->phl_com->drv_priv, THREAD_SLEEP_UNIT);
|
|
}
|
|
if (!TEST_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT))
|
|
obj->end_time = _os_get_cur_time_us();
|
|
|
|
ret = obj->test_obj.ctrl.is_test_pass(obj->test_obj.priv);
|
|
|
|
SET_STATUS_FLAG(obj->status, (!ret) ? \
|
|
(TO_STATUS_FAIL) : (TO_STATUS_PASS));
|
|
|
|
_enqueue_obj(d, &(test_mgnt->rpt_queue), obj);
|
|
|
|
if (obj->submd_test_mode == INTGR_TEST_MODE) {
|
|
if (!_os_thread_check_stop(d, &(obj->objthread)))
|
|
_os_thread_wait_stop(d, &obj->objthread);
|
|
}
|
|
|
|
CLEAR_STATUS_FLAG(obj->status, TO_STATUS_RUNNING);
|
|
PHL_INFO("[TM]: obj thread (%s) stop.\n", obj->test_obj.name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int test_thread(void *param)
|
|
{
|
|
struct test_mgnt_info *test_mgnt
|
|
= (struct test_mgnt_info *)phl_container_of(param,
|
|
struct test_mgnt_info,
|
|
thread);
|
|
void *d = NULL;
|
|
struct test_object_ex *obj;
|
|
|
|
if (!IS_TEST_MGNT_ALLOC(test_mgnt->phl_com))
|
|
return 0;
|
|
|
|
d = test_mgnt->phl_com->drv_priv;
|
|
if (!TEST_MGNT_ALREADY_INIT(test_mgnt)) {
|
|
PHL_ERR("[TM]: return.\n");
|
|
return 0;
|
|
}
|
|
PHL_INFO("[TM]: thread started.\n");
|
|
SET_STATUS_FLAG(test_mgnt->status, TM_STATUS_THREAD_START);
|
|
|
|
while (!TEST_STATUS_FLAG(test_mgnt->status, TM_STATUS_FORCE_STOP)) {
|
|
_os_sema_down(d, &(test_mgnt->busy_chk));
|
|
if (TEST_STATUS_FLAG(test_mgnt->status, TM_STATUS_FORCE_STOP))
|
|
break;
|
|
while (_dequeue_head_obj(d, &(test_mgnt->busy_queue),
|
|
&(test_mgnt->cur_test_obj))) {
|
|
_os_thread *thread = NULL;
|
|
obj = test_mgnt->cur_test_obj;
|
|
CLEAR_STATUS_FLAG(obj->status, TO_STATUS_ENQ);
|
|
|
|
if (obj->submd_test_mode == UNIT_TEST_MODE) {
|
|
PHL_INFO("[TM]: %s UNIT_TEST_MODE \n", __FUNCTION__);
|
|
run_test(obj);
|
|
} else if (obj->submd_test_mode == INTGR_TEST_MODE) {
|
|
PHL_INFO("[TM]: %s INTGR_TEST_MODE \n", __FUNCTION__);
|
|
thread = &obj->objthread;
|
|
_os_thread_init(d, thread, run_test, obj, obj->test_obj.name);
|
|
_os_thread_schedule(d, thread);
|
|
}
|
|
test_mgnt->cur_test_obj = NULL;
|
|
}
|
|
}
|
|
_os_thread_wait_stop(d, &test_mgnt->thread);
|
|
CLEAR_STATUS_FLAG(test_mgnt->status, TM_STATUS_THREAD_START);
|
|
PHL_INFO("[TM]: test mgnt thread is down\n");
|
|
return 0;
|
|
}
|
|
|
|
static void _test_submodule_deinit(void *tm)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)tm;
|
|
|
|
phl_test_mp_deinit(test_mgnt->mp_ctx);
|
|
phl_test_verify_deinit(test_mgnt->ver_ctx);
|
|
}
|
|
|
|
u8 phl_test_module_init(struct phl_info_t *phl_info)
|
|
{
|
|
struct rtw_phl_com_t* phl_com = phl_info->phl_com;
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
void *d = NULL;
|
|
u8 i = 0;
|
|
|
|
if(phl_com==NULL)
|
|
goto _test_module_mem;
|
|
d = phl_com->drv_priv;
|
|
|
|
test_mgnt = (struct test_mgnt_info *)_os_mem_alloc(d,
|
|
sizeof(struct test_mgnt_info));
|
|
if (test_mgnt == NULL)
|
|
goto _test_module_mem;
|
|
_os_mem_set(d, test_mgnt, 0, sizeof(struct test_mgnt_info));
|
|
phl_com->test_mgnt = test_mgnt;
|
|
test_mgnt->phl_com = phl_com;
|
|
test_mgnt->phl = phl_info;
|
|
test_mgnt->hal = phl_info->hal;
|
|
|
|
for(i = 0; i < MAX_TEST_OBJ_NUM; i++)
|
|
test_mgnt->test_obj_pool[i].submd_obj_id = TEST_SUB_MODULE_UNKNOWN;
|
|
|
|
if (phl_test_mp_alloc(test_mgnt->phl, test_mgnt->hal, &(test_mgnt->mp_ctx)) != RTW_PHL_STATUS_SUCCESS) {
|
|
PHL_INFO("[TM]: %s phl_test_mp_alloc fail!\n",__FUNCTION__);
|
|
goto _mp_module_mem;
|
|
}
|
|
|
|
if(phl_test_verify_alloc(test_mgnt->phl, test_mgnt->hal, &(test_mgnt->ver_ctx)) != RTW_PHL_STATUS_SUCCESS) {
|
|
PHL_INFO("[TM]: %s phl_test_verify_alloc fail!\n",__FUNCTION__);
|
|
goto _verify_module_mem;
|
|
}
|
|
|
|
PHL_INFO("[TM]: %s\n",__FUNCTION__);
|
|
return true;
|
|
|
|
_verify_module_mem:
|
|
phl_test_mp_free(&test_mgnt->mp_ctx);
|
|
_mp_module_mem:
|
|
_os_mem_free(d, test_mgnt, sizeof(struct test_mgnt_info));
|
|
_test_module_mem:
|
|
return false;
|
|
}
|
|
|
|
void phl_test_module_deinit(struct rtw_phl_com_t* phl_com)
|
|
{
|
|
void *d = NULL;
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return;
|
|
d = phl_com->drv_priv;
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
|
|
if(TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
phl_test_module_stop(phl_com);
|
|
|
|
phl_test_mp_free(&test_mgnt->mp_ctx);
|
|
phl_test_verify_free(&test_mgnt->ver_ctx);
|
|
_os_mem_free(d, test_mgnt, sizeof(struct test_mgnt_info));
|
|
phl_com->test_mgnt = NULL;
|
|
PHL_INFO("[TM]: %s\n",__FUNCTION__);
|
|
}
|
|
|
|
u8 phl_test_module_start(struct rtw_phl_com_t* phl_com)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
_os_thread *thread = NULL;
|
|
void *d = NULL;
|
|
u32 i = 0;
|
|
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return false;
|
|
d = phl_com->drv_priv;
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
|
|
if(TEST_MGNT_ALREADY_INIT(test_mgnt)) {
|
|
PHL_INFO("[TM]: %s, already initialized\n",__FUNCTION__);
|
|
return true;
|
|
}
|
|
test_mgnt->status = 0;
|
|
_init_test_obj_queue(d, &(test_mgnt->busy_queue));
|
|
_init_test_obj_queue(d, &(test_mgnt->idle_queue));
|
|
_init_test_obj_queue(d, &(test_mgnt->rpt_queue));
|
|
_init_test_obj_queue(d, &(test_mgnt->err_queue));
|
|
|
|
/*insert all elements in obj pool into idle Q*/
|
|
for(i = 0; i < MAX_TEST_OBJ_NUM;i++) {
|
|
test_mgnt->test_obj_pool[i].submd_obj_id = TEST_SUB_MODULE_UNKNOWN;
|
|
_enqueue_obj(d, &(test_mgnt->idle_queue),
|
|
&(test_mgnt->test_obj_pool[i]));
|
|
}
|
|
test_mgnt->max_run_time[TEST_LVL_LOW] = TEST_LVL_LOW_TO;
|
|
test_mgnt->max_run_time[TEST_LVL_NORMAL] = TEST_LVL_NORMAL_TO;
|
|
test_mgnt->max_run_time[TEST_LVL_HIGH] = TEST_LVL_HIGH_TO;
|
|
SET_STATUS_FLAG(test_mgnt->status, TM_STATUS_INIT);
|
|
|
|
thread = &(test_mgnt->thread);
|
|
_os_sema_init(d, &(test_mgnt->busy_chk), 0);
|
|
_os_thread_init(d, thread, test_thread, thread, "test_thread");
|
|
_os_thread_schedule(d, thread);
|
|
PHL_INFO("[TM]: %s\n",__FUNCTION__);
|
|
return true;
|
|
}
|
|
|
|
void phl_test_module_stop(struct rtw_phl_com_t* phl_com)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
void *d = NULL;
|
|
u32 i = 0;
|
|
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return;
|
|
d = phl_com->drv_priv;
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
|
|
if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
return;
|
|
|
|
/* Call all sub module deinit */
|
|
_test_submodule_deinit(test_mgnt);
|
|
|
|
SET_STATUS_FLAG(test_mgnt->status, TM_STATUS_FORCE_STOP);
|
|
_os_thread_stop(d, &(test_mgnt->thread));
|
|
_os_sema_up(d, &(test_mgnt->busy_chk));
|
|
/*wait thread stop*/
|
|
PHL_INFO("[TM]: %s stop test_thread\n",__FUNCTION__);
|
|
_os_thread_deinit(d, &(test_mgnt->thread));
|
|
_os_sema_free(d, &(test_mgnt->busy_chk));
|
|
/*clean up test obj resource*/
|
|
for (i = 0; i < MAX_TEST_OBJ_NUM; i++) {
|
|
struct test_object_ex *obj = &(test_mgnt->test_obj_pool[i]);
|
|
if (obj->submd_obj_id != TEST_SUB_MODULE_UNKNOWN && obj->status != TO_STATUS_ENQ) {
|
|
if (obj->submd_test_mode == INTGR_TEST_MODE) {
|
|
if (!_os_thread_check_stop(d, &(obj->objthread))) {
|
|
_os_thread_stop(d, &(obj->objthread));
|
|
_os_thread_deinit(d, &(obj->objthread));
|
|
}
|
|
}
|
|
phl_deregister_handler(phl_com, &(obj->handler));
|
|
}
|
|
}
|
|
/*no need to empty test obj Q before deinit*/
|
|
_deinit_test_obj_queue(d, &(test_mgnt->busy_queue));
|
|
_deinit_test_obj_queue(d, &(test_mgnt->idle_queue));
|
|
_deinit_test_obj_queue(d, &(test_mgnt->rpt_queue));
|
|
_deinit_test_obj_queue(d, &(test_mgnt->err_queue));
|
|
CLEAR_STATUS_FLAG(test_mgnt->status, TM_STATUS_INIT);
|
|
PHL_INFO("[TM]: %s\n",__FUNCTION__);
|
|
}
|
|
|
|
u8
|
|
rtw_phl_test_set_max_run_time(struct rtw_phl_com_t* phl_com,
|
|
enum TEST_RUN_LVL lvl,
|
|
u32 timeout_ms)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return false;
|
|
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
return false;
|
|
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
test_mgnt->max_run_time[lvl] = timeout_ms;
|
|
return true;
|
|
}
|
|
|
|
void setup_test_rpt(void *d, struct test_rpt* rpt,struct test_object_ex *obj)
|
|
{
|
|
char str[] = "Exceed Time Limit";
|
|
char str2[] = "Test not run";
|
|
char str3[] = "None";
|
|
_os_mem_cpy(d, rpt->name, obj->test_obj.name, TEST_NAME_LEN);
|
|
|
|
if(TEST_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT)) {
|
|
_os_mem_cpy(d, rpt->rsn, str, sizeof(str));
|
|
rpt->status = 0;
|
|
rpt->total_time = (u32)((obj->end_time - obj->start_time)/1000);
|
|
}
|
|
else if(TEST_STATUS_FLAG(obj->status, TO_STATUS_RUN_THREAD_FAIL)) {
|
|
_os_mem_cpy(d, rpt->rsn, str2, sizeof(str2));
|
|
rpt->status = 0;
|
|
rpt->total_time = 0;
|
|
}
|
|
else{
|
|
obj->test_obj.ctrl.get_fail_rsn(obj->test_obj.priv,
|
|
(char*)&(rpt->rsn[0]), TEST_NAME_LEN-1);
|
|
if(_os_strlen((u8*)rpt->rsn) <= 0)
|
|
_os_mem_cpy(d, rpt->rsn, str3, sizeof(str3));
|
|
if (TEST_STATUS_FLAG(obj->status, TO_STATUS_PASS))
|
|
rpt->status = 1;
|
|
else
|
|
rpt->status = 0;
|
|
rpt->total_time = (u32)((obj->end_time - obj->start_time)/1000);
|
|
}
|
|
}
|
|
|
|
u8 rtw_phl_test_get_rpt(struct rtw_phl_com_t* phl_com, u8* buf, u32 len)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
struct test_object_ex *obj = NULL;
|
|
u32 rpt_size = sizeof(struct test_rpt);
|
|
void *d = NULL;
|
|
u8 is_rpt_empty = true;
|
|
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return false;
|
|
|
|
d = phl_com->drv_priv;
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
return false;
|
|
|
|
while (len >= rpt_size) {
|
|
if(_dequeue_head_obj(d, &(test_mgnt->rpt_queue), &obj)) {
|
|
is_rpt_empty = false;
|
|
|
|
setup_test_rpt(d, (struct test_rpt*)buf, obj);
|
|
|
|
if (TEST_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT))
|
|
_enqueue_obj(d, &(test_mgnt->err_queue), obj);
|
|
else {
|
|
if (obj->submd_test_mode == INTGR_TEST_MODE) {
|
|
if (!_os_thread_check_stop(d, &(obj->objthread))) {
|
|
PHL_INFO("[TM]: %s obj thread (%s) stop.\n",
|
|
__FUNCTION__,
|
|
obj->test_obj.name);
|
|
_os_thread_stop(d, &(obj->objthread));
|
|
_os_thread_deinit(d, &(obj->objthread));
|
|
}
|
|
}
|
|
phl_deregister_handler(phl_com, &(obj->handler));
|
|
obj->status = 0;
|
|
obj->submd_obj_id = TEST_SUB_MODULE_UNKNOWN;
|
|
_enqueue_obj(d, &(test_mgnt->idle_queue), obj);
|
|
}
|
|
buf += rpt_size;
|
|
len -= rpt_size;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return (is_rpt_empty)?(false):(true);
|
|
}
|
|
|
|
u8 rtw_phl_test_is_test_complete(struct rtw_phl_com_t* phl_com)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
void *d = NULL;
|
|
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return false;
|
|
|
|
d = phl_com->drv_priv;
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
return false;
|
|
if (list_empty(&(test_mgnt->busy_queue.q)) && !(test_mgnt->cur_test_obj))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static void _test_obj_thread_callback(void *context)
|
|
{
|
|
struct rtw_phl_handler *phl_handler
|
|
= (struct rtw_phl_handler *)phl_container_of(context,
|
|
struct rtw_phl_handler,
|
|
os_handler);
|
|
struct test_object_ex *obj = (struct test_object_ex *)phl_handler->context;
|
|
obj->start_time = _os_get_cur_time_us();
|
|
obj->test_obj.ctrl.start_test(obj->test_obj.priv);
|
|
}
|
|
|
|
u8 init_obj_thread(struct test_mgnt_info *test_mgnt,
|
|
struct test_object_ex *obj,
|
|
enum TEST_RUN_LVL lvl)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
|
|
switch(lvl){
|
|
case TEST_LVL_LOW:
|
|
case TEST_LVL_NORMAL:
|
|
obj->handler.type = RTW_PHL_HANDLER_PRIO_LOW;
|
|
break;
|
|
case TEST_LVL_HIGH:
|
|
obj->handler.type = RTW_PHL_HANDLER_PRIO_HIGH;
|
|
break;
|
|
case TEST_LVL_NONE:
|
|
case TEST_LVL_MAX:
|
|
PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "init_obj_thread(): Unsupported case:%d, please check it\n",
|
|
lvl);
|
|
break;
|
|
default:
|
|
PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "init_obj_thread(): Unrecognize case:%d, please check it\n",
|
|
lvl);
|
|
break;
|
|
}
|
|
obj->handler.callback = _test_obj_thread_callback;
|
|
obj->handler.context = obj;
|
|
obj->handler.drv_priv = test_mgnt->phl_com->drv_priv;
|
|
pstatus = phl_register_handler(test_mgnt->phl_com, &(obj->handler));
|
|
return (RTW_PHL_STATUS_SUCCESS != pstatus) ? (false) : (true);
|
|
}
|
|
|
|
u8 rtw_phl_test_add_new_test_obj(struct rtw_phl_com_t *phl_com,
|
|
char *name,
|
|
void *custom_priv,
|
|
enum TEST_RUN_LVL lvl,
|
|
struct test_obj_ctrl_interface *ctrl_intf,
|
|
s32 total_time_ms,
|
|
u8 submd_id,
|
|
u8 test_mode)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
struct test_object_ex *obj = NULL;
|
|
void *d = NULL;
|
|
u8 i;
|
|
u8 is_idle_empty = true;
|
|
u32 name_len = (_os_strlen((u8 *)name) > (u32)(TEST_NAME_LEN - 1)) ?\
|
|
((u32)(TEST_NAME_LEN - 1)) :\
|
|
(_os_strlen((u8 *)name) + 1);
|
|
|
|
if (!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return false;
|
|
|
|
d = phl_com->drv_priv;
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
if (!TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
return false;
|
|
|
|
for (i = 0; i < MAX_TEST_OBJ_NUM; i++) {
|
|
obj = &(test_mgnt->test_obj_pool[i]);
|
|
if (obj->submd_obj_id == submd_id && obj->status == TO_STATUS_RUNNING) {
|
|
PHL_INFO("%s() Error same submd id %d\n", __func__, obj->submd_obj_id);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (_dequeue_head_obj(d, &(test_mgnt->idle_queue), &obj)) {
|
|
is_idle_empty = false;
|
|
if (TEST_STATUS_FLAG(obj->status, TO_STATUS_ENQ))
|
|
phl_deregister_handler(phl_com, &(obj->handler));
|
|
/*cleanup entire test obj before reuse*/
|
|
_os_mem_set(d, obj, 0, sizeof(struct test_object_ex));
|
|
|
|
_os_mem_cpy(d, &(obj->test_obj.ctrl), ctrl_intf,
|
|
sizeof(struct test_obj_ctrl_interface));
|
|
|
|
_os_mem_cpy(d, &(obj->test_obj.name[0]), name, name_len);
|
|
obj->test_obj.priv = custom_priv;
|
|
obj->test_obj.run_lvl = lvl;
|
|
obj->test_mgnt = test_mgnt;
|
|
obj->test_obj.total_time_ms = (lvl <= TEST_LVL_LOW) ?\
|
|
(total_time_ms) : (0);
|
|
obj->submd_obj_id = submd_id;
|
|
obj->submd_test_mode = test_mode;
|
|
|
|
if (init_obj_thread(test_mgnt, obj, lvl)) {
|
|
SET_STATUS_FLAG(obj->status, TO_STATUS_ENQ);
|
|
_enqueue_obj(d, &(test_mgnt->busy_queue), obj);
|
|
_os_sema_up(d, &(test_mgnt->busy_chk));
|
|
PHL_INFO("[TM]: %s, id %u EnQ\n", __FUNCTION__, submd_id);
|
|
} else {
|
|
_enqueue_obj(d, &(test_mgnt->idle_queue), obj);
|
|
PHL_INFO("[TM]: %s, id %u EnQ fail\n", __FUNCTION__, submd_id);
|
|
}
|
|
}
|
|
if (is_idle_empty || !TEST_STATUS_FLAG(obj->status, TO_STATUS_ENQ))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
u8
|
|
rtw_phl_test_setup_bp(struct rtw_phl_com_t* phl_com,
|
|
struct test_bp_info* bp_info,
|
|
u8 submdid)
|
|
{
|
|
u8 i;
|
|
struct test_mgnt_info *test_mgnt = NULL;
|
|
struct test_object_ex *obj = NULL;
|
|
if(!IS_TEST_MGNT_ALLOC(phl_com))
|
|
return false;
|
|
|
|
test_mgnt = phlcom_to_test_mgnt(phl_com);
|
|
|
|
for (i = 0; i < MAX_TEST_OBJ_NUM; i++) {
|
|
obj = &(test_mgnt->test_obj_pool[i]);
|
|
if (obj->submd_obj_id == submdid && TEST_STATUS_FLAG(obj->status, TO_STATUS_RUNNING)) {
|
|
PHL_DBG("%s() objid = %d setup bp\n", __func__, obj->submd_obj_id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
|
|
return false;
|
|
|
|
return (obj && TEST_STATUS_FLAG(obj->status, TO_STATUS_RUNNING))?\
|
|
(obj->test_obj.ctrl.bp_handler(obj->test_obj.priv, bp_info)):\
|
|
(BP_RET_RUN_ORIGIN_SEC);
|
|
}
|
|
|
|
void rtw_phl_test_submodule_init(struct rtw_phl_com_t* phl_com, void *buf)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
|
|
struct test_module_info *tm_info = NULL;
|
|
|
|
if(buf == NULL)
|
|
return;
|
|
|
|
tm_info = (struct test_module_info *)buf;
|
|
|
|
switch(tm_info->tm_type) {
|
|
case TEST_SUB_MODULE_MP:
|
|
phl_test_mp_init(test_mgnt->mp_ctx);
|
|
phl_test_mp_start(test_mgnt->mp_ctx, tm_info->tm_mode);
|
|
break;
|
|
case TEST_SUB_MODULE_VERIFY:
|
|
phl_test_verify_init(test_mgnt->ver_ctx);
|
|
phl_test_verify_start(test_mgnt->ver_ctx);
|
|
break;
|
|
case TEST_SUB_MODULE_FPGA:
|
|
case TEST_SUB_MODULE_TOOL:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void rtw_phl_test_submodule_deinit(struct rtw_phl_com_t* phl_com, void *buf)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
|
|
struct test_module_info *tm_info = NULL;
|
|
|
|
if(buf == NULL)
|
|
return;
|
|
|
|
tm_info = (struct test_module_info *)buf;
|
|
|
|
switch(tm_info->tm_type) {
|
|
case TEST_SUB_MODULE_MP:
|
|
phl_test_mp_stop(test_mgnt->mp_ctx, tm_info->tm_mode);
|
|
phl_test_mp_deinit(test_mgnt->mp_ctx);
|
|
break;
|
|
case TEST_SUB_MODULE_VERIFY:
|
|
phl_test_verify_stop(test_mgnt->ver_ctx);
|
|
phl_test_verify_deinit(test_mgnt->ver_ctx);
|
|
break;
|
|
case TEST_SUB_MODULE_FPGA:
|
|
case TEST_SUB_MODULE_TOOL:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
rtw_phl_test_submodule_cmd_process(struct rtw_phl_com_t* phl_com,
|
|
void *buf,
|
|
u32 buf_len)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
|
|
struct test_module_cmd *cmd = NULL;
|
|
u8 type = TEST_SUB_MODULE_UNKNOWN;
|
|
|
|
if(buf == NULL)
|
|
return;
|
|
|
|
cmd = (struct test_module_cmd *)buf;
|
|
type = cmd->type;
|
|
/* debug_dump_data(cmd->buf, MAX_TEST_CMD_BUF, "[TM] cmd buf ="); */
|
|
PHL_INFO("%s: len = %d\n", __FUNCTION__, cmd->len);
|
|
|
|
switch(type) {
|
|
case TEST_SUB_MODULE_MP:
|
|
phl_test_mp_cmd_process(test_mgnt->mp_ctx, cmd->buf, cmd->len, TEST_SUB_MODULE_MP);
|
|
break;
|
|
case TEST_SUB_MODULE_VERIFY:
|
|
phl_test_verify_cmd_process(test_mgnt->ver_ctx, cmd->buf, cmd->len, TEST_SUB_MODULE_VERIFY);
|
|
break;
|
|
case TEST_SUB_MODULE_FPGA:
|
|
case TEST_SUB_MODULE_TOOL:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
rtw_phl_test_submodule_get_rpt(struct rtw_phl_com_t* phl_com,
|
|
void *buf,
|
|
u32 buf_len)
|
|
{
|
|
struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
|
|
struct test_module_cmd *cmd = NULL;
|
|
u8 type = TEST_SUB_MODULE_UNKNOWN;
|
|
|
|
if(!buf)
|
|
return;
|
|
|
|
cmd = (struct test_module_cmd *)buf;
|
|
type = cmd->type;
|
|
|
|
switch(type) {
|
|
case TEST_SUB_MODULE_MP:
|
|
phl_test_mp_get_rpt(test_mgnt->mp_ctx, cmd->buf, cmd->len);
|
|
break;
|
|
case TEST_SUB_MODULE_VERIFY:
|
|
phl_test_verify_get_rpt(test_mgnt->ver_ctx, cmd->buf, cmd->len);
|
|
break;
|
|
case TEST_SUB_MODULE_FPGA:
|
|
case TEST_SUB_MODULE_TOOL:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#endif /*ifdef CONFIG_PHL_TEST_SUITE*/
|