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