xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/test/mp/phl_test_mp.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 _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