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_CMD_BTC_C_
16 #include "phl_headers.h"
17
18 #ifdef CONFIG_BTCOEX
19 #ifdef CONFIG_PHL_CMD_BTC
_fail_hdlr(void * phl,struct phl_msg * msg)20 static void _fail_hdlr(void *phl, struct phl_msg *msg)
21 {
22 }
23
_hdl_tmr(void * phl,struct phl_msg * msg)24 static void _hdl_tmr(void *phl, struct phl_msg *msg)
25 {
26 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
27
28 rtw_hal_btc_timer(phl_info->hal, (void *)msg->inbuf);
29 }
30
_hdl_role_notify(void * phl,struct phl_msg * msg)31 static void _hdl_role_notify(void *phl, struct phl_msg *msg)
32 {
33 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
34 struct rtw_role_cmd *rcmd = NULL;
35 struct rtw_wifi_role_t *wrole = NULL;
36 struct rtw_phl_stainfo_t *sta = NULL;
37
38 if (msg->inbuf && (msg->inlen == sizeof(struct rtw_role_cmd))) {
39 rcmd = (struct rtw_role_cmd *)msg->inbuf;
40 wrole = rcmd->wrole;
41 sta = rtw_phl_get_stainfo_self(phl_info, wrole);
42
43 rtw_hal_btc_update_role_info_ntfy(phl_info->hal,
44 rcmd->wrole->id, wrole, sta, rcmd->rstate);
45 } else {
46 PHL_ERR("%s: invalid msg, buf = %p, len = %d\n",
47 __func__, msg->inbuf, msg->inlen);
48 }
49 }
50
_hdl_pkt_evt_notify(void * phl,struct phl_msg * msg)51 static void _hdl_pkt_evt_notify(void *phl, struct phl_msg *msg)
52 {
53 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
54 struct rtw_pkt_evt_ntfy *pkt_evt = NULL;
55 struct rtw_wifi_role_t *wrole = NULL;
56
57 if (msg->inbuf && (msg->inlen == sizeof(struct rtw_pkt_evt_ntfy))) {
58 pkt_evt = (struct rtw_pkt_evt_ntfy *)msg->inbuf;
59 wrole = pkt_evt->wrole; /* not used currently */
60
61 rtw_hal_btc_packet_event_ntfy(phl_info->hal,
62 (u8)pkt_evt->type);
63 } else {
64 PHL_ERR("%s: invalid msg, buf = %p, len = %d\n",
65 __func__, msg->inbuf, msg->inlen);
66 }
67 }
68
_btc_cmd_init(void * phl,void * dispr,void ** priv)69 static enum phl_mdl_ret_code _btc_cmd_init(void *phl, void *dispr,
70 void **priv)
71 {
72 PHL_INFO("[BTCCMD], %s(): \n", __func__);
73
74 *priv = phl;
75 return MDL_RET_SUCCESS;
76 }
77
_btc_cmd_deinit(void * dispr,void * priv)78 static void _btc_cmd_deinit(void *dispr, void *priv)
79 {
80 PHL_INFO("[BTCCMD], %s(): \n", __func__);
81 }
82
_btc_cmd_start(void * dispr,void * priv)83 static enum phl_mdl_ret_code _btc_cmd_start(void *dispr, void *priv)
84 {
85 enum phl_mdl_ret_code ret = MDL_RET_SUCCESS;
86
87 PHL_INFO("[BTCCMD], %s(): \n", __func__);
88
89 return ret;
90 }
91
_btc_cmd_stop(void * dispr,void * priv)92 static enum phl_mdl_ret_code _btc_cmd_stop(void *dispr, void *priv)
93 {
94 enum phl_mdl_ret_code ret = MDL_RET_SUCCESS;
95
96 PHL_INFO("[BTCCMD], %s(): \n", __func__);
97
98 return ret;
99 }
100
101 static enum phl_mdl_ret_code
_btc_internal_pre_msg_hdlr(struct phl_info_t * phl_info,void * dispr,struct phl_msg * msg)102 _btc_internal_pre_msg_hdlr(struct phl_info_t *phl_info,
103 void *dispr,
104 struct phl_msg *msg)
105 {
106 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
107 enum phl_msg_evt_id evt_id = MSG_EVT_ID_FIELD(msg->msg_id);
108
109 /*PHL_INFO("[BTCCMD], msg->band_idx = %d, msg->msg_id = 0x%x\n",
110 msg->band_idx, msg->msg_id);*/
111
112 switch(evt_id) {
113 case MSG_EVT_BTC_REQ_BT_SLOT:
114 PHL_INFO("[BTCCMD], MSG_EVT_BTC_REQ_BT_SLOT \n");
115 ret = MDL_RET_SUCCESS;
116 break;
117
118 case MSG_EVT_BTC_PKT_EVT_NTFY:
119 PHL_INFO("[BTCCMD], MSG_EVT_BTC_PKT_EVT_NTFY \n");
120 _hdl_pkt_evt_notify(phl_info, msg);
121 ret = MDL_RET_SUCCESS;
122 break;
123
124 default:
125 break;
126 }
127
128 return ret;
129 }
130
131 static enum phl_mdl_ret_code
_btc_internal_post_msg_hdlr(struct phl_info_t * phl_info,void * dispr,struct phl_msg * msg)132 _btc_internal_post_msg_hdlr(struct phl_info_t *phl_info,
133 void *dispr,
134 struct phl_msg *msg)
135 {
136 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
137 enum phl_msg_evt_id evt_id = MSG_EVT_ID_FIELD(msg->msg_id);
138
139 switch(evt_id) {
140 case MSG_EVT_BTC_TMR:
141 PHL_DBG("[BTCCMD], MSG_EVT_BTC_TMR \n");
142 _hdl_tmr(phl_info, msg);
143 ret = MDL_RET_SUCCESS;
144 break;
145
146 case MSG_EVT_BTC_FWEVNT:
147 PHL_DBG("[BTCCMD], MSG_EVT_BTC_FWEVNT \n");
148 rtw_hal_btc_fwinfo_ntfy(phl_info->hal);
149 ret = MDL_RET_SUCCESS;
150 break;
151
152 default:
153 break;
154 }
155
156 return ret;
157 }
158
159 static enum phl_mdl_ret_code
_btc_internal_msg_hdlr(struct phl_info_t * phl_info,void * dispr,struct phl_msg * msg)160 _btc_internal_msg_hdlr(struct phl_info_t *phl_info,
161 void *dispr,
162 struct phl_msg *msg)
163 {
164 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
165
166 if (IS_MSG_IN_PRE_PHASE(msg->msg_id))
167 ret = _btc_internal_pre_msg_hdlr(phl_info, dispr, msg);
168 else
169 ret = _btc_internal_post_msg_hdlr(phl_info, dispr, msg);
170
171 return ret;
172 }
173
174 static enum phl_mdl_ret_code
_btc_external_pre_msg_hdlr(struct phl_info_t * phl_info,void * dispr,struct phl_msg * msg)175 _btc_external_pre_msg_hdlr(struct phl_info_t *phl_info,
176 void *dispr,
177 struct phl_msg *msg)
178 {
179 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
180 enum phl_msg_evt_id evt_id = MSG_EVT_ID_FIELD(msg->msg_id);
181 enum band_type band = BAND_ON_5G;
182 struct rtw_hal_com_t *hal_com = rtw_hal_get_halcom(phl_info->hal);
183 enum phl_phy_idx phy_idx = HW_PHY_0;
184
185 /*PHL_INFO("[BTCCMD], msg->band_idx = %d, msg->msg_id = 0x%x\n",
186 msg->band_idx, msg->msg_id);*/
187
188 switch(evt_id) {
189 case MSG_EVT_SCAN_START:
190 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_SCAN)
191 break;
192
193 if (msg->band_idx == HW_BAND_1)
194 phy_idx = HW_PHY_1;
195 PHL_INFO("[BTCCMD], MSG_EVT_SCAN_START \n");
196 band = hal_com->band[msg->band_idx].cur_chandef.band;
197 rtw_hal_btc_scan_start_ntfy(phl_info->hal, phy_idx, band);
198
199 ret = MDL_RET_SUCCESS;
200 break;
201
202 case MSG_EVT_CONNECT_START:
203 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_CONNECT)
204 break;
205
206 PHL_INFO("[BTCCMD], MSG_EVT_CONNECT_START \n");
207 ret = MDL_RET_SUCCESS;
208 break;
209
210 default:
211 break;
212 }
213
214 return ret;
215 }
216
217 static enum phl_mdl_ret_code
_btc_external_post_msg_hdlr(struct phl_info_t * phl_info,void * dispr,struct phl_msg * msg)218 _btc_external_post_msg_hdlr(struct phl_info_t *phl_info,
219 void *dispr,
220 struct phl_msg *msg)
221 {
222 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
223 enum phl_msg_evt_id evt_id = MSG_EVT_ID_FIELD(msg->msg_id);
224 struct hal_info_t *hal_info = (struct hal_info_t *)phl_info->hal;
225 enum phl_phy_idx phy_idx = HW_PHY_0;
226
227 switch(evt_id) {
228 case MSG_EVT_SCAN_END:
229 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_SCAN)
230 break;
231
232 if (msg->band_idx == HW_BAND_1)
233 phy_idx = HW_PHY_1;
234 PHL_DBG("[BTCCMD], MSG_EVT_SCAN_END \n");
235 rtw_hal_btc_scan_finish_ntfy(hal_info, phy_idx);
236 ret = MDL_RET_SUCCESS;
237 break;
238
239 case MSG_EVT_CONNECT_END:
240 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_CONNECT)
241 break;
242
243 PHL_DBG("[BTCCMD], MSG_EVT_CONNECT_END \n");
244 ret = MDL_RET_SUCCESS;
245 break;
246
247 case MSG_EVT_ROLE_NTFY:
248 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_MRC)
249 break;
250
251 PHL_DBG("[BTCCMD], MSG_EVT_ROLE_NTFY \n");
252 _hdl_role_notify(phl_info, msg);
253 ret = MDL_RET_SUCCESS;
254 break;
255
256 case MSG_EVT_BTC_TMR:
257 PHL_DBG("[BTCCMD], MSG_EVT_BTC_TMR \n");
258 _hdl_tmr(phl_info, msg);
259 ret = MDL_RET_SUCCESS;
260 break;
261
262 case MSG_EVT_BTC_FWEVNT:
263 PHL_DBG("[BTCCMD], MSG_EVT_BTC_FWEVNT \n");
264 rtw_hal_btc_fwinfo_ntfy(phl_info->hal);
265 ret = MDL_RET_SUCCESS;
266 break;
267
268 default:
269 break;
270 }
271
272 return ret;
273 }
274
275 static enum phl_mdl_ret_code
_btc_external_msg_hdlr(struct phl_info_t * phl_info,void * dispr,struct phl_msg * msg)276 _btc_external_msg_hdlr(struct phl_info_t *phl_info,
277 void *dispr,
278 struct phl_msg *msg)
279 {
280 enum phl_mdl_ret_code ret = MDL_RET_FAIL;
281
282 if (IS_MSG_IN_PRE_PHASE(msg->msg_id))
283 ret = _btc_external_pre_msg_hdlr(phl_info, dispr, msg);
284 else
285 ret = _btc_external_post_msg_hdlr(phl_info, dispr, msg);
286
287 return ret;
288 }
289
290 static enum phl_mdl_ret_code
_btc_msg_hdlr(void * dispr,void * priv,struct phl_msg * msg)291 _btc_msg_hdlr(void *dispr, void *priv, struct phl_msg *msg)
292 {
293 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
294 struct phl_info_t *phl_info = (struct phl_info_t *)priv;
295
296 FUNCIN();
297
298 if (IS_MSG_FAIL(msg->msg_id)) {
299 PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
300 "%s: cmd dispatcher notify cmd failure: 0x%x.\n",
301 __FUNCTION__, msg->msg_id);
302 _fail_hdlr(phl_info, msg);
303 FUNCOUT();
304 return MDL_RET_FAIL;
305 }
306
307 if (IS_PRIVATE_MSG(msg->msg_id)) {
308 FUNCOUT();
309 return ret;
310 }
311
312 switch(MSG_MDL_ID_FIELD(msg->msg_id)) {
313 case PHL_MDL_BTC:
314 ret = _btc_internal_msg_hdlr(phl_info, dispr, msg);
315 break;
316
317 default:
318 ret = _btc_external_msg_hdlr(phl_info, dispr, msg);
319 break;
320 }
321
322 FUNCOUT();
323 return ret;
324 }
325
326 static enum phl_mdl_ret_code
_btc_set_info(void * dispr,void * priv,struct phl_module_op_info * info)327 _btc_set_info(void *dispr, void *priv,
328 struct phl_module_op_info *info)
329 {
330 PHL_INFO("[BTCCMD], %s(): \n", __func__);
331
332 return MDL_RET_SUCCESS;
333 }
334
335 static enum phl_mdl_ret_code
_btc_query_info(void * dispr,void * priv,struct phl_module_op_info * info)336 _btc_query_info(void *dispr, void *priv,
337 struct phl_module_op_info *info)
338 {
339 PHL_INFO("[BTCCMD], %s(): \n", __func__);
340
341 return MDL_RET_SUCCESS;
342 }
343
phl_register_btc_module(struct phl_info_t * phl_info)344 enum rtw_phl_status phl_register_btc_module(struct phl_info_t *phl_info)
345 {
346 enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
347 struct phl_bk_module_ops bk_ops = {0};
348
349 PHL_INFO("[BTCCMD], %s(): \n", __func__);
350
351 bk_ops.init = _btc_cmd_init;
352 bk_ops.deinit = _btc_cmd_deinit;
353 bk_ops.start = _btc_cmd_start;
354 bk_ops.stop = _btc_cmd_stop;
355 bk_ops.msg_hdlr = _btc_msg_hdlr;
356 bk_ops.set_info = _btc_set_info;
357 bk_ops.query_info = _btc_query_info;
358
359 phl_status = phl_disp_eng_register_module(phl_info, HW_BAND_0,
360 PHL_MDL_BTC, &bk_ops);
361 if (RTW_PHL_STATUS_SUCCESS != phl_status) {
362 PHL_ERR("Failed to register BTC module in cmd dispr of hw band 0\n");
363 }
364
365 return phl_status;
366 }
367
rtw_phl_btc_send_cmd(struct rtw_phl_com_t * phl_com,u8 * buf,u32 len,u16 ev_id)368 bool rtw_phl_btc_send_cmd(struct rtw_phl_com_t *phl_com,
369 u8 *buf, u32 len, u16 ev_id)
370 {
371 struct phl_info_t *phl_info = phl_com->phl_priv;
372 u8 band_idx = HW_BAND_0;
373 struct phl_msg msg = {0};
374 struct phl_msg_attribute attr = {0};
375
376 msg.inbuf = buf;
377 msg.inlen = len;
378 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_BTC);
379 msg.band_idx = band_idx;
380 switch (ev_id) {
381 case BTC_HMSG_TMR_EN:
382 SET_MSG_EVT_ID_FIELD(msg.msg_id,
383 MSG_EVT_BTC_TMR);
384 break;
385 case BTC_HMSG_SET_BT_REQ_SLOT:
386 SET_MSG_EVT_ID_FIELD(msg.msg_id,
387 MSG_EVT_BTC_REQ_BT_SLOT);
388 break;
389 case BTC_HMSG_FW_EV:
390 SET_MSG_EVT_ID_FIELD(msg.msg_id,
391 MSG_EVT_BTC_FWEVNT);
392 break;
393 default:
394 PHL_ERR("%s: Unknown msg !\n", __func__);
395 return false;
396 }
397
398 if (phl_disp_eng_send_msg(phl_info, &msg, &attr, NULL) !=
399 RTW_PHL_STATUS_SUCCESS) {
400 PHL_ERR("%s: [BTC] dispr_send_msg failed !\n", __func__);
401 return false;
402 }
403
404 return true;
405 }
406
407 static void
_phl_pkt_evt_ntfy_done(void * priv,struct phl_msg * msg)408 _phl_pkt_evt_ntfy_done(void* priv, struct phl_msg* msg)
409 {
410 struct phl_info_t *phl_info = (struct phl_info_t *)priv;
411
412 if(msg->inbuf && msg->inlen){
413 _os_mem_free(phl_to_drvpriv(phl_info),
414 msg->inbuf, msg->inlen);
415 }
416 }
417
rtw_phl_btc_packet_event_notify(void * phl,u8 role_id,u8 pkt_evt_type)418 void rtw_phl_btc_packet_event_notify(void *phl, u8 role_id, u8 pkt_evt_type)
419 {
420 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
421 struct phl_msg msg = {0};
422 struct phl_msg_attribute attr = {0};
423 struct rtw_pkt_evt_ntfy *pkt_evt = NULL;
424
425 pkt_evt = (struct rtw_pkt_evt_ntfy *)_os_mem_alloc(
426 phl_to_drvpriv(phl_info), sizeof(struct rtw_pkt_evt_ntfy));
427 if (pkt_evt == NULL) {
428 PHL_ERR("%s: alloc packet cmd fail.\n", __func__);
429 return;
430 }
431
432 pkt_evt->type = pkt_evt_type;
433
434 msg.inbuf = (u8 *)pkt_evt;
435 msg.inlen = sizeof(struct rtw_pkt_evt_ntfy);
436
437 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_BTC);
438 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_BTC_PKT_EVT_NTFY);
439 msg.band_idx = HW_BAND_0;
440 attr.completion.completion = _phl_pkt_evt_ntfy_done;
441 attr.completion.priv = phl_info;
442
443 if (phl_disp_eng_send_msg(phl_info, &msg, &attr, NULL) !=
444 RTW_PHL_STATUS_SUCCESS) {
445 PHL_ERR("%s: dispr_send_msg failed !\n", __func__);
446 goto cmd_fail;
447 }
448
449 return;
450
451 cmd_fail:
452 _os_mem_free(phl_to_drvpriv(phl_info), pkt_evt,
453 sizeof(struct rtw_pkt_evt_ntfy));
454 }
455
rtw_phl_btc_pkt_2_evt_type(u8 packet_type)456 u8 rtw_phl_btc_pkt_2_evt_type(u8 packet_type)
457 {
458 u8 pkt_evt_type = BTC_PKT_EVT_MAX;
459
460 switch (packet_type) {
461 case PACKET_NORMAL:
462 pkt_evt_type = BTC_PKT_EVT_NORMAL;
463 break;
464 case PACKET_DHCP:
465 pkt_evt_type = BTC_PKT_EVT_DHCP;
466 break;
467 case PACKET_ARP:
468 pkt_evt_type = BTC_PKT_EVT_ARP;
469 break;
470 case PACKET_EAPOL:
471 pkt_evt_type = BTC_PKT_EVT_EAPOL;
472 break;
473 case PACKET_EAPOL_START:
474 pkt_evt_type = BTC_PKT_EVT_EAPOL_START;
475 break;
476 default:
477 PHL_ERR("%s packet type(%d) not support\n",
478 __func__, packet_type);
479 break;
480 }
481
482 return pkt_evt_type;
483 }
484 #endif /*CONFIG_PHL_CMD_BTC*/
485
486 #ifndef CONFIG_FSM
rtw_phl_btc_notify(void * phl,enum RTW_PHL_BTC_NOTIFY notify,struct rtw_phl_btc_ntfy * ntfy)487 int rtw_phl_btc_notify(void *phl, enum RTW_PHL_BTC_NOTIFY notify,
488 struct rtw_phl_btc_ntfy *ntfy)
489 {
490 PHL_ERR("CMD_BTC not support :%s\n", __func__);
491 return 0;
492 }
rtw_phl_btc_role_notify(void * phl,u8 role_id,enum role_state rstate)493 void rtw_phl_btc_role_notify(void *phl, u8 role_id, enum role_state rstate)
494 {
495 struct rtw_phl_btc_ntfy ntfy = {0};
496 struct rtw_phl_btc_role_info_param *prinfo = &ntfy.u.rinfo;
497
498 prinfo->role_id = role_id;
499 prinfo->rstate = rstate;
500
501 ntfy.notify = PHL_BTC_NTFY_ROLE_INFO;
502 ntfy.ops = NULL;
503 ntfy.priv = NULL;
504 ntfy.ntfy_cb = NULL;
505
506 rtw_phl_btc_notify(phl, ntfy.notify, &ntfy);
507 }
508
rtw_phl_btc_hub_msg_hdl(void * phl,struct phl_msg * msg)509 void rtw_phl_btc_hub_msg_hdl(void *phl, struct phl_msg *msg)
510 {
511 }
512 #endif
513
514 #endif /*CONFIG_BTCOEX*/
515
516