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 _PHL_TEST_MP_C_
16 #include "../../phl_headers.h"
17 #include "phl_test_mp_def.h"
18 #include "phl_test_mp_api.h"
19 #include "../../hal_g6/test/mp/hal_test_mp_api.h"
20
21 #ifdef CONFIG_PHL_TEST_MP
mp_notification_complete(void * priv,struct phl_msg * msg)22 void mp_notification_complete(void* priv, struct phl_msg* msg)
23 {
24 struct mp_context *mp_ctx = (struct mp_context *)priv;
25
26 if(msg->inbuf){
27 PHL_INFO("%s: Free info buf\n", __FUNCTION__);
28 _os_kmem_free(mp_ctx->phl_com->drv_priv, msg->inbuf, msg->inlen);
29 }
30 }
31
mp_cmd_done_notification(struct mp_context * mp_ctx,enum mp_class mp_class,u8 mp_cmd_id)32 void mp_cmd_done_notification(struct mp_context *mp_ctx, enum mp_class mp_class,
33 u8 mp_cmd_id)
34 {
35 struct phl_msg msg = {0};
36 struct phl_msg_attribute attr;
37 u8 *info = NULL;
38
39 info = _os_kmem_alloc(mp_ctx->phl_com->drv_priv, 2);
40
41 if(info == NULL){
42 PHL_ERR("%s: Allocate msg hub buffer fail!\n", __FUNCTION__);
43 return;
44 }
45
46 info[0] = mp_class;
47 info[1] = mp_cmd_id;
48
49 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FUNC_MDL_TEST_MODULE);
50 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_MP_CMD_DONE);
51
52 attr.completion.completion = mp_notification_complete;
53 attr.completion.priv = mp_ctx;
54
55 msg.inbuf = info;
56 msg.inlen = 2;
57
58 if (phl_msg_hub_send(mp_ctx->phl,
59 &attr, &msg) != RTW_PHL_STATUS_SUCCESS) {
60 PHL_ERR("%s: send msg_hub failed\n", __func__);
61 _os_kmem_free(mp_ctx->phl_com->drv_priv, info, 2);
62 }
63 }
64
65 /*
66 * @enum phl_msg_evt_id id: Assign different types of MP related msg event
67 * to pass buffer to another layer for further process
68 */
mp_buf_notification(struct mp_context * mp_ctx,void * buf,u32 buf_len,enum phl_msg_evt_id id)69 void mp_buf_notification(struct mp_context *mp_ctx, void *buf, u32 buf_len,
70 enum phl_msg_evt_id id)
71 {
72 struct phl_msg msg = {0};
73 struct phl_msg_attribute attr;
74 u8 *info = NULL;
75
76 info = _os_kmem_alloc(mp_ctx->phl_com->drv_priv, buf_len);
77
78 if(info == NULL){
79 PHL_ERR("%s: Allocate msg hub buffer fail!\n", __FUNCTION__);
80 return;
81 }
82
83 _os_mem_cpy(mp_ctx->phl_com->drv_priv, info, buf, buf_len);
84
85 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FUNC_MDL_TEST_MODULE);
86 SET_MSG_EVT_ID_FIELD(msg.msg_id, id);
87
88 attr.completion.completion = mp_notification_complete;
89 attr.completion.priv = mp_ctx;
90
91 msg.inbuf = info;
92 msg.inlen = buf_len;
93
94 if (phl_msg_hub_send(mp_ctx->phl, &attr, &msg) != RTW_PHL_STATUS_SUCCESS) {
95 PHL_ERR("%s: send msg_hub failed\n", __func__);
96 _os_kmem_free(mp_ctx->phl_com->drv_priv, info, buf_len);
97 }
98 }
99
100
mp_get_rpt_check(struct mp_context * mp_ctx,void * rpt_buf)101 bool mp_get_rpt_check(struct mp_context *mp_ctx, void *rpt_buf)
102 {
103 bool ret = true;
104 struct mp_arg_hdr *rpt_hdr = (struct mp_arg_hdr *)mp_ctx->rpt;
105 struct mp_arg_hdr *rpt_buf_hdr = (struct mp_arg_hdr *)rpt_buf;
106
107 if((rpt_hdr->mp_class != rpt_buf_hdr->mp_class) ||
108 (rpt_hdr->cmd != rpt_buf_hdr->cmd)) {
109 PHL_WARN("%s: Report buffer not match!\n", __FUNCTION__);
110 rpt_buf_hdr->cmd_ok = true;
111 rpt_buf_hdr->status = RTW_PHL_STATUS_FAILURE;
112 ret = false;
113 }
114
115 return ret;
116 }
117
mp_get_class_from_buf(struct mp_context * mp_ctx)118 u8 mp_get_class_from_buf(struct mp_context *mp_ctx)
119 {
120 u8 *buf_tmp = NULL;
121 u8 mp_class = MP_CLASS_MAX;
122 if(mp_ctx && mp_ctx->buf) {
123 buf_tmp = (u8 *)mp_ctx->buf;
124 mp_class = buf_tmp[0];
125 }
126 return mp_class;
127 }
128
mp_bp_handler(void * priv,struct test_bp_info * bp_info)129 u8 mp_bp_handler(void *priv, struct test_bp_info* bp_info)
130 {
131 struct mp_context *mp_ctx = (struct mp_context *)priv;
132 enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
133
134 PHL_DBG("%s: bp_info->type = %x\n", __FUNCTION__, bp_info->type);
135
136 switch(bp_info->type){
137 case BP_INFO_TYPE_MP_CMD_EVENT:
138 if(mp_ctx->status == MP_STATUS_WAIT_CMD) {
139 mp_ctx->status = MP_STATUS_CMD_EVENT;
140 _os_sema_up(mp_ctx->phl_com->drv_priv,&(mp_ctx->mp_cmd_sema));
141 phl_status = RTW_PHL_STATUS_SUCCESS;
142 }
143 break;
144 case BP_INFO_TYPE_MP_RX_PHYSTS:
145 if(mp_ctx->rx_physts == true) {
146 u32 i = 0;
147 for(i = 0; i < (bp_info->len/4); i ++)
148 PHL_DBG("0x%08X\n",
149 *((u32 *)(bp_info->ptr)+i));
150
151 mp_buf_notification(mp_ctx,
152 bp_info->ptr,
153 bp_info->len,
154 MSG_EVT_MP_RX_PHYSTS);
155 }
156 break;
157 case BP_INFO_TYPE_NONE:
158 case BP_INFO_TYPE_WAIT_BEACON_JOIN:
159 case BP_INFO_TYPE_SEND_AUTH_ODD:
160 case BP_INFO_TYPE_SEND_ASOC_REQ:
161 case BP_INFO_TYPE_SEND_DISASSOC:
162 case BP_INFO_TYPE_FILL_DISASSOC_RSN:
163 case BP_INFO_TYPE_SEND_PROBE_REQ:
164 case BP_INFO_TYPE_RX_TEST_WPRPT:
165 case BP_INFO_TYPE_RX_TEST_PATTERN:
166 case BP_INFO_TYPE_MAX:
167 PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "mp_bp_handler(): Unsupported case:%d, please check it\n",
168 bp_info->type);
169 break;
170 default:
171 PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "mp_bp_handler(): Unrecognize case:%d, please check it\n",
172 bp_info->type);
173 break;
174 }
175 return phl_status;
176 }
177
mp_get_fail_rsn(void * priv,char * rsn,u32 max_len)178 u8 mp_get_fail_rsn(void *priv,char* rsn, u32 max_len)
179 {
180 //struct mp_context *mp_ctx = (struct mp_context *)priv;
181 return true;
182 }
183
mp_is_test_end(void * priv)184 u8 mp_is_test_end(void *priv)
185 {
186 struct mp_context *mp_ctx = (struct mp_context *)priv;
187
188 return mp_ctx->is_mp_test_end;
189 }
190
mp_is_test_pass(void * priv)191 u8 mp_is_test_pass(void *priv)
192 {
193 //struct mp_context *mp_ctx = (struct mp_context *)priv;
194 return true;
195 }
196
mp_start(void * priv)197 u8 mp_start(void *priv)
198 {
199 struct mp_context *mp_ctx = (struct mp_context *)priv;
200 struct rtw_phl_com_t* phl_com = mp_ctx->phl_com;
201
202 enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
203 u8 mp_class = MP_CLASS_MAX;
204 FUNCIN();
205 while(!mp_is_test_end(mp_ctx)){
206 _os_sema_down(phl_com->drv_priv,&(mp_ctx->mp_cmd_sema));
207 if(mp_ctx->status == MP_STATUS_CMD_EVENT){
208 mp_ctx->status = MP_STATUS_RUN_CMD;
209 mp_class = mp_get_class_from_buf(mp_ctx);
210
211 /* Clear report buffer before executing next command */
212 if(mp_ctx->rpt != NULL) {
213 PHL_INFO("%s: Report not empty, cleanup!\n", __FUNCTION__);
214 _os_mem_free(phl_com->drv_priv, mp_ctx->rpt, mp_ctx->rpt_len);
215 mp_ctx->rpt = NULL;
216 mp_ctx->rpt_len = 0;
217 }
218
219 switch(mp_class){
220 case MP_CLASS_CONFIG:
221 PHL_INFO("%s: class = MP_CLASS_CONFIG\n", __FUNCTION__);
222 phl_status = mp_config(mp_ctx, (struct mp_config_arg *)mp_ctx->buf);
223 break;
224 case MP_CLASS_TX:
225 PHL_INFO("%s: class = MP_CLASS_TX\n", __FUNCTION__);
226 phl_status = mp_tx(mp_ctx, (struct mp_tx_arg *)mp_ctx->buf);
227 break;
228 case MP_CLASS_RX:
229 PHL_INFO("%s: class = MP_CLASS_RX\n", __FUNCTION__);
230 phl_status = mp_rx(mp_ctx, (struct mp_rx_arg *)mp_ctx->buf);
231 break;
232 case MP_CLASS_EFUSE:
233 PHL_INFO("%s: class = MP_CLASS_EFUSE\n", __FUNCTION__);
234 phl_status = mp_efuse(mp_ctx, (struct mp_efuse_arg *)mp_ctx->buf);
235 break;
236 case MP_CLASS_REG:
237 PHL_INFO("%s: class = MP_CLASS_REG\n", __FUNCTION__);
238 phl_status = mp_reg(mp_ctx, (struct mp_reg_arg *)mp_ctx->buf);
239 break;
240 case MP_CLASS_TXPWR:
241 PHL_INFO("%s: class = MP_CLASS_TXPWR\n", __FUNCTION__);
242 phl_status = mp_txpwr(mp_ctx, (struct mp_txpwr_arg *)mp_ctx->buf);
243 break;
244 case MP_CLASS_CAL:
245 PHL_INFO("%s: class = MP_CLASS_CAL\n", __FUNCTION__);
246 phl_status = mp_cal(mp_ctx, (struct mp_cal_arg *)mp_ctx->buf);
247 break;
248 default:
249 PHL_WARN("%s: Unknown mp class! (%d)\n", __FUNCTION__, mp_class);
250 break;
251
252 }
253
254 if(mp_ctx->rpt != NULL) {
255 struct mp_arg_hdr *hdr = (struct mp_arg_hdr *)mp_ctx->rpt;
256 mp_cmd_done_notification(mp_ctx, hdr->mp_class, hdr->cmd);
257 PHL_INFO("%s: Indication class(%d) cmd(%d)\n",
258 __FUNCTION__, hdr->mp_class, hdr->cmd);
259 }
260
261 /* Clear command buffer after executing the command */
262 if(mp_ctx->buf != NULL) {
263 PHL_INFO("%s: Command buf not empty, cleanup!\n", __FUNCTION__);
264 _os_mem_free(phl_com->drv_priv, mp_ctx->buf, mp_ctx->buf_len);
265 mp_ctx->buf = NULL;
266 mp_ctx->buf_len = 0;
267 }
268 mp_ctx->status = MP_STATUS_WAIT_CMD;
269 }
270 }
271
272 FUNCOUT();
273 return (u8)phl_status;
274 }
275
mp_change_mode(struct mp_context * mp_ctx,enum rtw_drv_mode driver_mode)276 void mp_change_mode(struct mp_context *mp_ctx, enum rtw_drv_mode driver_mode)
277 {
278 struct phl_info_t *phl_info = mp_ctx->phl;
279 PHL_INFO("%s Change to %x\n", __FUNCTION__, driver_mode);
280
281 /* Need PHL stop function later */
282
283 phl_info->phl_com->drv_mode = driver_mode;
284
285 #ifdef RTW_WKARD_MP_MODE_CHANGE
286 #else
287 rtw_phl_reset(phl_info);
288 #endif
289
290 if(true == phl_is_mp_mode(phl_info->phl_com)) {
291
292 /* Load bt map to shadow map */
293 rtw_hal_mp_efuse_bt_shadow_reload(mp_ctx);
294
295 rtw_hal_acpt_crc_err_pkt(mp_ctx->hal,mp_ctx->cur_phy,true);
296 }
297 else {
298 rtw_hal_acpt_crc_err_pkt(mp_ctx->hal,mp_ctx->cur_phy,false);
299 }
300 #ifdef CONFIG_DBCC_SUPPORT
301 if (phl_info->phl_com->dev_cap.dbcc_sup)
302 rtw_hal_dbcc_cfg(mp_ctx->hal, phl_info->phl_com, true);
303 #endif
304 rtw_hal_mp_ic_hw_setting_init(mp_ctx);
305 rtw_hal_mp_cfg(phl_info->phl_com ,mp_ctx->hal);
306
307 rtw_hal_mp_ic_hw_setting_init(mp_ctx);
308 }
309
phl_test_mp_alloc(struct phl_info_t * phl_info,void * hal,void ** mp)310 enum rtw_phl_status phl_test_mp_alloc(struct phl_info_t *phl_info, void *hal, void **mp)
311 {
312 enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
313 struct rtw_phl_com_t *phl_com = phl_info->phl_com;
314 struct mp_context *mp_ctx = NULL;
315
316 mp_ctx = _os_mem_alloc(phl_com->drv_priv, sizeof(struct mp_context));
317
318 if (mp_ctx == NULL) {
319 PHL_ERR("alloc mp_context failed\n");
320 phl_status = RTW_PHL_STATUS_RESOURCE;
321 goto exit;
322 }
323 _os_sema_init(phl_com->drv_priv,&(mp_ctx->mp_cmd_sema), 0);
324 mp_ctx->cur_phy = HW_PHY_0;
325 mp_ctx->rx_physts = false;
326 mp_ctx->phl = phl_info;
327 mp_ctx->phl_com = phl_com;
328 mp_ctx->hal = hal;
329 mp_ctx->status = MP_STATUS_INIT;
330 *mp = mp_ctx;
331 phl_status = RTW_PHL_STATUS_SUCCESS;
332
333 exit:
334 return phl_status;
335 }
336
phl_test_mp_free(void ** mp)337 void phl_test_mp_free(void **mp)
338 {
339 struct mp_context *mp_ctx = NULL;
340
341 if(*mp == NULL)
342 return;
343
344 mp_ctx = (struct mp_context *)(*mp);
345 _os_sema_free(mp_ctx->phl_com->drv_priv, &(mp_ctx->mp_cmd_sema));
346 _os_mem_free(mp_ctx->phl_com->drv_priv, mp_ctx, sizeof(struct mp_context));
347 mp_ctx = NULL;
348 *mp = NULL;
349 }
350
351
phl_test_mp_init(void * mp)352 void phl_test_mp_init(void *mp)
353 {
354 struct mp_context *mp_ctx = NULL;
355 struct test_obj_ctrl_interface *pctrl = NULL;
356
357 if(mp == NULL)
358 return;
359
360 mp_ctx = (struct mp_context *)mp;
361 pctrl = &(mp_ctx->mp_test_ctrl);
362
363 mp_ctx->status = MP_STATUS_WAIT_CMD;
364 mp_ctx->is_mp_test_end = false;
365 pctrl->bp_handler = mp_bp_handler;
366 pctrl->get_fail_rsn = mp_get_fail_rsn;
367 pctrl->is_test_end = mp_is_test_end;
368 pctrl->is_test_pass = mp_is_test_pass;
369 pctrl->start_test = mp_start;
370 rtw_phl_test_add_new_test_obj(mp_ctx->phl_com,
371 "mp_test",
372 mp_ctx,
373 TEST_LVL_LOW,
374 pctrl,
375 -1,
376 TEST_SUB_MODULE_MP,
377 INTGR_TEST_MODE);
378 }
379
phl_test_mp_deinit(void * mp)380 void phl_test_mp_deinit(void *mp)
381 {
382 struct mp_context *mp_ctx = NULL;
383 if(mp == NULL)
384 return;
385
386 mp_ctx = (struct mp_context *)mp;
387
388 if(mp_ctx->status < MP_STATUS_WAIT_CMD)
389 return;
390
391 mp_ctx->is_mp_test_end = true;
392 _os_sema_up(mp_ctx->phl_com->drv_priv,&(mp_ctx->mp_cmd_sema));
393 mp_ctx->status = MP_STATUS_INIT;
394 }
395
phl_test_mp_start(void * mp,u8 tm_mode)396 void phl_test_mp_start(void *mp, u8 tm_mode)
397 {
398 struct mp_context *mp_ctx = NULL;
399
400 if(mp == NULL)
401 return;
402
403 mp_ctx = (struct mp_context *)mp;
404
405 mp_change_mode(mp_ctx, tm_mode);
406 }
407
phl_test_mp_stop(void * mp,u8 tm_mode)408 void phl_test_mp_stop(void *mp, u8 tm_mode)
409 {
410 struct mp_context *mp_ctx = NULL;
411 if(mp == NULL)
412 return;
413
414 mp_ctx = (struct mp_context *)mp;
415
416 if(mp_ctx->status < MP_STATUS_WAIT_CMD)
417 return;
418
419 mp_change_mode(mp_ctx, tm_mode);
420 }
421
422
phl_test_mp_cmd_process(void * mp,void * buf,u32 buf_len,u8 submdid)423 void phl_test_mp_cmd_process(void *mp, void *buf, u32 buf_len, u8 submdid)
424 {
425 struct mp_context *mp_ctx = NULL;
426 struct rtw_phl_com_t *phl_com = NULL;
427 struct test_bp_info bp_info;
428 FUNCIN();
429
430 if(mp == NULL)
431 return;
432
433 mp_ctx = (struct mp_context *)mp;
434 phl_com = mp_ctx->phl_com;
435
436 if((buf == NULL) || (buf_len <= 0)) {
437 PHL_ERR("%s: Invalid buffer content!\n", __func__);
438 return;
439 }
440
441
442 if(mp_ctx->status == MP_STATUS_WAIT_CMD) {
443 mp_ctx->buf_len = buf_len;
444 mp_ctx->buf = _os_mem_alloc(phl_com->drv_priv, buf_len);
445 _os_mem_cpy(phl_com->drv_priv, mp_ctx->buf, buf, buf_len);
446 _os_mem_set(phl_com->drv_priv, &bp_info, 0, sizeof(struct test_bp_info));
447 bp_info.type = BP_INFO_TYPE_MP_CMD_EVENT;
448 rtw_phl_test_setup_bp(phl_com, &bp_info, submdid);
449 }
450 else {
451 PHL_WARN("%s: Previous command is still running!\n", __FUNCTION__);
452 }
453
454 FUNCOUT();
455 }
456
phl_test_mp_get_rpt(void * mp,void * buf,u32 buf_len)457 void phl_test_mp_get_rpt(void *mp, void *buf, u32 buf_len)
458 {
459 struct mp_context *mp_ctx = NULL;
460 FUNCIN();
461
462 if(mp == NULL) {
463 PHL_WARN("%s: mp is NULL!\n", __FUNCTION__);
464 goto exit;
465 }
466
467 mp_ctx = (struct mp_context *)mp;
468
469 if(mp_ctx->status != MP_STATUS_WAIT_CMD) {
470 PHL_WARN("%s: command is running!\n", __FUNCTION__);
471 goto exit;
472 }
473
474 if(mp_ctx->rpt == NULL) {
475 PHL_DBG("%s: mp_ctx->rpt is NULL!\n", __FUNCTION__);
476 goto exit;
477 }
478
479 if(buf_len < mp_ctx->rpt_len) {
480 PHL_WARN("%s: buffer not enough!\n", __FUNCTION__);
481 goto exit;
482 }
483
484 if(mp_get_rpt_check(mp_ctx, buf) == true) {
485 _os_mem_cpy(mp_ctx->phl_com->drv_priv, buf, mp_ctx->rpt, mp_ctx->rpt_len);
486 _os_mem_free(mp_ctx->phl_com->drv_priv, mp_ctx->rpt, mp_ctx->rpt_len);
487 mp_ctx->rpt = NULL;
488 mp_ctx->rpt_len = 0;
489 }
490
491 exit:
492 FUNCOUT();
493 }
494 #endif /* CONFIG_PHL_TEST_MP */
495