xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/test/test_module.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _TEST_MODULE_C_
16 
17 #ifdef CONFIG_PHL_TEST_SUITE
18 #include "../phl_headers.h"
19 
20 #define MAX_TEST_OBJ_NUM 128
21 #define THREAD_SLEEP_UNIT 1000 /* ms */
22 #define MAX_TEST_CMD_BUF 2000
23 
24 #define TEST_MGNT_ALREADY_INIT(_test_mgnt) \
25 	((_test_mgnt) && TEST_STATUS_FLAG((_test_mgnt)->status,TM_STATUS_INIT))
26 #define IS_TEST_MGNT_ALLOC(_phl_com)	((_phl_com) && ((_phl_com)->test_mgnt))
27 
28 enum TEST_MGNT_STATUS_FALGS{
29 	TM_STATUS_INIT = BIT0,
30 	TM_STATUS_FORCE_STOP = BIT1,
31 	TM_STATUS_THREAD_START = BIT2
32 };
33 
34 enum TEST_OBJ_STATUS_FALGS{
35 /* regular status*/
36 	TO_STATUS_PASS = BIT0,
37 	TO_STATUS_FAIL = BIT1,
38 	TO_STATUS_ENQ = BIT2,
39 	TO_STATUS_RUNNING = BIT3,
40 /* process error status*/
41 	TO_STATUS_RUN_THREAD_FAIL = BIT24,
42 	TO_STATUS_TIMEOUT = BIT25,
43 };
44 
45 struct test_object_ex {
46 	struct test_object test_obj;
47 	u32 start_time;
48 	u32 end_time;
49 	u32 status;
50 	struct rtw_phl_handler handler;
51 	void* test_mgnt;
52 	_os_thread objthread;
53 	u8 submd_obj_id;
54 	u8 submd_test_mode;
55 };
56 
57 struct test_obj_queue {
58 	_os_list q;
59 	_os_mutex lock;
60 };
61 
62 struct test_mgnt_info{
63 	struct test_obj_queue idle_queue;
64 	struct test_obj_queue busy_queue;
65 	struct test_obj_queue rpt_queue;
66 	struct test_obj_queue err_queue;
67 	struct test_object_ex test_obj_pool[MAX_TEST_OBJ_NUM];
68 	struct test_object_ex *cur_test_obj;
69 	s32 max_run_time[TEST_LVL_MAX];
70 	_os_thread thread;
71 	u32 status;
72 	_os_sema busy_chk;
73 	struct rtw_phl_com_t *phl_com;
74 	struct phl_info_t *phl;
75 	void *hal;
76 
77 	/* test module context root */
78 	void *mp_ctx;
79 	void *ver_ctx;
80 };
81 
82 struct test_module_cmd {
83 	u8 type;
84 	u8 buf[MAX_TEST_CMD_BUF];
85 	u16 len;
86 };
87 
88 struct test_module_info {
89 	u8 tm_type;
90 	u8 tm_mode;
91 };
92 
_init_test_obj_queue(void * d,struct test_obj_queue * queue)93 static void _init_test_obj_queue(void *d, struct test_obj_queue *queue)
94 {
95 	INIT_LIST_HEAD(&queue->q);
96 	_os_mutex_init(d, &queue->lock);
97 }
98 
_deinit_test_obj_queue(void * d,struct test_obj_queue * queue)99 static void _deinit_test_obj_queue(void *d, struct test_obj_queue *queue)
100 {
101 	_os_mutex_deinit(d, &queue->lock);
102 }
103 
_enqueue_obj(void * d,struct test_obj_queue * queue,struct test_object_ex * obj)104 static int _enqueue_obj(void *d,
105 	struct test_obj_queue *queue, struct test_object_ex *obj)
106 {
107 	_os_mutex_lock(d, &queue->lock);
108 	list_add_tail(&(obj->test_obj.list), &queue->q);
109 	_os_mutex_unlock(d, &queue->lock);
110 
111 	return 0;
112 }
113 
_dequeue_head_obj(void * d,struct test_obj_queue * queue,struct test_object_ex ** obj)114 static u8 _dequeue_head_obj(void *d,
115 	struct test_obj_queue *queue, struct test_object_ex **obj)
116 {
117 	(*obj) = NULL;
118 	if(list_empty(&(queue->q)))
119 		return false;
120 	_os_mutex_lock(d, &queue->lock);
121 	(*obj) = list_first_entry(&(queue->q),
122 				struct test_object_ex, test_obj.list);
123 	list_del(&((*obj)->test_obj.list));
124 	_os_mutex_unlock(d, &queue->lock);
125 	return ((*obj) == NULL|| ((struct list_head*)(*obj)) == &(queue->q)) ? \
126 		(false) : (true);
127 }
128 
run_test(void * testobj)129 int run_test(void *testobj)
130 {
131 	struct test_object_ex *obj = (struct test_object_ex *)testobj;
132 	struct test_mgnt_info *test_mgnt = obj->test_mgnt;
133 	u8 ret = false;
134 	u32 start_time = 0;
135 	u32 end_time = 0;
136 	void	*d = test_mgnt->phl_com->drv_priv;
137 	/* -1: no limit, 0: not set use default value */
138 	s32 limit = obj->test_obj.total_time_ms;
139 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
140 
141 	if (obj->test_obj.total_time_ms != -1) {
142 		limit = (obj->test_obj.total_time_ms) ? \
143 			(obj->test_obj.total_time_ms) : \
144 			(test_mgnt->max_run_time[obj->test_obj.run_lvl]);
145 	}
146 
147 	SET_STATUS_FLAG(obj->status, TO_STATUS_RUNNING);
148 
149 	pstatus = phl_schedule_handler(test_mgnt->phl_com, &(obj->handler));
150 
151 	if (RTW_PHL_STATUS_SUCCESS != pstatus) {
152 		SET_STATUS_FLAG(obj->status, TO_STATUS_RUN_THREAD_FAIL);
153 		CLEAR_STATUS_FLAG(obj->status, TO_STATUS_RUNNING);
154 		return 0;
155 	}
156 	start_time = _os_get_cur_time_us();
157 	/*wait test end*/
158 	while (!(obj->test_obj.ctrl.is_test_end(obj->test_obj.priv))) {
159 		end_time = _os_get_cur_time_us();
160 		if ((limit >= 0) && ((s32)((end_time-start_time)/1000) >= limit)) {
161 			SET_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT);
162 			obj->end_time = end_time;
163 			break;
164 		}
165 		_os_sleep_us(test_mgnt->phl_com->drv_priv, THREAD_SLEEP_UNIT);
166 	}
167 	if (!TEST_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT))
168 		obj->end_time = _os_get_cur_time_us();
169 
170 	ret = obj->test_obj.ctrl.is_test_pass(obj->test_obj.priv);
171 
172 	SET_STATUS_FLAG(obj->status, (!ret) ? \
173 				(TO_STATUS_FAIL) : (TO_STATUS_PASS));
174 
175 	_enqueue_obj(d, &(test_mgnt->rpt_queue), obj);
176 
177 	if (obj->submd_test_mode == INTGR_TEST_MODE) {
178 		if (!_os_thread_check_stop(d, &(obj->objthread)))
179 			_os_thread_wait_stop(d, &obj->objthread);
180 	}
181 
182 	CLEAR_STATUS_FLAG(obj->status, TO_STATUS_RUNNING);
183 	PHL_INFO("[TM]: obj thread (%s) stop.\n", obj->test_obj.name);
184 
185 	return 0;
186 }
187 
test_thread(void * param)188 int test_thread(void *param)
189 {
190 	struct test_mgnt_info *test_mgnt
191 		= (struct test_mgnt_info *)phl_container_of(param,
192 							     struct test_mgnt_info,
193 							     thread);
194 	void *d = NULL;
195 	struct test_object_ex *obj;
196 
197 	if (!IS_TEST_MGNT_ALLOC(test_mgnt->phl_com))
198 		return 0;
199 
200 	d = test_mgnt->phl_com->drv_priv;
201 	if (!TEST_MGNT_ALREADY_INIT(test_mgnt)) {
202 		PHL_ERR("[TM]: return.\n");
203 		return 0;
204 	}
205 	PHL_INFO("[TM]: thread started.\n");
206 	SET_STATUS_FLAG(test_mgnt->status, TM_STATUS_THREAD_START);
207 
208 	while (!TEST_STATUS_FLAG(test_mgnt->status, TM_STATUS_FORCE_STOP)) {
209 		_os_sema_down(d, &(test_mgnt->busy_chk));
210 		if (TEST_STATUS_FLAG(test_mgnt->status, TM_STATUS_FORCE_STOP))
211 			break;
212 		while (_dequeue_head_obj(d, &(test_mgnt->busy_queue),
213 					&(test_mgnt->cur_test_obj))) {
214 			_os_thread *thread = NULL;
215 			obj = test_mgnt->cur_test_obj;
216 			CLEAR_STATUS_FLAG(obj->status, TO_STATUS_ENQ);
217 
218 			if (obj->submd_test_mode == UNIT_TEST_MODE) {
219 				PHL_INFO("[TM]: %s UNIT_TEST_MODE \n", __FUNCTION__);
220 				run_test(obj);
221 			} else if (obj->submd_test_mode == INTGR_TEST_MODE) {
222 				PHL_INFO("[TM]: %s INTGR_TEST_MODE \n", __FUNCTION__);
223 				thread = &obj->objthread;
224 				_os_thread_init(d, thread, run_test, obj, obj->test_obj.name);
225 				_os_thread_schedule(d, thread);
226 			}
227 			test_mgnt->cur_test_obj = NULL;
228 		}
229 	}
230 	_os_thread_wait_stop(d, &test_mgnt->thread);
231 	CLEAR_STATUS_FLAG(test_mgnt->status, TM_STATUS_THREAD_START);
232 	PHL_INFO("[TM]: test mgnt thread is down\n");
233 	return 0;
234 }
235 
_test_submodule_deinit(void * tm)236 static void _test_submodule_deinit(void *tm)
237 {
238 	struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)tm;
239 
240 	phl_test_mp_deinit(test_mgnt->mp_ctx);
241 	phl_test_verify_deinit(test_mgnt->ver_ctx);
242 }
243 
phl_test_module_init(struct phl_info_t * phl_info)244 u8 phl_test_module_init(struct phl_info_t *phl_info)
245 {
246 	struct rtw_phl_com_t* phl_com = phl_info->phl_com;
247 	struct test_mgnt_info *test_mgnt = NULL;
248 	void *d = NULL;
249 	u8 i = 0;
250 
251 	if(phl_com==NULL)
252 		goto _test_module_mem;
253 	d = phl_com->drv_priv;
254 
255 	test_mgnt = (struct test_mgnt_info *)_os_mem_alloc(d,
256 					sizeof(struct test_mgnt_info));
257 	if (test_mgnt == NULL)
258 		goto _test_module_mem;
259 	_os_mem_set(d, test_mgnt, 0, sizeof(struct test_mgnt_info));
260 	phl_com->test_mgnt = test_mgnt;
261 	test_mgnt->phl_com = phl_com;
262 	test_mgnt->phl = phl_info;
263 	test_mgnt->hal = phl_info->hal;
264 
265 	for(i = 0; i < MAX_TEST_OBJ_NUM; i++)
266 		test_mgnt->test_obj_pool[i].submd_obj_id = TEST_SUB_MODULE_UNKNOWN;
267 
268 	if (phl_test_mp_alloc(test_mgnt->phl, test_mgnt->hal, &(test_mgnt->mp_ctx)) != RTW_PHL_STATUS_SUCCESS) {
269 		PHL_INFO("[TM]: %s phl_test_mp_alloc fail!\n",__FUNCTION__);
270 		goto _mp_module_mem;
271 	}
272 
273 	if(phl_test_verify_alloc(test_mgnt->phl, test_mgnt->hal, &(test_mgnt->ver_ctx)) != RTW_PHL_STATUS_SUCCESS) {
274 		PHL_INFO("[TM]: %s phl_test_verify_alloc fail!\n",__FUNCTION__);
275 		goto _verify_module_mem;
276 	}
277 
278 	PHL_INFO("[TM]: %s\n",__FUNCTION__);
279 	return true;
280 
281 _verify_module_mem:
282 	phl_test_mp_free(&test_mgnt->mp_ctx);
283 _mp_module_mem:
284 	_os_mem_free(d, test_mgnt, sizeof(struct test_mgnt_info));
285 _test_module_mem:
286 	return false;
287 }
288 
phl_test_module_deinit(struct rtw_phl_com_t * phl_com)289 void phl_test_module_deinit(struct rtw_phl_com_t* phl_com)
290 {
291 	void *d = NULL;
292 	struct test_mgnt_info *test_mgnt = NULL;
293 
294 	if(!IS_TEST_MGNT_ALLOC(phl_com))
295 		return;
296 	d = phl_com->drv_priv;
297 	test_mgnt = phlcom_to_test_mgnt(phl_com);
298 
299 	if(TEST_MGNT_ALREADY_INIT(test_mgnt))
300 		phl_test_module_stop(phl_com);
301 
302 	phl_test_mp_free(&test_mgnt->mp_ctx);
303 	phl_test_verify_free(&test_mgnt->ver_ctx);
304 	_os_mem_free(d, test_mgnt, sizeof(struct test_mgnt_info));
305 	phl_com->test_mgnt = NULL;
306 	PHL_INFO("[TM]: %s\n",__FUNCTION__);
307 }
308 
phl_test_module_start(struct rtw_phl_com_t * phl_com)309 u8 phl_test_module_start(struct rtw_phl_com_t* phl_com)
310 {
311 	struct test_mgnt_info *test_mgnt = NULL;
312 	_os_thread *thread = NULL;
313 	void *d = NULL;
314 	u32	i = 0;
315 
316 	if(!IS_TEST_MGNT_ALLOC(phl_com))
317 		return false;
318 	d = phl_com->drv_priv;
319 	test_mgnt = phlcom_to_test_mgnt(phl_com);
320 
321 	if(TEST_MGNT_ALREADY_INIT(test_mgnt)) {
322 		PHL_INFO("[TM]: %s, already initialized\n",__FUNCTION__);
323 		return true;
324 	}
325 	test_mgnt->status = 0;
326 	_init_test_obj_queue(d, &(test_mgnt->busy_queue));
327 	_init_test_obj_queue(d, &(test_mgnt->idle_queue));
328 	_init_test_obj_queue(d, &(test_mgnt->rpt_queue));
329 	_init_test_obj_queue(d, &(test_mgnt->err_queue));
330 
331 	/*insert all elements in obj pool into idle Q*/
332 	for(i = 0; i < MAX_TEST_OBJ_NUM;i++) {
333 		test_mgnt->test_obj_pool[i].submd_obj_id = TEST_SUB_MODULE_UNKNOWN;
334 		_enqueue_obj(d, &(test_mgnt->idle_queue),
335 				&(test_mgnt->test_obj_pool[i]));
336 	}
337 	test_mgnt->max_run_time[TEST_LVL_LOW] = TEST_LVL_LOW_TO;
338 	test_mgnt->max_run_time[TEST_LVL_NORMAL] = TEST_LVL_NORMAL_TO;
339 	test_mgnt->max_run_time[TEST_LVL_HIGH] = TEST_LVL_HIGH_TO;
340 	SET_STATUS_FLAG(test_mgnt->status, TM_STATUS_INIT);
341 
342 	thread = &(test_mgnt->thread);
343 	_os_sema_init(d, &(test_mgnt->busy_chk), 0);
344 	_os_thread_init(d, thread, test_thread, thread, "test_thread");
345 	_os_thread_schedule(d, thread);
346 	PHL_INFO("[TM]: %s\n",__FUNCTION__);
347 	return true;
348 }
349 
phl_test_module_stop(struct rtw_phl_com_t * phl_com)350 void phl_test_module_stop(struct rtw_phl_com_t* phl_com)
351 {
352 	struct test_mgnt_info *test_mgnt = NULL;
353 	void *d = NULL;
354 	u32	i = 0;
355 
356 	if(!IS_TEST_MGNT_ALLOC(phl_com))
357 		return;
358 	d = phl_com->drv_priv;
359 	test_mgnt = phlcom_to_test_mgnt(phl_com);
360 
361 	if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
362 		return;
363 
364 	/* Call all sub module deinit */
365 	_test_submodule_deinit(test_mgnt);
366 
367 	SET_STATUS_FLAG(test_mgnt->status, TM_STATUS_FORCE_STOP);
368 	_os_thread_stop(d, &(test_mgnt->thread));
369 	_os_sema_up(d, &(test_mgnt->busy_chk));
370 	/*wait thread stop*/
371 	PHL_INFO("[TM]: %s stop test_thread\n",__FUNCTION__);
372 	_os_thread_deinit(d, &(test_mgnt->thread));
373 	_os_sema_free(d, &(test_mgnt->busy_chk));
374 	/*clean up test obj resource*/
375 	for (i = 0; i < MAX_TEST_OBJ_NUM; i++) {
376 		struct test_object_ex *obj = &(test_mgnt->test_obj_pool[i]);
377 		if (obj->submd_obj_id != TEST_SUB_MODULE_UNKNOWN && obj->status != TO_STATUS_ENQ) {
378 			if (obj->submd_test_mode == INTGR_TEST_MODE) {
379 				if (!_os_thread_check_stop(d, &(obj->objthread))) {
380 					_os_thread_stop(d, &(obj->objthread));
381 			_os_thread_deinit(d, &(obj->objthread));
382 				}
383 			}
384 			phl_deregister_handler(phl_com, &(obj->handler));
385 	}
386 	}
387 	/*no need to empty test obj Q before deinit*/
388 	_deinit_test_obj_queue(d, &(test_mgnt->busy_queue));
389 	_deinit_test_obj_queue(d, &(test_mgnt->idle_queue));
390 	_deinit_test_obj_queue(d, &(test_mgnt->rpt_queue));
391 	_deinit_test_obj_queue(d, &(test_mgnt->err_queue));
392 	CLEAR_STATUS_FLAG(test_mgnt->status, TM_STATUS_INIT);
393 	PHL_INFO("[TM]: %s\n",__FUNCTION__);
394 }
395 
396 u8
rtw_phl_test_set_max_run_time(struct rtw_phl_com_t * phl_com,enum TEST_RUN_LVL lvl,u32 timeout_ms)397 rtw_phl_test_set_max_run_time(struct rtw_phl_com_t* phl_com,
398                               enum TEST_RUN_LVL lvl,
399                               u32 timeout_ms)
400 {
401 	struct test_mgnt_info *test_mgnt = NULL;
402 	if(!IS_TEST_MGNT_ALLOC(phl_com))
403 		return false;
404 
405 	test_mgnt = phlcom_to_test_mgnt(phl_com);
406 	if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
407 		return false;
408 
409 	test_mgnt = phlcom_to_test_mgnt(phl_com);
410 	test_mgnt->max_run_time[lvl] = timeout_ms;
411 	return true;
412 }
413 
setup_test_rpt(void * d,struct test_rpt * rpt,struct test_object_ex * obj)414 void setup_test_rpt(void *d, struct test_rpt* rpt,struct test_object_ex *obj)
415 {
416 	char str[] = "Exceed Time Limit";
417 	char str2[] = "Test not run";
418 	char str3[] = "None";
419 	_os_mem_cpy(d,	rpt->name, obj->test_obj.name, TEST_NAME_LEN);
420 
421 	if(TEST_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT)) {
422 		_os_mem_cpy(d, rpt->rsn, str, sizeof(str));
423 		rpt->status = 0;
424 		rpt->total_time = (u32)((obj->end_time - obj->start_time)/1000);
425 	}
426 	else if(TEST_STATUS_FLAG(obj->status, TO_STATUS_RUN_THREAD_FAIL)) {
427 		_os_mem_cpy(d, rpt->rsn, str2, sizeof(str2));
428 		rpt->status = 0;
429 		rpt->total_time = 0;
430 	}
431 	else{
432 		obj->test_obj.ctrl.get_fail_rsn(obj->test_obj.priv,
433 					(char*)&(rpt->rsn[0]), TEST_NAME_LEN-1);
434 		if(_os_strlen((u8*)rpt->rsn) <= 0)
435 			_os_mem_cpy(d, rpt->rsn, str3, sizeof(str3));
436 		if (TEST_STATUS_FLAG(obj->status, TO_STATUS_PASS))
437 			rpt->status = 1;
438 		else
439 			rpt->status = 0;
440 		rpt->total_time = (u32)((obj->end_time - obj->start_time)/1000);
441 	}
442 }
443 
rtw_phl_test_get_rpt(struct rtw_phl_com_t * phl_com,u8 * buf,u32 len)444 u8 rtw_phl_test_get_rpt(struct rtw_phl_com_t* phl_com, u8* buf, u32 len)
445 {
446 	struct test_mgnt_info *test_mgnt = NULL;
447 	struct test_object_ex *obj = NULL;
448 	u32 rpt_size = sizeof(struct test_rpt);
449 	void *d = NULL;
450 	u8 is_rpt_empty = true;
451 
452 	if(!IS_TEST_MGNT_ALLOC(phl_com))
453 		return false;
454 
455 	d = phl_com->drv_priv;
456 	test_mgnt = phlcom_to_test_mgnt(phl_com);
457 	if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
458 		return false;
459 
460 	while (len >= rpt_size) {
461 		if(_dequeue_head_obj(d,	&(test_mgnt->rpt_queue), &obj)) {
462 			is_rpt_empty = false;
463 
464 			setup_test_rpt(d, (struct test_rpt*)buf, obj);
465 
466 			if (TEST_STATUS_FLAG(obj->status, TO_STATUS_TIMEOUT))
467 				_enqueue_obj(d,	&(test_mgnt->err_queue), obj);
468 			else {
469 				if (obj->submd_test_mode == INTGR_TEST_MODE) {
470 					if (!_os_thread_check_stop(d, &(obj->objthread))) {
471 						PHL_INFO("[TM]: %s obj thread (%s) stop.\n",
472 						         __FUNCTION__,
473 						         obj->test_obj.name);
474 						_os_thread_stop(d, &(obj->objthread));
475 						_os_thread_deinit(d, &(obj->objthread));
476 					}
477 				}
478 				phl_deregister_handler(phl_com, &(obj->handler));
479 				obj->status = 0;
480 				obj->submd_obj_id = TEST_SUB_MODULE_UNKNOWN;
481 				_enqueue_obj(d,	&(test_mgnt->idle_queue), obj);
482 			}
483 			buf += rpt_size;
484 			len -= rpt_size;
485 		}
486 		else
487 			break;
488 	}
489 	return (is_rpt_empty)?(false):(true);
490 }
491 
rtw_phl_test_is_test_complete(struct rtw_phl_com_t * phl_com)492 u8 rtw_phl_test_is_test_complete(struct rtw_phl_com_t* phl_com)
493 {
494 	struct test_mgnt_info *test_mgnt = NULL;
495 	void *d = NULL;
496 
497 	if(!IS_TEST_MGNT_ALLOC(phl_com))
498 		return false;
499 
500 	d = phl_com->drv_priv;
501 	test_mgnt = phlcom_to_test_mgnt(phl_com);
502 	if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
503 		return false;
504 	if (list_empty(&(test_mgnt->busy_queue.q)) && !(test_mgnt->cur_test_obj))
505 		return true;
506 	return false;
507 }
508 
_test_obj_thread_callback(void * context)509 static void _test_obj_thread_callback(void *context)
510 {
511 	struct rtw_phl_handler *phl_handler
512 		= (struct rtw_phl_handler *)phl_container_of(context,
513 							     struct rtw_phl_handler,
514 							     os_handler);
515 	struct test_object_ex *obj = (struct test_object_ex *)phl_handler->context;
516 	obj->start_time = _os_get_cur_time_us();
517 	obj->test_obj.ctrl.start_test(obj->test_obj.priv);
518 }
519 
init_obj_thread(struct test_mgnt_info * test_mgnt,struct test_object_ex * obj,enum TEST_RUN_LVL lvl)520 u8 init_obj_thread(struct test_mgnt_info *test_mgnt,
521                    struct test_object_ex *obj,
522                    enum TEST_RUN_LVL lvl)
523 {
524 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
525 
526 	switch(lvl){
527 	case TEST_LVL_LOW:
528 	case TEST_LVL_NORMAL:
529 		obj->handler.type = RTW_PHL_HANDLER_PRIO_LOW;
530 		break;
531 	case TEST_LVL_HIGH:
532 		obj->handler.type = RTW_PHL_HANDLER_PRIO_HIGH;
533 		break;
534 	case TEST_LVL_NONE:
535 	case TEST_LVL_MAX:
536 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "init_obj_thread(): Unsupported case:%d, please check it\n",
537 				lvl);
538 		break;
539 	default:
540 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "init_obj_thread(): Unrecognize case:%d, please check it\n",
541 				lvl);
542 		break;
543 	}
544 	obj->handler.callback = _test_obj_thread_callback;
545 	obj->handler.context = obj;
546 	obj->handler.drv_priv = test_mgnt->phl_com->drv_priv;
547 	pstatus = phl_register_handler(test_mgnt->phl_com, &(obj->handler));
548 	return (RTW_PHL_STATUS_SUCCESS != pstatus) ? (false) : (true);
549 }
550 
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)551 u8 rtw_phl_test_add_new_test_obj(struct rtw_phl_com_t *phl_com,
552                                  char *name,
553                                  void *custom_priv,
554                                  enum TEST_RUN_LVL lvl,
555                                  struct test_obj_ctrl_interface *ctrl_intf,
556                                  s32 total_time_ms,
557                                  u8 submd_id,
558                                  u8 test_mode)
559 {
560 	struct test_mgnt_info *test_mgnt = NULL;
561 	struct test_object_ex *obj = NULL;
562 	void *d = NULL;
563 	u8 i;
564 	u8 is_idle_empty = true;
565 	u32 name_len = (_os_strlen((u8 *)name) > (u32)(TEST_NAME_LEN - 1)) ?\
566 		((u32)(TEST_NAME_LEN - 1)) :\
567 		(_os_strlen((u8 *)name) + 1);
568 
569 	if (!IS_TEST_MGNT_ALLOC(phl_com))
570 		return false;
571 
572 	d = phl_com->drv_priv;
573 	test_mgnt = phlcom_to_test_mgnt(phl_com);
574 	if (!TEST_MGNT_ALREADY_INIT(test_mgnt))
575 		return false;
576 
577 	for (i = 0; i < MAX_TEST_OBJ_NUM; i++) {
578 		obj = &(test_mgnt->test_obj_pool[i]);
579 		if (obj->submd_obj_id == submd_id && obj->status == TO_STATUS_RUNNING) {
580 			PHL_INFO("%s() Error same submd id %d\n", __func__, obj->submd_obj_id);
581 		return false;
582 		}
583 	}
584 
585 	if (_dequeue_head_obj(d, &(test_mgnt->idle_queue), &obj)) {
586 		is_idle_empty = false;
587 		if (TEST_STATUS_FLAG(obj->status, TO_STATUS_ENQ))
588 			phl_deregister_handler(phl_com, &(obj->handler));
589 		/*cleanup entire test obj before reuse*/
590 		_os_mem_set(d, obj, 0, sizeof(struct test_object_ex));
591 
592 		_os_mem_cpy(d, &(obj->test_obj.ctrl), ctrl_intf,
593 				sizeof(struct test_obj_ctrl_interface));
594 
595 		_os_mem_cpy(d, &(obj->test_obj.name[0]), name, name_len);
596 		obj->test_obj.priv = custom_priv;
597 		obj->test_obj.run_lvl = lvl;
598 		obj->test_mgnt = test_mgnt;
599 		obj->test_obj.total_time_ms = (lvl <= TEST_LVL_LOW) ?\
600 						(total_time_ms) : (0);
601 		obj->submd_obj_id = submd_id;
602 		obj->submd_test_mode = test_mode;
603 
604 		if (init_obj_thread(test_mgnt, obj, lvl)) {
605 			SET_STATUS_FLAG(obj->status, TO_STATUS_ENQ);
606 			_enqueue_obj(d,	&(test_mgnt->busy_queue), obj);
607 			_os_sema_up(d, &(test_mgnt->busy_chk));
608 			PHL_INFO("[TM]: %s, id %u EnQ\n", __FUNCTION__, submd_id);
609 		} else {
610 			_enqueue_obj(d,	&(test_mgnt->idle_queue), obj);
611 			PHL_INFO("[TM]: %s, id %u EnQ fail\n", __FUNCTION__, submd_id);
612 		}
613 	}
614 	if (is_idle_empty || !TEST_STATUS_FLAG(obj->status, TO_STATUS_ENQ))
615 		return false;
616 	return true;
617 }
618 
619 u8
rtw_phl_test_setup_bp(struct rtw_phl_com_t * phl_com,struct test_bp_info * bp_info,u8 submdid)620 rtw_phl_test_setup_bp(struct rtw_phl_com_t* phl_com,
621                       struct test_bp_info* bp_info,
622                       u8 submdid)
623 {
624 	u8 i;
625 	struct test_mgnt_info *test_mgnt = NULL;
626 	struct test_object_ex *obj = NULL;
627 	if(!IS_TEST_MGNT_ALLOC(phl_com))
628 		return false;
629 
630 	test_mgnt = phlcom_to_test_mgnt(phl_com);
631 
632 	for (i = 0; i < MAX_TEST_OBJ_NUM; i++) {
633 		obj = &(test_mgnt->test_obj_pool[i]);
634 		if (obj->submd_obj_id == submdid && TEST_STATUS_FLAG(obj->status, TO_STATUS_RUNNING)) {
635 			PHL_DBG("%s() objid = %d setup bp\n", __func__, obj->submd_obj_id);
636 			break;
637 		}
638 	}
639 
640 	if(!TEST_MGNT_ALREADY_INIT(test_mgnt))
641 		return false;
642 
643 	return (obj && TEST_STATUS_FLAG(obj->status, TO_STATUS_RUNNING))?\
644 		(obj->test_obj.ctrl.bp_handler(obj->test_obj.priv, bp_info)):\
645 		(BP_RET_RUN_ORIGIN_SEC);
646 }
647 
rtw_phl_test_submodule_init(struct rtw_phl_com_t * phl_com,void * buf)648 void rtw_phl_test_submodule_init(struct rtw_phl_com_t* phl_com, void *buf)
649 {
650 	struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
651 	struct test_module_info *tm_info = NULL;
652 
653 	if(buf == NULL)
654 		return;
655 
656 	tm_info = (struct test_module_info *)buf;
657 
658 	switch(tm_info->tm_type) {
659 		case TEST_SUB_MODULE_MP:
660 			phl_test_mp_init(test_mgnt->mp_ctx);
661 			phl_test_mp_start(test_mgnt->mp_ctx, tm_info->tm_mode);
662 			break;
663 		case TEST_SUB_MODULE_VERIFY:
664 			phl_test_verify_init(test_mgnt->ver_ctx);
665 			phl_test_verify_start(test_mgnt->ver_ctx);
666 			break;
667 		case TEST_SUB_MODULE_FPGA:
668 		case TEST_SUB_MODULE_TOOL:
669 		default:
670 			break;
671 	}
672 }
673 
rtw_phl_test_submodule_deinit(struct rtw_phl_com_t * phl_com,void * buf)674 void rtw_phl_test_submodule_deinit(struct rtw_phl_com_t* phl_com, void *buf)
675 {
676 	struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
677 	struct test_module_info *tm_info = NULL;
678 
679 	if(buf == NULL)
680 		return;
681 
682 	tm_info = (struct test_module_info *)buf;
683 
684 	switch(tm_info->tm_type) {
685 		case TEST_SUB_MODULE_MP:
686 			phl_test_mp_stop(test_mgnt->mp_ctx, tm_info->tm_mode);
687 			phl_test_mp_deinit(test_mgnt->mp_ctx);
688 			break;
689 		case TEST_SUB_MODULE_VERIFY:
690 			phl_test_verify_stop(test_mgnt->ver_ctx);
691 			phl_test_verify_deinit(test_mgnt->ver_ctx);
692 			break;
693 		case TEST_SUB_MODULE_FPGA:
694 		case TEST_SUB_MODULE_TOOL:
695 		default:
696 			break;
697 	}
698 }
699 
700 void
rtw_phl_test_submodule_cmd_process(struct rtw_phl_com_t * phl_com,void * buf,u32 buf_len)701 rtw_phl_test_submodule_cmd_process(struct rtw_phl_com_t* phl_com,
702                                    void *buf,
703                                    u32 buf_len)
704 {
705 	struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
706 	struct test_module_cmd *cmd = NULL;
707 	u8 type = TEST_SUB_MODULE_UNKNOWN;
708 
709 	if(buf == NULL)
710 		return;
711 
712 	cmd = (struct test_module_cmd *)buf;
713 	type = cmd->type;
714 	/* debug_dump_data(cmd->buf, MAX_TEST_CMD_BUF, "[TM] cmd buf ="); */
715 	PHL_INFO("%s: len = %d\n", __FUNCTION__, cmd->len);
716 
717 	switch(type) {
718 		case TEST_SUB_MODULE_MP:
719 			phl_test_mp_cmd_process(test_mgnt->mp_ctx, cmd->buf, cmd->len, TEST_SUB_MODULE_MP);
720 			break;
721 		case TEST_SUB_MODULE_VERIFY:
722 			phl_test_verify_cmd_process(test_mgnt->ver_ctx, cmd->buf, cmd->len, TEST_SUB_MODULE_VERIFY);
723 			break;
724 		case TEST_SUB_MODULE_FPGA:
725 		case TEST_SUB_MODULE_TOOL:
726 		default:
727 			break;
728 	}
729 }
730 
731 void
rtw_phl_test_submodule_get_rpt(struct rtw_phl_com_t * phl_com,void * buf,u32 buf_len)732 rtw_phl_test_submodule_get_rpt(struct rtw_phl_com_t* phl_com,
733                                void *buf,
734                                u32 buf_len)
735 {
736 	struct test_mgnt_info *test_mgnt = (struct test_mgnt_info *)phl_com->test_mgnt;
737 	struct test_module_cmd *cmd = NULL;
738 	u8 type = TEST_SUB_MODULE_UNKNOWN;
739 
740 	if(!buf)
741 		return;
742 
743 	cmd = (struct test_module_cmd *)buf;
744 	type = cmd->type;
745 
746 	switch(type) {
747 		case TEST_SUB_MODULE_MP:
748 			phl_test_mp_get_rpt(test_mgnt->mp_ctx, cmd->buf, cmd->len);
749 			break;
750 		case TEST_SUB_MODULE_VERIFY:
751 			phl_test_verify_get_rpt(test_mgnt->ver_ctx, cmd->buf, cmd->len);
752 			break;
753 		case TEST_SUB_MODULE_FPGA:
754 		case TEST_SUB_MODULE_TOOL:
755 		default:
756 			break;
757 	}
758 }
759 #endif /*ifdef CONFIG_PHL_TEST_SUITE*/
760