xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_btc_fsm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 - 2020 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 #include "phl_headers.h"
16 
17 #ifdef CONFIG_FSM
18 #include "phl_btc_fsm.h"
19 
20 struct btc_obj {
21 	struct fsm_main *fsm;
22 	struct fsm_obj *fsm_obj;
23 	struct phl_info_t *phl_info;
24 
25 	struct rtw_phl_btc_ntfy *ntfy;
26 };
27 
28 enum BTC_STATE_ST {
29 	BTC_ST_IDLE,
30 	BTC_ST_SERVICE
31 };
32 
33 enum BTC_EV_ID {
34 	BTC_EV_START,
35 	BTC_EV_UPDATE_ROLE_INFO,
36 	BTC_EV_FWINFO,
37 	BTC_EV_WLSTA,
38 	BTC_EV_TIMER,
39 	BTC_EV_PACKET_EVT,
40 	BTC_EV_MAX
41 };
42 
43 static int btc_idle_st_hdl(void *obj, u16 event, void *param);
44 static int btc_service_st_hdl(void *obj, u16 event, void *param);
45 
46 /* STATE table */
47 static struct fsm_state_ent btc_state_tbl[] = {
48 	ST_ENT(BTC_ST_IDLE, btc_idle_st_hdl),
49 	ST_ENT(BTC_ST_SERVICE, btc_service_st_hdl)
50 	//{BTC_ST_MAX, "BTC_ST_MAX", NULL} /* ST_MAX for fsm safety checking */
51 };
52 
53 /* EVENT table */
54 static struct fsm_event_ent btc_event_tbl[] = {
55 	EV_ENT(BTC_EV_START),
56 	EV_ENT(BTC_EV_UPDATE_ROLE_INFO),
57 	EV_ENT(BTC_EV_FWINFO),
58 	EV_ENT(BTC_EV_WLSTA),
59 	EV_DBG(BTC_EV_TIMER),
60 	EV_ENT(BTC_EV_PACKET_EVT),
61 	EV_ENT(BTC_EV_MAX) /* EV_MAX for fsm safety checking */
62 };
63 
64 
65 /*
66  * btc idle handler
67  */
btc_idle_st_hdl(void * obj,u16 event,void * param)68 static int btc_idle_st_hdl(void *obj, u16 event, void *param)
69 {
70 	struct btc_obj *pbtc = (struct btc_obj *)obj;
71 
72 	FSM_DBG(pbtc->fsm, "[BTC], %s, event : 0x%x\n", __func__, event);
73 	switch (event) {
74 	case FSM_EV_STATE_IN:
75 		break;
76 
77 	case FSM_EV_TIMER_EXPIRE:
78 		break;
79 
80 	case BTC_EV_START:
81 		phl_fsm_state_goto(pbtc->fsm_obj, BTC_ST_SERVICE);
82 		break;
83 
84 	case FSM_EV_STATE_OUT:
85 		break;
86 
87 	default:
88 		break;
89 	}
90 	return 0;
91 }
92 
btc_service_st_hdl(void * obj,u16 event,void * param)93 static int btc_service_st_hdl(void *obj, u16 event, void *param)
94 {
95 	struct btc_obj *pbtc = (struct btc_obj *)obj;
96 	struct phl_info_t *phl_info = pbtc->phl_info;
97 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
98 	int rtn = FSM_FREE_PARAM;
99 
100 	FSM_DBG(pbtc->fsm, "[BTC], %s, event : 0x%x\n", __func__, event);
101 	switch (event) {
102 	case FSM_EV_STATE_IN:
103 		break;
104 
105 	case BTC_EV_UPDATE_ROLE_INFO:
106 		if (param) {
107 			struct rtw_phl_btc_role_info_param *prinfo = NULL;
108 			struct rtw_wifi_role_t *wrole = NULL;
109 			struct rtw_phl_stainfo_t *sta = NULL;
110 
111 			pbtc->ntfy = param;
112 			prinfo = &pbtc->ntfy->u.rinfo;
113 
114 			if (prinfo->role_id < MAX_WIFI_ROLE_NUMBER) {
115 				wrole = &phl_com->wifi_roles[prinfo->role_id];
116 				sta = rtw_phl_get_stainfo_self(phl_info, wrole);
117 			}
118 #ifdef CONFIG_BTCOEX
119 			rtw_hal_btc_update_role_info_ntfy(phl_info->hal,
120 					prinfo->role_id, wrole, sta, prinfo->rstate);
121 #endif
122 			if (pbtc->ntfy->ntfy_cb)
123 				pbtc->ntfy->ntfy_cb(pbtc->ntfy->priv,
124 						pbtc->ntfy->notify,
125 						pbtc->ntfy);
126 
127 			rtn = FSM_FREE_PARAM;
128 		}
129 		break;
130 
131 	case BTC_EV_FWINFO:
132 #ifdef CONFIG_BTCOEX
133 		rtw_hal_btc_fwinfo_ntfy(phl_info->hal);
134 #endif
135 		break;
136 
137 	case BTC_EV_TIMER:
138 	{
139 #ifdef CONFIG_BTCOEX
140 		struct rtw_phl_btc_tmr_param *tmr = NULL;
141 
142 		pbtc->ntfy = param;
143 		tmr = &pbtc->ntfy->u.tmr;
144 
145 		rtw_hal_btc_timer(phl_info->hal, tmr->timer);
146 #endif
147 	}
148 		break;
149 
150 	case BTC_EV_PACKET_EVT:
151 		if (param) {
152 			struct rtw_phl_btc_pkt_param *pkt = NULL;
153 			struct rtw_wifi_role_t *wrole = NULL;
154 			pbtc->ntfy = param;
155 			pkt = &pbtc->ntfy->u.pkt;
156 
157 			if (pkt->role_id < MAX_WIFI_ROLE_NUMBER) {
158 				wrole = &phl_com->wifi_roles[pkt->role_id];
159 			}
160 #ifdef CONFIG_BTCOEX
161 			rtw_hal_btc_packet_event_ntfy(phl_info->hal,
162 							pkt->pkt_evt_type);
163 #endif
164 			if (pbtc->ntfy->ntfy_cb)
165 				pbtc->ntfy->ntfy_cb(pbtc->ntfy->priv,
166 						pbtc->ntfy->notify,
167 						pbtc->ntfy);
168 
169 			rtn = FSM_FREE_PARAM;
170 		}
171 		break;
172 
173 	case FSM_EV_TIMER_EXPIRE:
174 		break;
175 
176 	case FSM_EV_CANCEL:
177 		phl_fsm_state_goto(pbtc->fsm_obj, BTC_ST_IDLE);
178 		break;
179 
180 	case FSM_EV_STATE_OUT:
181 		phl_fsm_cancel_alarm(pbtc->fsm_obj);
182 		break;
183 
184 	default:
185 		break;
186 	}
187 	return rtn;
188 }
189 
btc_dump_obj(void * obj,char * s,int * sz)190 static void btc_dump_obj(void *obj, char *s, int *sz)
191 {
192 	/* nothing to do for now */
193 }
194 
btc_dump_fsm(void * fsm,char * s,int * sz)195 static void btc_dump_fsm(void *fsm, char *s, int *sz)
196 {
197 	/* nothing to do for now */
198 }
199 
200 /* For EXTERNAL application to create a btc FSM */
201 /* @root: FSM root structure
202  * @phl_info: private data structure to invoke hal/phl function
203  *
204  * return
205  * fsm_main: FSM main structure (Do NOT expose)
206  */
phl_btc_new_fsm(struct fsm_root * root,struct phl_info_t * phl_info)207 struct fsm_main *phl_btc_new_fsm(struct fsm_root *root,
208 				struct phl_info_t *phl_info)
209 {
210 	void *d = phl_to_drvpriv(phl_info);
211 	struct fsm_main *fsm = NULL;
212 	struct rtw_phl_fsm_tb tb;
213 
214 	_os_mem_set(d, &tb, 0, sizeof(tb));
215 	tb.max_state = sizeof(btc_state_tbl)/sizeof(btc_state_tbl[0]);
216 	tb.max_event = sizeof(btc_event_tbl)/sizeof(btc_event_tbl[0]);
217 	tb.state_tbl = btc_state_tbl;
218 	tb.evt_tbl = btc_event_tbl;
219 	tb.dump_obj = btc_dump_obj;
220 	tb.dump_obj = btc_dump_fsm;
221 	tb.dbg_level = FSM_DBG_INFO;
222 	tb.evt_level = FSM_DBG_INFO;
223 
224 	fsm = phl_fsm_init_fsm(root, "btc", phl_info, &tb);
225 
226 	return fsm;
227 }
228 
229 /* For EXTERNAL application to destory btc fsm */
230 /* @fsm: see fsm_main
231  */
phl_btc_destory_fsm(struct fsm_main * fsm)232 void phl_btc_destory_fsm(struct fsm_main *fsm)
233 {
234 	if (fsm == NULL)
235 		return;
236 
237 	/* deinit fsm local variable if has */
238 
239 	/* call FSM Framewro to deinit fsm */
240 	phl_fsm_deinit_fsm(fsm);
241 }
242 
243 /* For EXTERNAL application to create btcoex object */
244 /* @fsm: FSM main structure which created by phl_btc_new_fsm()
245  * @phl_info: private data structure to invoke hal/phl function
246  *
247  * return
248  * btc_obj: structure of command object (Do NOT expose)
249  */
phl_btc_new_obj(struct fsm_main * fsm,struct phl_info_t * phl_info)250 struct btc_obj *phl_btc_new_obj(struct fsm_main *fsm,
251 				struct phl_info_t *phl_info)
252 {
253 	struct fsm_obj *obj;
254 	struct btc_obj *pbtc;
255 
256 	pbtc = phl_fsm_new_obj(fsm, (void **)&obj, sizeof(*pbtc));
257 
258 	if (pbtc == NULL || obj == NULL) {
259 		/* TODO free fsm; currently will be freed in deinit process */
260 		FSM_ERR(fsm, "btc: malloc obj fail\n");
261 		return NULL;
262 	}
263 	pbtc->fsm = fsm;
264 	pbtc->fsm_obj = obj;
265 	pbtc->phl_info = phl_info;
266 
267 	return pbtc;
268 }
269 
270 /* For EXTERNAL application to destory btc object */
271 /* @pbtc: local created command object
272  *
273  */
phl_btc_destory_obj(struct btc_obj * pbtc)274 void phl_btc_destory_obj(struct btc_obj *pbtc)
275 {
276 	if (pbtc == NULL)
277 		return;
278 
279 	/* inform FSM framewory to recycle fsm_obj */
280 	phl_fsm_destory_obj(pbtc->fsm_obj);
281 }
282 
283 /* For EXTERNAL application to start btcoex service (expose) */
284 /* @pbtc: btc object
285  */
phl_btc_start(struct btc_obj * pbtc)286 enum rtw_phl_status phl_btc_start(struct btc_obj *pbtc)
287 {
288 	void *d = phl_to_drvpriv(pbtc->phl_info);
289 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
290 	struct fsm_msg *msg;
291 
292 	/* Start FSM */
293 	phl_status = phl_fsm_start_fsm(pbtc->fsm);
294 	if (phl_status != RTW_PHL_STATUS_SUCCESS)
295 		return phl_status;
296 
297 	if (pbtc->fsm_obj == NULL)
298 		return RTW_PHL_STATUS_FAILURE;
299 
300 	/* NEW message to start btc object */
301 	msg = phl_fsm_new_msg(pbtc->fsm_obj, BTC_EV_START);
302 	if (msg == NULL) {
303 		FSM_ERR(pbtc->fsm, "btc: alloc msg fail\n");
304 		return RTW_PHL_STATUS_RESOURCE;
305 	}
306 	if (phl_fsm_sent_msg(pbtc->fsm_obj, msg) != RTW_PHL_STATUS_SUCCESS) {
307 		_os_kmem_free(d, msg, sizeof(*msg));
308 		return RTW_PHL_STATUS_FAILURE;
309 	}
310 
311 	return phl_status;
312 }
313 
314 /* For EXTERNAL application to stop btc service (expose) */
315 /* @pbtc: btc to be cancelled
316  */
phl_btc_cancel(struct btc_obj * pbtc)317 enum rtw_phl_status phl_btc_cancel(struct btc_obj *pbtc)
318 {
319 	return phl_fsm_cancel_obj(pbtc->fsm_obj);
320 }
321 
322 /* For EXTERNAL application to notify btc (expose) */
323 /* @phl: refer to phl_infi_t
324  * @notify: notification event
325  * @ntfy: notify information (optional)
326  * return value:
327  *	0: no wait
328  *	1: have to wait call back info->ntfy_cb()
329  *	-1: Failure
330  */
rtw_phl_btc_notify(void * phl,enum RTW_PHL_BTC_NOTIFY notify,struct rtw_phl_btc_ntfy * ntfy)331 int rtw_phl_btc_notify(void *phl, enum RTW_PHL_BTC_NOTIFY notify,
332 				struct rtw_phl_btc_ntfy *ntfy)
333 {
334 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
335 	struct btc_obj *pbtc = phl_info->btc_obj;
336 	int wait = 0, sz = 0;
337 	u16 event;
338 
339 	if (ntfy)
340 		sz = sizeof(*ntfy);
341 
342 	switch (notify) {
343 	case PHL_BTC_NTFY_ROLE_INFO:
344 		event = BTC_EV_UPDATE_ROLE_INFO;
345 		break;
346 	case PHL_BTC_NTFY_FWINFO:
347 		event = BTC_EV_FWINFO;
348 		break;
349 	case PHL_BTC_NTFY_PACKET_EVT:
350 		event = BTC_EV_PACKET_EVT;
351 		break;
352 	case PHL_BTC_NTFY_MAX:
353 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "rtw_phl_btc_notify(): Unsupported case:%d, please check it\n",
354 				notify);
355 		return wait;
356 	case PHL_BTC_NTFY_TIMER:
357 		event = BTC_EV_TIMER;
358 		break;
359 	default:
360 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "rtw_phl_btc_notify(): Unrecognize case:%d, please check it\n",
361 				notify);
362 		return wait;
363 	}
364 	phl_fsm_gen_msg(phl, pbtc->fsm_obj, ntfy, sz, event);
365 	return wait;
366 }
367 
rtw_phl_btc_role_notify(void * phl,u8 role_id,enum role_state rstate)368 void rtw_phl_btc_role_notify(void *phl, u8 role_id, enum role_state rstate)
369 {
370 	struct rtw_phl_btc_ntfy ntfy = {0};
371 	struct rtw_phl_btc_role_info_param *prinfo = &ntfy.u.rinfo;
372 
373 	prinfo->role_id = role_id;
374 	prinfo->rstate = rstate;
375 
376 	ntfy.notify = PHL_BTC_NTFY_ROLE_INFO;
377 	ntfy.ops = NULL;
378 	ntfy.priv = NULL;
379 	ntfy.ntfy_cb = NULL;
380 
381 	rtw_phl_btc_notify(phl, ntfy.notify, &ntfy);
382 }
383 
384 #ifndef CONFIG_PHL_CMD_BTC
rtw_phl_btc_packet_event_notify(void * phl,u8 role_id,u8 pkt_evt_type)385 void rtw_phl_btc_packet_event_notify(void *phl, u8 role_id, u8 pkt_evt_type)
386 {
387 	struct rtw_phl_btc_ntfy ntfy = {0};
388 	struct rtw_phl_btc_pkt_param *pkt = &ntfy.u.pkt;
389 
390 	pkt->role_id = role_id;
391 	pkt->pkt_evt_type = pkt_evt_type;
392 
393 	ntfy.notify = PHL_BTC_NTFY_PACKET_EVT;
394 	ntfy.ops = NULL;
395 	ntfy.priv = NULL;
396 	ntfy.ntfy_cb = NULL;
397 
398 	rtw_phl_btc_notify(phl, ntfy.notify, &ntfy);
399 }
400 
rtw_phl_btc_pkt_2_evt_type(u8 packet_type)401 u8 rtw_phl_btc_pkt_2_evt_type(u8 packet_type)
402 {
403 	u8 pkt_evt_type = BTC_PKT_EVT_MAX;
404 
405 	switch (packet_type) {
406 	case PACKET_NORMAL:
407 		pkt_evt_type = BTC_PKT_EVT_NORMAL;
408 		break;
409 	case PACKET_DHCP:
410 		pkt_evt_type = BTC_PKT_EVT_DHCP;
411 		break;
412 	case PACKET_ARP:
413 		pkt_evt_type = BTC_PKT_EVT_ARP;
414 		break;
415 	case PACKET_EAPOL:
416 		pkt_evt_type = BTC_PKT_EVT_EAPOL;
417 		break;
418 	case PACKET_EAPOL_START:
419 		pkt_evt_type = BTC_PKT_EVT_EAPOL_START;
420 		break;
421 	default:
422 		PHL_ERR("%s packet type(%d) not support\n",
423 			__func__, packet_type);
424 		break;
425 	}
426 
427 	return pkt_evt_type;
428 }
429 #endif
430 
_btc_fsm_tmr(void * phl,void * timer)431 static void _btc_fsm_tmr(void *phl, void *timer)
432 {
433 	struct rtw_phl_btc_ntfy ntfy = {0};
434 	struct rtw_phl_btc_tmr_param *tmr = &ntfy.u.tmr;
435 
436 	tmr->timer = timer;
437 
438 	ntfy.notify = PHL_BTC_NTFY_TIMER;
439 	ntfy.ops = NULL;
440 	ntfy.priv = NULL;
441 	ntfy.ntfy_cb = NULL;
442 
443 	rtw_phl_btc_notify(phl, ntfy.notify, &ntfy);
444 }
445 
rtw_phl_btc_hub_msg_hdl(void * phl,struct phl_msg * msg)446 void rtw_phl_btc_hub_msg_hdl(void *phl, struct phl_msg *msg)
447 {
448 	u8 mdl_id = MSG_MDL_ID_FIELD(msg->msg_id);
449 	u16 evt_id = MSG_EVT_ID_FIELD(msg->msg_id);
450 
451 	switch (mdl_id) {
452 	case PHL_MDL_BTC:
453 		if (evt_id == BTC_HMSG_TMR_EN) {
454 			_btc_fsm_tmr(phl, msg->inbuf);
455 		} else if (evt_id == BTC_HMSG_FW_EV) {
456 			rtw_phl_btc_notify(phl, PHL_BTC_NTFY_FWINFO, NULL);
457 		}
458 		break;
459 	default:
460 		break;
461 	}
462 }
463 #endif /*CONFIG_FSM*/
464 
465