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 _HAL_API_BTC_C_
16 #include "hal_headers.h"
17 #include "btc/hal_btc.h"
18
19 #ifdef CONFIG_BTCOEX
20
21 /*******************************************
22 * C2H FW message
23 *******************************************/
24 #define BTC_FWBUF_NUM 4
25 struct fw_msg_entry {
26 _os_list list;
27 u8 c2h_class;
28 u8 c2h_func;
29 u16 len;
30 u8 buf[RTW_PHL_BTC_FWINFO_BUF];
31 };
32
_bt_msg_init(struct rtw_hal_com_t * hal_com,struct hal_bt_msg * msg)33 static void _bt_msg_init(struct rtw_hal_com_t *hal_com,
34 struct hal_bt_msg *msg)
35 {
36 void *d = halcom_to_drvpriv(hal_com);
37
38 _os_spinlock_init(d, &msg->lock);
39 _os_mem_set(d, &msg->latest[0], 0, RTW_BTC_OVERWRITE_BUF_LEN);
40 _os_mem_set(d, &msg->working[0], 0, RTW_BTC_OVERWRITE_BUF_LEN);
41 msg->len = 0;
42 msg->cnt = 0;
43 }
44
_bt_msg_deinit(struct rtw_hal_com_t * hal_com,struct hal_bt_msg * msg)45 static void _bt_msg_deinit(struct rtw_hal_com_t *hal_com,
46 struct hal_bt_msg *msg)
47 {
48 void *d = halcom_to_drvpriv(hal_com);
49
50 _os_spinlock_free(d, &msg->lock);
51 }
52
_msg_enq(struct rtw_hal_com_t * hal_com,struct phl_queue * q,struct fw_msg_entry * entry)53 static void _msg_enq(struct rtw_hal_com_t *hal_com,
54 struct phl_queue *q, struct fw_msg_entry *entry)
55 {
56 pq_push(halcom_to_drvpriv(hal_com), q, &entry->list, _tail, _bh);
57 }
58
_msg_deq(struct rtw_hal_com_t * hal_com,struct phl_queue * q)59 static struct fw_msg_entry *_msg_deq(struct rtw_hal_com_t *hal_com,
60 struct phl_queue *q)
61 {
62 struct fw_msg_entry *entry = NULL;
63 _os_list *list = NULL;
64
65 if (pq_pop(halcom_to_drvpriv(hal_com), q, &list, _first, _bh))
66 entry = (struct fw_msg_entry *)list;
67
68 return entry;
69 }
70
_fw_msg_init(struct rtw_hal_com_t * hal_com)71 static bool _fw_msg_init(struct rtw_hal_com_t *hal_com)
72 {
73 void *d = halcom_to_drvpriv(hal_com);
74 struct btc_fw_msg *fw_msg = &hal_com->btc_msg;
75 struct fw_msg_entry *entry = NULL;
76 u16 i = 0;
77
78 _os_spinlock_init(d, &fw_msg->lock);
79 fw_msg->fev_cnt = 0;
80
81 _bt_msg_init(hal_com, &fw_msg->btinfo);
82 _bt_msg_init(hal_com, &fw_msg->scbd);
83
84 pq_init(d, &fw_msg->idleq);
85 pq_init(d, &fw_msg->waitq);
86 for (i = 0; i < BTC_FWBUF_NUM; i++) {
87 entry = (struct fw_msg_entry *)_os_kmem_alloc(d,
88 sizeof(struct fw_msg_entry));
89 if (entry)
90 _msg_enq(hal_com, &fw_msg->idleq, entry);
91 else
92 return false;
93 }
94
95 return true;
96 }
97
_fw_msg_free(struct rtw_hal_com_t * hal_com)98 static void _fw_msg_free(struct rtw_hal_com_t *hal_com)
99 {
100 void *d = halcom_to_drvpriv(hal_com);
101 struct btc_fw_msg *fw_msg = &hal_com->btc_msg;
102 struct fw_msg_entry *entry = NULL;
103
104 _bt_msg_deinit(hal_com, &fw_msg->btinfo);
105 _bt_msg_deinit(hal_com, &fw_msg->scbd);
106
107 while (1) {
108 entry = _msg_deq(hal_com, &fw_msg->waitq);
109 if (entry)
110 _os_kmem_free(d, entry, sizeof(struct fw_msg_entry));
111 else
112 break;
113 }
114 pq_deinit(d, &fw_msg->waitq);
115
116 while (1) {
117 entry = _msg_deq(hal_com, &fw_msg->idleq);
118 if (entry)
119 _os_kmem_free(d, entry, sizeof(struct fw_msg_entry));
120 else
121 break;
122 }
123 pq_deinit(d, &fw_msg->idleq);
124
125 _os_spinlock_free(d, &fw_msg->lock);
126 }
127
_copy_btmsg(struct rtw_hal_com_t * hal_com,struct hal_bt_msg * msg,u16 len,u8 * buf)128 static void _copy_btmsg(struct rtw_hal_com_t *hal_com,
129 struct hal_bt_msg *msg, u16 len, u8 *buf)
130 {
131 void *d = halcom_to_drvpriv(hal_com);
132
133 if (len > RTW_BTC_OVERWRITE_BUF_LEN)
134 return;
135
136 _os_spinlock(d, &msg->lock, _bh, NULL);
137 msg->cnt++;
138 msg->len = len;
139 _os_mem_cpy(d, &msg->latest[0], buf, len);
140 _os_spinunlock(d, &msg->lock, _bh, NULL);
141 }
142
_fw_evnt_enq(struct rtw_hal_com_t * hal_com,u8 cls,u8 func,u16 len,u8 * buf)143 static bool _fw_evnt_enq(struct rtw_hal_com_t *hal_com,
144 u8 cls, u8 func, u16 len, u8 *buf)
145 {
146 struct btc_fw_msg *fmsg = &hal_com->btc_msg;
147 void *d = halcom_to_drvpriv(hal_com);
148 struct fw_msg_entry *entry = NULL;
149
150 entry = _msg_deq(hal_com, &fmsg->idleq);
151 if (!entry)
152 return false;
153
154 entry->c2h_class = cls;
155 entry->c2h_func = func;
156 entry->len = len;
157 _os_mem_cpy(d, &entry->buf[0], buf, len);
158 _msg_enq(hal_com, &fmsg->waitq, entry);
159
160 return true;
161 }
162
rtw_hal_btc_init(struct rtw_phl_com_t * phl_com,struct hal_info_t * hal_info)163 enum rtw_hal_status rtw_hal_btc_init(struct rtw_phl_com_t *phl_com,
164 struct hal_info_t *hal_info)
165 {
166 enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;
167 struct btc_t *btc = NULL;
168 void *drv_priv = NULL;
169
170 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "%s\n", __FUNCTION__);
171
172 drv_priv = halcom_to_drvpriv(hal_info->hal_com);
173 btc = _os_mem_alloc(drv_priv, sizeof(struct btc_t));
174 if (!btc) {
175 hal_status = RTW_HAL_STATUS_RESOURCE;
176 goto error_btc_init;
177 }
178
179 /* assign phl_com & hal_com */
180 btc->phl = phl_com;
181 btc->hal = hal_info->hal_com;
182
183 if (!hal_btc_init(btc)) {
184 hal_status = RTW_HAL_STATUS_BTC_INIT_FAILURE;
185 goto error_btc_init;
186 }
187
188 if (!_fw_msg_init(hal_info->hal_com)) {
189 hal_status = RTW_HAL_STATUS_BTC_INIT_FAILURE;
190 goto error_msg_init;
191 }
192
193
194 hal_status = RTW_HAL_STATUS_SUCCESS;
195 hal_info->btc = btc;
196
197 return hal_status;
198
199 error_msg_init:
200 _fw_msg_free(hal_info->hal_com);
201
202 error_btc_init:
203 if (btc) {
204 _os_mem_free(drv_priv, (void *)btc, sizeof(struct btc_t));
205 hal_info->btc = NULL;
206 }
207
208 return hal_status;
209 }
210
rtw_hal_btc_deinit(struct rtw_phl_com_t * phl_com,struct hal_info_t * hal_info)211 void rtw_hal_btc_deinit(struct rtw_phl_com_t *phl_com,
212 struct hal_info_t *hal_info)
213 {
214 struct btc_t *btc = hal_info->btc;
215 void *drv_priv = NULL;
216
217 _fw_msg_free(hal_info->hal_com);
218
219 drv_priv = halcom_to_drvpriv(hal_info->hal_com);
220 if (drv_priv && btc) {
221 hal_btc_deinit(btc);
222 _os_mem_free(drv_priv, (void *)btc, sizeof(struct btc_t));
223 }
224 }
225
226 /**********************/
227 /* called by non-hal layers */
228 /**********************/
rtw_hal_btc_update_role_info_ntfy(void * hinfo,u8 role_id,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta,enum role_state rstate)229 void rtw_hal_btc_update_role_info_ntfy(void *hinfo, u8 role_id,
230 struct rtw_wifi_role_t *wrole,
231 struct rtw_phl_stainfo_t *sta,
232 enum role_state rstate)
233 {
234 struct hal_info_t *h = (struct hal_info_t *)hinfo;
235 struct btc_t *btc = (struct btc_t *)h->btc;
236 struct btc_ops *ops = btc->ops;
237
238 if (ops && ops->ntfy_role_info)
239 ops->ntfy_role_info(btc, role_id, wrole, sta, rstate);
240 }
241
rtw_hal_btc_power_on_ntfy(void * hinfo)242 void rtw_hal_btc_power_on_ntfy(void *hinfo)
243 {
244 }
245
rtw_hal_btc_power_off_ntfy(void * hinfo)246 void rtw_hal_btc_power_off_ntfy(void *hinfo)
247 {
248 struct hal_info_t *h = (struct hal_info_t *)hinfo;
249 struct btc_t *btc = (struct btc_t *)h->btc;
250 struct btc_ops *ops = btc->ops;
251
252 if (ops && ops->ntfy_power_off)
253 ops->ntfy_power_off(btc);
254 }
255
rtw_hal_btc_init_coex_cfg_ntfy(void * hinfo)256 void rtw_hal_btc_init_coex_cfg_ntfy(void *hinfo)
257 {
258 struct hal_info_t *h = (struct hal_info_t *)hinfo;
259 struct btc_t *btc = (struct btc_t *)h->btc;
260 struct btc_ops *ops = btc->ops;
261 u8 mode = btc->phl->dev_cap.btc_mode;
262
263 if (ops && ops->ntfy_init_coex)
264 ops->ntfy_init_coex(btc, mode);
265 }
266
rtw_hal_btc_scan_start_ntfy(void * hinfo,enum phl_phy_idx phy_idx,enum band_type band)267 void rtw_hal_btc_scan_start_ntfy(void *hinfo, enum phl_phy_idx phy_idx,
268 enum band_type band)
269 {
270 struct hal_info_t *h = (struct hal_info_t *)hinfo;
271 struct btc_t *btc = (struct btc_t *)h->btc;
272 struct btc_ops *ops = btc->ops;
273
274 if (ops && ops->ntfy_scan_start)
275 ops->ntfy_scan_start(btc, phy_idx, band);
276 }
277
rtw_hal_btc_scan_finish_ntfy(void * hinfo,enum phl_phy_idx phy_idx)278 void rtw_hal_btc_scan_finish_ntfy(void *hinfo, enum phl_phy_idx phy_idx)
279 {
280 struct hal_info_t *h = (struct hal_info_t *)hinfo;
281 struct btc_t *btc = (struct btc_t *)h->btc;
282 struct btc_ops *ops = btc->ops;
283
284 if (ops && ops->ntfy_scan_finish)
285 ops->ntfy_scan_finish(btc, phy_idx);
286 }
287
rtw_hal_btc_switch_band_ntfy(void * hinfo,enum phl_phy_idx phy_idx,enum band_type band)288 void rtw_hal_btc_switch_band_ntfy(void *hinfo, enum phl_phy_idx phy_idx,
289 enum band_type band)
290 {
291 struct hal_info_t *h = (struct hal_info_t *)hinfo;
292 struct btc_t *btc = (struct btc_t *)h->btc;
293 struct btc_ops *ops = btc->ops;
294
295 if (ops && ops->ntfy_switch_band)
296 ops->ntfy_switch_band(btc, phy_idx, band);
297 }
298
rtw_hal_btc_packet_event_ntfy(void * hinfo,u8 pkt_evt_type)299 void rtw_hal_btc_packet_event_ntfy(void *hinfo, u8 pkt_evt_type)
300 {
301 struct hal_info_t *h = (struct hal_info_t *)hinfo;
302 struct btc_t *btc = (struct btc_t *)h->btc;
303 struct btc_ops *ops = btc->ops;
304
305 if (ops && ops->ntfy_specific_packet)
306 ops->ntfy_specific_packet(btc, pkt_evt_type);
307 }
308
rtw_hal_btc_radio_state_ntfy(void * hinfo,u8 rf_state)309 void rtw_hal_btc_radio_state_ntfy(void *hinfo, u8 rf_state)
310 {
311 struct hal_info_t *h = (struct hal_info_t *)hinfo;
312 struct btc_t *btc = (struct btc_t *)h->btc;
313 struct btc_ops *ops = btc->ops;
314
315 if (ops && ops->ntfy_radio_state)
316 ops->ntfy_radio_state(btc, rf_state);
317 }
318
rtw_hal_btc_customerize_ntfy(void * hinfo,u8 type,u16 len,u8 * buf)319 void rtw_hal_btc_customerize_ntfy(void *hinfo, u8 type, u16 len, u8 *buf)
320 {
321 struct hal_info_t *h = (struct hal_info_t *)hinfo;
322 struct btc_t *btc = (struct btc_t *)h->btc;
323 struct btc_ops *ops = btc->ops;
324
325 if (ops && ops->ntfy_customerize)
326 ops->ntfy_customerize(btc, type, len, buf);
327 }
328
rtw_hal_btc_wl_rfk_ntfy(struct rtw_hal_com_t * hal_com,u8 phy_idx,u8 rfk_type,u8 rfk_process)329 u8 rtw_hal_btc_wl_rfk_ntfy(struct rtw_hal_com_t *hal_com, u8 phy_idx, u8 rfk_type, u8 rfk_process)
330 {
331 struct hal_info_t *h = hal_com->hal_priv;
332 struct btc_t *btc = (struct btc_t *)h->btc;
333 struct btc_ops *ops = btc->ops;
334 u8 val = 0;
335
336 if (ops && ops->ntfy_wl_rfk)
337 val = ops->ntfy_wl_rfk(btc, phy_idx, rfk_type, rfk_process);
338
339 return val;
340 }
341
rtw_hal_btc_wl_status_ntfy(void * hinfo,struct rtw_phl_com_t * phl_com,u8 ntfy_num,struct rtw_phl_stainfo_t * sta[],u8 reason)342 void rtw_hal_btc_wl_status_ntfy(void *hinfo, struct rtw_phl_com_t *phl_com, u8 ntfy_num,
343 struct rtw_phl_stainfo_t *sta[], u8 reason)
344 {
345 struct hal_info_t *h = (struct hal_info_t *)hinfo;
346 struct btc_t *btc = (struct btc_t *)h->btc;
347 struct btc_ops *ops = btc->ops;
348
349 if (ops && ops->ntfy_wl_sta)
350 ops->ntfy_wl_sta(btc, &phl_com->phl_stats,
351 ntfy_num, sta, reason);
352
353 }
354
rtw_hal_btc_fwinfo_ntfy(void * hinfo)355 void rtw_hal_btc_fwinfo_ntfy(void *hinfo)
356 {
357 struct hal_info_t *h = (struct hal_info_t *)hinfo;
358 struct btc_t *btc = (struct btc_t *)h->btc;
359 struct btc_ops *ops = btc->ops;
360 struct rtw_hal_com_t *hal_com = h->hal_com;
361 void *d = halcom_to_drvpriv(hal_com);
362 struct btc_fw_msg *fmsg = &hal_com->btc_msg;
363 struct hal_bt_msg *bmsg = NULL;
364 struct fw_msg_entry *entry = NULL;
365
366 _os_spinlock(d, &fmsg->lock, _bh, NULL);
367 fmsg->fev_cnt = 0;
368 _os_spinunlock(d, &fmsg->lock, _bh, NULL);
369
370 if (!ops || !ops->ntfy_fwinfo)
371 return;
372
373 /* bt score board notification */
374 while (1) {
375 bmsg = &fmsg->scbd;
376 if (bmsg->cnt) {
377 _os_spinlock(d, &bmsg->lock, _bh, NULL);
378 bmsg->cnt = 0;
379 _os_mem_cpy(d, &bmsg->working[0],
380 &bmsg->latest[0], bmsg->len);
381 _os_spinunlock(d, &bmsg->lock, _bh, NULL);
382 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
383 "[BTC], scoreboard notify !! \n");
384 ops->ntfy_fwinfo(btc, &bmsg->working[0], bmsg->len,
385 BTC_CLASS_FEV, BTC_FEV_BT_SCBD);
386 } else
387 break;
388 }
389
390 /* bt info notification */
391 while (1) {
392 bmsg = &fmsg->btinfo;
393 if (bmsg->cnt) {
394 _os_spinlock(d, &bmsg->lock, _bh, NULL);
395 bmsg->cnt = 0;
396 _os_mem_cpy(d, &bmsg->working[0],
397 &bmsg->latest[0], bmsg->len);
398 _os_spinunlock(d, &bmsg->lock, _bh, NULL);
399 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
400 "[BTC], bt info notify !! \n");
401 ops->ntfy_fwinfo(btc, &bmsg->working[0], bmsg->len,
402 BTC_CLASS_FEV, BTC_FEV_BT_INFO);
403 } else
404 break;
405 }
406
407 /* common btc fw events */
408 while (1) {
409 entry = _msg_deq(hal_com, &fmsg->waitq);
410 if (entry) {
411 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
412 "[BTC], fw event notify !! \n");
413 ops->ntfy_fwinfo(btc, entry->buf, entry->len,
414 entry->c2h_class, entry->c2h_func);
415 _msg_enq(hal_com, &fmsg->idleq, entry);
416 }
417 else
418 break;
419 }
420 }
421
rtw_hal_btc_timer(void * hinfo,void * timer)422 void rtw_hal_btc_timer(void *hinfo, void *timer)
423 {
424 struct hal_info_t *h = (struct hal_info_t *)hinfo;
425 struct btc_t *btc = (struct btc_t *)h->btc;
426 struct btc_ops *ops = btc->ops;
427 struct btc_tmr *btmr = NULL;
428 u8 i = 0;
429 bool found = false;
430
431 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
432 "[BTC], %s(), timer = 0x%p !!\n", __func__, timer);
433
434 if (!hinfo || !timer)
435 return;
436
437 btmr = (struct btc_tmr *)timer;
438
439 for (i = 0; i < BTC_TIMER_MAX; i++) {
440 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
441 "[BTC], %s(): btmr = 0x%p, &btc->timer[%d] = 0x%p \n",
442 __func__, btmr, i, &btc->timer[i]);
443 if (btmr == &btc->timer[i]) {
444 found = true;
445 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
446 "[BTC], %s(): found timer %p, id = %d \n",
447 __func__, btmr, btmr->id);
448 break;
449 }
450 }
451
452 if (ops && found) {
453 if (btmr->id == BTC_TIMER_PERIODIC) {
454 struct rtw_wifi_role_t *wrole = NULL;
455 struct rtw_phl_stainfo_t *sta = NULL;
456 struct rtw_phl_stainfo_t *wrole_sta[MAX_WIFI_ROLE_NUMBER] = {0};
457 u8 ntfy_num = 0;
458
459 for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
460 wrole = &(btc->phl->wifi_roles[i]);
461 if(wrole->mstate == MLME_LINKED) {
462 sta = rtw_phl_get_stainfo_self(
463 btc->phl->phl_priv, wrole);
464 if(sta != NULL) {
465 wrole_sta[ntfy_num] = sta;
466 ntfy_num++;
467 }
468 }
469 }
470 rtw_hal_btc_wl_status_ntfy(hinfo, btc->phl, ntfy_num,
471 wrole_sta, PHL_BTC_NTFY_RSN_PERIOTIC);
472 }
473 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
474 "[BTC], %s(): btmr->id = %d \n",
475 __func__, btmr->id);
476 if(ops->ntfy_timer)
477 ops->ntfy_timer(btc, btmr->id);
478 } else {
479 PHL_INFO("[BTC], %s(): not found, ops = 0x%p, found = %d \n",
480 __func__, ops, found);
481 }
482 }
483
rtw_hal_btc_req_bt_slot_t(void * hinfo)484 u32 rtw_hal_btc_req_bt_slot_t(void *hinfo)
485 {
486 struct hal_info_t *h = (struct hal_info_t *)hinfo;
487 struct btc_t *btc = (struct btc_t *)h->btc;
488
489 return btc->bt_req_len;
490 }
491
492 /***********************/
493 /* Called by BTC submodule */
494 /***********************/
hal_btc_send_event(struct btc_t * btc,u8 * buf,u32 len,u16 ev_id)495 void hal_btc_send_event(struct btc_t *btc, u8 *buf, u32 len, u16 ev_id)
496 {
497 #ifdef CONFIG_PHL_CMD_BTC
498 rtw_phl_btc_send_cmd(btc->phl, buf, len, ev_id);
499 #endif
500 }
501
hal_btc_notify_ps_tdma(struct btc_t * btc,bool tdma_start)502 void hal_btc_notify_ps_tdma(struct btc_t *btc, bool tdma_start)
503 {
504 #ifdef CONFIG_POWER_SAVE
505 enum rtw_hal_status hstatus;
506
507 hstatus = rtw_hal_ps_pwr_req(btc->phl, HAL_BTC_PWR_REQ, (tdma_start ? true : false));
508 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
509 PHL_ERR("[BTC], %s, TDMA (%d) request pwr fail, status: %d \n",
510 __func__, tdma_start, hstatus);
511 }
512 #endif
513 }
514
rtw_hal_btc_proc_cmd(struct hal_info_t * hal_info,struct rtw_proc_cmd * incmd,char * output,u32 out_len)515 bool rtw_hal_btc_proc_cmd(struct hal_info_t *hal_info, struct rtw_proc_cmd *incmd,
516 char *output, u32 out_len)
517 {
518 if(incmd->in_type == RTW_ARG_TYPE_BUF)
519 halbtc_cmd(hal_info->btc, incmd->in.buf, output, out_len);
520 else if(incmd->in_type == RTW_ARG_TYPE_ARRAY){
521 halbtc_cmd_parser(hal_info->btc, incmd->in.vector,
522 incmd->in_cnt_len, output, out_len);
523 }
524
525 return true;
526 }
527
528
529 #endif
530
531 enum rtw_hal_status
rtw_hal_btc_get_efuse_info(struct rtw_hal_com_t * hal_com,u8 * efuse_map,enum rtw_efuse_info info_type,void * value,u8 size,u8 map_valid)532 rtw_hal_btc_get_efuse_info(struct rtw_hal_com_t *hal_com,
533 u8 *efuse_map, enum rtw_efuse_info info_type, void *value,
534 u8 size, u8 map_valid)
535 {
536 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "%s\n", __FUNCTION__);
537 return RTW_HAL_STATUS_SUCCESS;
538 }
539
rtw_hal_btc_process_c2h(void * hal,struct rtw_c2h_info * c2h)540 u32 rtw_hal_btc_process_c2h(void *hal, struct rtw_c2h_info *c2h)
541 {
542 struct hal_info_t *h = (struct hal_info_t *)hal;
543 struct btc_t *btc = (struct btc_t *)h->btc;
544 struct rtw_hal_com_t *hal_com = h->hal_com;
545 struct btc_fw_msg *fmsg = &hal_com->btc_msg;
546 void *d = halcom_to_drvpriv(hal_com);
547 u8 cls = c2h->c2h_class;
548 u8 func = c2h->c2h_func;
549 u16 len = c2h->content_len;
550 u8 *buf = c2h->content;
551
552 if (len && len < RTW_PHL_BTC_FWINFO_BUF) {
553 if (cls == BTC_CLASS_FEV && func == BTC_FEV_BT_INFO)
554 _copy_btmsg(hal_com, &fmsg->btinfo, len, buf);
555 else if (cls == BTC_CLASS_FEV && func == BTC_FEV_BT_SCBD)
556 _copy_btmsg(hal_com, &fmsg->scbd, len, buf);
557 else
558 _fw_evnt_enq(hal_com, cls, func, len, buf);
559
560 _os_spinlock(d, &fmsg->lock, _bh, NULL);
561 if (fmsg->fev_cnt == 0) {
562 if (rtw_phl_btc_send_cmd(btc->phl, NULL, 0,
563 BTC_HMSG_FW_EV))
564 fmsg->fev_cnt++;
565 }
566 _os_spinunlock(d, &fmsg->lock, _bh, NULL);
567 } else {
568 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): Invalid c2h packet len : %d\n",
569 __func__, len);
570 }
571
572 return 0;
573 }
574
575