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_BTC_C_
16 #include "../hal_headers_le.h"
17 #include "hal_btc.h"
18 #include "halbtc_fw.h"
19 #include "halbtc_def.h"
20 #include "halbtc_action.h"
21
22 #ifdef CONFIG_BTCOEX
23
24 /* [31:24] -> main-version
25 * [23:16] -> sub-version
26 * [15:8] -> Hot-Fix-version
27 * [7:0] -> branch ID, ex: 0x00-> Main-Branch
28 * Modify bt_8852x.c chip_8852x member: btcx_desired, wlcx_desired if required
29 * btcx_desired: BT FW coex version -> main-version + 1 if update.
30 * wlcx_desired: WL FW coex version -> sub-version + 1 if update
31 */
32 const u32 coex_ver = 0x0601040f;
33
34 static struct btc_ops _btc_ops = {
35 _send_fw_cmd,
36 _ntfy_power_on,
37 _ntfy_power_off,
38 _ntfy_init_coex,
39 _ntfy_scan_start,
40 _ntfy_scan_finish,
41 _ntfy_switch_band,
42 _ntfy_specific_packet,
43 _ntfy_role_info,
44 _ntfy_radio_state,
45 _ntfy_customerize,
46 _ntfy_wl_rfk,
47 _ntfy_wl_sta,
48 _ntfy_fwinfo,
49 _ntfy_timer
50 };
51
52 #define _update_dbcc_band(phy_idx) \
53 btc->cx.wl.dbcc_info.real_band[phy_idx] =\
54 (btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?\
55 btc->cx.wl.dbcc_info.scan_band[phy_idx] :\
56 btc->cx.wl.dbcc_info.op_band[phy_idx])
57
58 /******************************************************************************
59 *
60 * coex internal functions
61 *
62 *****************************************************************************/
_set_btc_timer(struct btc_t * btc,u16 tmr_id,u32 ms)63 static void _set_btc_timer(struct btc_t *btc, u16 tmr_id, u32 ms)
64 {
65 struct btc_tmr *btmr = NULL;
66
67 if (tmr_id < BTC_TIMER_MAX) {
68 btmr = &btc->timer[tmr_id];
69 _os_set_timer(halcom_to_drvpriv(btc->hal), &btmr->tmr, ms);
70 }
71 }
72
_btmr_stop(struct btc_t * btc)73 static void _btmr_stop(struct btc_t *btc)
74 {
75 struct btc_tmr *btmr = NULL;
76 u8 i = 0;
77
78 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): stop btc timers!!\n",
79 __func__);
80
81 btc->tmr_stop = true;
82
83 for (i = 0; i < BTC_TIMER_MAX; i++) {
84 btmr = &btc->timer[i];
85 _os_cancel_timer(halcom_to_drvpriv(btc->hal), &btmr->tmr);
86 }
87 _os_cancel_timer(halcom_to_drvpriv(btc->hal), &btc->delay_tmr);
88 }
89
_btmr_release(struct btc_t * btc)90 static void _btmr_release(struct btc_t *btc)
91 {
92 struct btc_tmr *btmr = NULL;
93 u8 i = 0;
94
95 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): release btc timers!!\n",
96 __func__);
97
98 for (i = 0; i < BTC_TIMER_MAX; i++) {
99 btmr = &btc->timer[i];
100 _os_release_timer(halcom_to_drvpriv(btc->hal), &btmr->tmr);
101 }
102 _os_release_timer(halcom_to_drvpriv(btc->hal), &btc->delay_tmr);
103 }
104
_btmr_start(struct btc_t * btc)105 static void _btmr_start(struct btc_t *btc)
106 {
107 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): start btc periodic timer!!\n",
108 __func__);
109
110 btc->tmr_stop = false;
111
112 /* Wait 2 sec for phl starting then periodic timer will be started */
113 _os_set_timer(halcom_to_drvpriv(btc->hal),
114 &btc->delay_tmr, BTC_DELAYED_PERIODIC_TIME);
115 }
116
_delay_tmr_cb(void * ctx)117 static void _delay_tmr_cb(void *ctx)
118 {
119 struct btc_t *btc = NULL;
120
121 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s() !!\n", __func__);
122
123 if (!ctx)
124 return;
125
126 btc = (struct btc_t *)ctx;
127
128 _set_btc_timer(btc, BTC_TIMER_PERIODIC, BTC_PERIODIC_TIME);
129 }
130
_btmr_cb(void * ctx)131 static void _btmr_cb(void *ctx)
132 {
133 struct btc_tmr *btmr = NULL;
134 struct btc_t *btc = NULL;
135
136 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(), ctx = 0x%p !!\n",
137 __func__, ctx);
138
139 if (!ctx)
140 return;
141
142 btmr = (struct btc_tmr *)ctx;
143 btc = (struct btc_t *)btmr->btc;
144
145 if (!btc->tmr_init || btc->tmr_stop)
146 return;
147
148 hal_btc_send_event(btc, (u8 *)btmr, sizeof(struct btc_tmr *),
149 BTC_HMSG_TMR_EN);
150 }
151
_btmr_init(struct btc_t * btc)152 static void _btmr_init(struct btc_t *btc)
153 {
154 struct btc_tmr *btmr = NULL;
155 u8 i = 0;
156
157 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): !!\n", __func__);
158
159 for (i = 0; i < BTC_TIMER_MAX; i++) {
160 btmr = &btc->timer[i];
161 btmr->btc = btc;
162 btmr->id = i;
163 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
164 "[BTC], init btc timer(%d) = 0x%p !!\n", i, btmr);
165 _os_init_timer(halcom_to_drvpriv(btc->hal), &btmr->tmr,
166 _btmr_cb, btmr, "btc_tmr");
167 }
168
169 _os_init_timer(halcom_to_drvpriv(btc->hal), &btc->delay_tmr,
170 _delay_tmr_cb, btc, NULL);
171
172 btc->tmr_init = true;
173 btc->tmr_stop = true;
174 }
175
_btmr_deinit(struct btc_t * btc)176 static void _btmr_deinit(struct btc_t *btc)
177 {
178 if (btc->tmr_init) {
179 _btmr_stop(btc);
180 _btmr_release(btc);
181 btc->tmr_init = false;
182 }
183 }
184
185 static void
_send_fw_cmd(struct btc_t * btc,u8 h2c_class,u8 h2c_func,u8 * param,u16 len)186 _send_fw_cmd(struct btc_t *btc, u8 h2c_class, u8 h2c_func, u8 *param, u16 len)
187 {
188 struct rtw_hal_com_t *h = btc->hal;
189 struct btc_wl_info *wl = &btc->cx.wl;
190 struct rtw_g6_h2c_hdr hdr = {0};
191
192 hdr.h2c_class = h2c_class;
193 hdr.h2c_func = h2c_func;
194 hdr.type = H2CB_TYPE_DATA;
195 hdr.content_len = len;
196 hdr.done_ack = 1;
197
198 if (!wl->status.map.init_ok) {
199 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return by btc not init!!\n",
200 __func__);
201 btc->fwinfo.cnt_h2c_fail++;
202 return;
203 } else if ((wl->status.map.rf_off_pre == 1 &&
204 wl->status.map.rf_off == 1) ||
205 (wl->status.map.lps_pre == 1 &&
206 wl->status.map.lps == 1)) {
207 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return by wl off!!\n",
208 __func__);
209 btc->fwinfo.cnt_h2c_fail++;
210 return;
211 }
212
213 btc->fwinfo.cnt_h2c++;
214
215 if (rtw_hal_mac_send_h2c(h, &hdr, (u32 *)param) != 0)
216 btc->fwinfo.cnt_h2c_fail++;
217 }
218
_read_cx_reg(struct btc_t * btc,u32 offset)219 u32 _read_cx_reg(struct btc_t *btc, u32 offset)
220 {
221 u32 val = 0;
222 rtw_hal_mac_coex_reg_read(btc->hal, offset, &val);
223 return val;
224 }
225
_read_cx_ctrl(struct btc_t * btc)226 u8 _read_cx_ctrl(struct btc_t *btc)
227 {
228 u32 val = 0;
229 rtw_hal_mac_get_coex_ctrl(btc->hal, &val);
230
231 return ((u8)val);
232 }
233
_read_scbd(struct btc_t * btc)234 u32 _read_scbd(struct btc_t *btc)
235 {
236 const struct btc_chip *chip = btc->chip;
237 u32 scbd_val = 0;
238
239 if (!chip->scbd)
240 return 0;
241
242 rtw_hal_mac_get_scoreboard(btc->hal, &scbd_val);
243
244 PHL_INFO("[BTC], read scbd : 0x%08x \n", scbd_val);
245 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
246 return (scbd_val);
247 }
248
_write_scbd(struct btc_t * btc,u32 val,bool state)249 void _write_scbd(struct btc_t *btc, u32 val, bool state)
250 {
251 const struct btc_chip *chip = btc->chip;
252 struct btc_wl_info *wl = &btc->cx.wl;
253 u32 scbd_val = 0;
254
255 if (!chip->scbd)
256 return;
257
258 /* only use bit23~0 */
259 scbd_val = (state ? (wl->scbd | val) : (wl->scbd & (~val)));
260
261 if (scbd_val != wl->scbd) {
262 rtw_hal_mac_set_scoreboard(btc->hal, &scbd_val);
263 PHL_INFO("[BTC], write scbd : 0x%08x \n", scbd_val);
264 wl->scbd = scbd_val;
265
266 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
267 /* Add delay to avoid BT FW loss information */
268 _os_delay_us(btc->hal, BTC_SCBD_REWRITE_DELAY);
269 }
270 }
271
272 static u8
_update_rssi_state(struct btc_t * btc,u8 pre_state,u8 rssi,u8 thresh)273 _update_rssi_state(struct btc_t *btc, u8 pre_state, u8 rssi, u8 thresh)
274 {
275 u8 next_state, tol = btc->chip->rssi_tol;
276
277 if (pre_state == BTC_RSSI_ST_LOW ||
278 pre_state == BTC_RSSI_ST_STAY_LOW) {
279 if (rssi >= (thresh + tol))
280 next_state = BTC_RSSI_ST_HIGH;
281 else
282 next_state = BTC_RSSI_ST_STAY_LOW;
283 } else {
284 if (rssi < thresh)
285 next_state = BTC_RSSI_ST_LOW;
286 else
287 next_state = BTC_RSSI_ST_STAY_HIGH;
288 }
289
290 return next_state;
291 }
292
_write_bt_reg(struct btc_t * btc,u8 reg_type,u16 addr,u32 val)293 void _write_bt_reg(struct btc_t *btc, u8 reg_type, u16 addr, u32 val)
294 {
295 u8 buf[4] = {0};
296
297 /* set write address */
298 buf[0] = reg_type;
299 buf[1] = addr & bMASKB0;
300 buf[2] = (addr & bMASKB1) >> 8;
301 hal_btc_fw_set_bt(btc, SET_BT_WREG_ADDR, 3, buf);
302
303 /* set write value */
304 buf[0] = val & bMASKB0;
305 buf[1] = (val & bMASKB1) >> 8;
306 buf[2] = (val & bMASKB2) >> 16;
307 buf[3] = (val & bMASKB3) >> 23;
308 hal_btc_fw_set_bt(btc, SET_BT_WREG_VAL, 4, buf);
309 }
310
_read_bt_reg(struct btc_t * btc,u8 reg_type,u16 addr)311 void _read_bt_reg(struct btc_t *btc, u8 reg_type, u16 addr)
312 {
313 /* this function is only for API call.
314 * If BTC should use hal_btc_fw_set_monreg to read bt reg.
315 */
316 u8 buf[3] = {0};
317
318 /* set write address */
319 buf[0] = reg_type;
320 buf[1] = addr & bMASKB0;
321 buf[2] = (addr & bMASKB1) >> 8;
322 hal_btc_fw_set_bt(btc, SET_BT_RREG_ADDR, sizeof(buf), buf);
323
324 /* To do wait FW event -> BTF_EVNT_BT_REG*/
325 }
326
_set_bt_psd_report(struct btc_t * btc,u8 start_idx,u8 rpt_type)327 void _set_bt_psd_report(struct btc_t *btc, u8 start_idx, u8 rpt_type)
328 {
329 u8 buf[2] = {0};
330
331 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): set bt psd\n",
332 __func__);
333
334 buf[0] = start_idx;
335 buf[1] = rpt_type;
336 hal_btc_fw_set_bt(btc, SET_BT_PSD_REPORT, 2, buf);
337 }
338
_set_bt_info_report(struct btc_t * btc,u8 trigger)339 static void _set_bt_info_report(struct btc_t *btc, u8 trigger)
340 {
341 u8 buf = 0;
342
343 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): query bt info\n",
344 __func__);
345
346 buf = trigger;
347 hal_btc_fw_set_bt(btc, SET_BT_INFO_REPORT, 1, &buf);
348 }
349
_reset_btc_var(struct btc_t * btc,u8 type)350 static void _reset_btc_var(struct btc_t *btc, u8 type)
351 {
352 struct rtw_hal_com_t *h = btc->hal;
353 struct btc_cx *cx = &btc->cx;
354 struct btc_wl_info *wl = &cx->wl;
355 struct btc_bt_info *bt = &cx->bt;
356 struct btc_bt_link_info *bt_linfo = &bt->link_info;
357 struct btc_wl_link_info *wl_linfo = wl->link_info;
358 u8 i;
359
360 PHL_INFO("[BTC], %s()\n", __func__);
361
362 /* Reset Coex variable */
363 if (type & BTC_RESET_CX)
364 hal_mem_set(h, cx, 0, sizeof(struct btc_cx));
365 else if (type & BTC_RESET_BTINFO) /* only for BT enable */
366 hal_mem_set(h, bt, 0, sizeof(struct btc_bt_info));
367
368 if (type & BTC_RESET_CTRL)
369 hal_mem_set(h, &btc->ctrl, 0, sizeof(struct btc_ctrl));
370
371 /* Init Coex variables that are not zero */
372 if (type & BTC_RESET_DM) {
373 hal_mem_set(h, &btc->dm, 0, sizeof(struct btc_dm));
374 hal_mem_set(h, bt_linfo->rssi_state, 0, BTC_BT_RSSI_THMAX);
375
376 for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++)
377 hal_mem_set(h, wl_linfo[i].rssi_state, 0,
378 BTC_WL_RSSI_THMAX);
379
380 /* set the slot_now table to original */
381 _tdma_cpy(&btc->dm.tdma_now, &t_def[CXTD_OFF]);
382 _tdma_cpy(&btc->dm.tdma, &t_def[CXTD_OFF]);
383 _slots_cpy(btc->dm.slot_now, s_def);
384 _slots_cpy(btc->dm.slot, s_def);
385 btc->policy_len = 0;
386 btc->bt_req_len = 0;
387 btc->hubmsg_cnt = 0;
388
389 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
390 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
391 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
392 }
393
394 if (type & BTC_RESET_MDINFO)
395 hal_mem_set(h, &btc->mdinfo, 0, sizeof(struct btc_module));
396 }
397
_chk_wl_rfk_request(struct btc_t * btc)398 static bool _chk_wl_rfk_request(struct btc_t *btc)
399 {
400 struct btc_cx *cx = &btc->cx;
401 struct btc_bt_info *bt = &cx->bt;
402
403 _update_bt_scbd(btc, true);
404
405 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
406
407 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
408 (!bt->rfk_info.map.timeout)) {
409 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
410 return BTC_WRFK_REJECT;
411 } else {
412 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
413 return BTC_WRFK_ALLOW;
414 }
415 }
416
_set_init_info(struct btc_t * btc)417 void _set_init_info(struct btc_t *btc)
418 {
419 struct btc_dm *dm = &btc->dm;
420 struct btc_wl_info *wl = &btc->cx.wl;
421
422 dm->init_info.wl_only = (u8)dm->wl_only;
423 dm->init_info.bt_only = (u8)dm->bt_only;
424 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok;
425 dm->init_info.dbcc_en = btc->hal->dbcc_en;
426 dm->init_info.cx_other = btc->cx.other.type;
427 dm->init_info.wl_guard_ch = btc->chip->afh_guard_ch;
428 dm->init_info.module = btc->mdinfo;
429 }
430
_get_role_link_mode(struct btc_t * btc,u8 role)431 u8 _get_role_link_mode(struct btc_t *btc, u8 role)
432 {
433 switch(role) {
434 case PHL_RTYPE_STATION:
435 return BTC_WLINK_2G_STA;
436 case PHL_RTYPE_P2P_GO:
437 return BTC_WLINK_2G_GO;
438 case PHL_RTYPE_P2P_GC:
439 return BTC_WLINK_2G_GC;
440 case PHL_RTYPE_AP:
441 return BTC_WLINK_2G_AP;
442 default:
443 return BTC_WLINK_OTHER;
444 }
445 }
446
_get_wl_role_idx(struct btc_t * btc,u8 role)447 u8 _get_wl_role_idx(struct btc_t *btc, u8 role)
448 {
449 struct btc_wl_role_info *wl_rinfo = &btc->cx.wl.role_info;
450 u8 i, pid = 0;
451
452 for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
453 if (wl_rinfo->active_role[i].role == role)
454 break;
455 }
456
457 pid = i;
458 return pid; /*cation: return MAX_WIFI_ROLE_NUMBER if role not found */
459 }
460
_set_wl_req_mac(struct btc_t * btc,u8 mac_id)461 void _set_wl_req_mac(struct btc_t *btc, u8 mac_id)
462 {
463 struct btc_wl_info *wl = &btc->cx.wl;
464 struct btc_chip_ops *ops = btc->chip->ops;
465
466 if (mac_id == wl->pta_req_mac)
467 return;
468
469 if (ops && ops->wl_req_mac)
470 ops->wl_req_mac(btc, mac_id);
471
472 wl->pta_req_mac = mac_id;
473 }
474
_chk_role_ch_group(struct btc_t * btc,struct rtw_chan_def r1,struct rtw_chan_def r2)475 static bool _chk_role_ch_group(struct btc_t *btc, struct rtw_chan_def r1, struct rtw_chan_def r2)
476 {
477 bool is_grouped = false;
478
479 if (r1.chan != r2.chan) {
480 /* primary ch is different */
481 goto exit;
482 } else if (r1.bw == CHANNEL_WIDTH_40 && r2.bw == CHANNEL_WIDTH_40) {
483 if (r1.offset != r2.offset)
484 goto exit;
485 }
486
487 is_grouped = true;
488
489 exit:
490 return is_grouped;
491 }
492
_update_wl_info(struct btc_t * btc)493 static void _update_wl_info(struct btc_t *btc)
494 {
495 struct btc_wl_info *wl = &btc->cx.wl;
496 struct btc_wl_link_info *wl_linfo = wl->link_info;
497 struct btc_wl_role_info *wl_rinfo = &wl->role_info;
498 struct btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
499 struct btc_wl_active_role *active_role = NULL;
500 struct rtw_hal_com_t *h = btc->hal;
501 struct rtw_chan_def cid_ch[MAX_WIFI_ROLE_NUMBER];
502 u8 i, j, k, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
503 u8 cnt_2g = 0, cnt_5g = 0, max_role_cnt = BTC_TDMA_WLROLE_MAX;
504 u8 cid_phy[MAX_WIFI_ROLE_NUMBER] = {0};
505 u8 cid_role[MAX_WIFI_ROLE_NUMBER] = {0};
506 u8 dbcc_2g_phy = 0, dbcc_2g_cid = 0, dbcc_2g_role = 0;
507 u32 noa_duration = 0;
508 bool b2g = false, b5g = false, client_joined = false, noa_exist = false;
509
510 hal_mem_set(h, wl_rinfo, 0, sizeof(struct btc_wl_role_info));
511 hal_mem_set(h, wl_dinfo, 0, sizeof(struct btc_wl_dbcc_info));
512 hal_mem_set(h, cid_ch, 0, MAX_WIFI_ROLE_NUMBER * sizeof(struct rtw_chan_def));
513
514 for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
515 /* check if role active? */
516 if (!wl_linfo[i].active || wl_linfo[i].phy >= HW_PHY_MAX)
517 continue;
518
519 cnt_active++;
520 active_role = &wl_rinfo->active_role[cnt_active-1];
521 active_role->role = wl_linfo[i].role;
522 active_role->pid = wl_linfo[i].pid;
523 active_role->phy = wl_linfo[i].phy;
524 active_role->band = wl_linfo[i].chdef.band;
525 active_role->noa = (u8)wl_linfo[i].noa;
526 active_role->noa_duration = wl_linfo[i].noa_duration/1000;
527
528 /* check if role connect? */
529 if (wl_linfo[i].connected == MLME_NO_LINK) {
530 wl_rinfo->active_role[cnt_active-1].connected = 0;
531 continue;
532 } else if (wl_linfo[i].connected == MLME_LINKING) {
533 cnt_connecting++;
534 } else {
535 cnt_connect++;
536 /* only if client connect for p2p-Go/AP */
537 if ((wl_linfo[i].role == PHL_RTYPE_P2P_GO ||
538 wl_linfo[i].role == PHL_RTYPE_AP) &&
539 wl_linfo[i].client_cnt > 1)
540 client_joined = true;
541
542 cid_phy[cnt_connect-1] = wl_linfo[i].phy;
543 hal_mem_cpy(h, &cid_ch[cnt_connect-1],
544 &wl_linfo[i].chdef, sizeof(struct rtw_chan_def));
545
546 cid_role[cnt_connect-1] = wl_linfo[i].role;
547 }
548
549 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
550 active_role->ch = wl_linfo[i].chdef.center_ch;
551 active_role->bw = wl_linfo[i].chdef.bw;
552 active_role->connected = 1;
553
554 /* only one noa-role exist */
555 if (active_role->noa && active_role->noa_duration > 0) {
556 noa_exist = true;
557 noa_duration = active_role->noa_duration;
558 }
559
560 /* Check dbcc role,the last role may overwrite the former role,
561 * This will be modified in the below code.
562 */
563 if (h->dbcc_en) {
564 wl_dinfo->role[wl_linfo[i].phy] = wl_linfo[i].role;
565 wl_dinfo->op_band[wl_linfo[i].phy] = wl_linfo[i].chdef.band;
566 max_role_cnt = BTC_TDMA_WLROLE_MAX + 1;
567 }
568
569 if (wl_linfo[i].chdef.band != BAND_ON_24G) {
570 cnt_5g++;
571 b5g = true;
572 } else {
573 cnt_2g++;
574 b2g = true;
575 }
576 }
577
578 wl_rinfo->connect_cnt = cnt_connect;
579
580 /* Be careful to change the following sequence!! */
581 if (cnt_connect == 0) {
582 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
583 wl_rinfo->role_map.role.none = 1;
584 } else if (!b2g && b5g) {
585 wl_rinfo->link_mode = BTC_WLINK_5G;
586 } else if (wl_rinfo->role_map.role.nan) {
587 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
588 } else if (cnt_connect > max_role_cnt) {
589 wl_rinfo->link_mode = BTC_WLINK_OTHER;
590 } else if (h->dbcc_en) {
591 /* find out the 2G-PHY by connect-id ->ch */
592 for (j = 0; j < cnt_connect; j++) {
593 if (cid_ch[j].center_ch <= 14 || j == cnt_connect-1)
594 break;
595 }
596
597 dbcc_2g_cid = j;
598 dbcc_2g_phy = cid_phy[j];
599 dbcc_2g_role = cid_role[j];
600
601 /* find out the other role in the 2.4G_band-PHY*/
602 if (cnt_connect == 3) {
603 for (k = 0; k < cnt_connect; k++) {
604 if (k == j)
605 continue;
606 else if (cid_phy[k] == dbcc_2g_phy)
607 break;
608 }
609
610 if (k < cnt_connect) { /* if find -> DBCC + MCC/SCC */
611 if (cid_ch[k].center_ch > 14)
612 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
613 else if (_chk_role_ch_group(btc, cid_ch[j], cid_ch[k]))
614 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
615 else
616 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
617
618 /* correct 2G-located PHY role/band
619 * for gnt ctrl.
620 */
621 wl_dinfo->role[dbcc_2g_phy] = dbcc_2g_role;
622 wl_dinfo->op_band[dbcc_2g_phy] = BAND_ON_24G;
623 goto exit;
624 }
625 }
626
627 wl_rinfo->link_mode = _get_role_link_mode(btc, cid_role[j]);
628 } else if (b2g && b5g && cnt_connect == 2) {
629 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
630 } else if (!b5g && cnt_connect == 2) { /* cnt_connect = 2 */
631 if (_chk_role_ch_group(btc, cid_ch[0], cid_ch[cnt_connect - 1]))
632 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
633 else
634 wl_rinfo->link_mode= BTC_WLINK_2G_MCC;
635 } else if (!b5g && cnt_connect == 1) { /* cnt_connect = 1 */
636 wl_rinfo->link_mode = _get_role_link_mode(btc, cid_role[0]);
637 }
638
639 /* if no client_joined, don't care P2P-GO/AP role */
640 if ((wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) &&
641 !client_joined) {
642 #if 0 /* work-around for Go/AP(no-client) can not move channel to same as STA*/
643 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
644 wl_rinfo->link_mode == BTC_WLINK_2G_MCC)
645 #else
646 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC)
647 #endif
648
649 {
650 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
651 wl_rinfo->connect_cnt--;
652 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
653 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
654 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
655 wl_rinfo->connect_cnt--;
656 }
657 }
658
659 exit:
660 /* Identify 2-Role type */
661 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
662 wl_rinfo->link_mode == BTC_WLINK_2G_MCC ||
663 wl_rinfo->link_mode == BTC_WLINK_25G_MCC ||
664 (wl_rinfo->link_mode == BTC_WLINK_5G && cnt_connect > 1)) {
665 if (wl_rinfo->role_map.role.p2p_go ||
666 wl_rinfo->role_map.role.ap) {
667 if (noa_exist)
668 wl_rinfo->mrole_type = BTC_WLMROLE_STA_GO_NOA;
669 else
670 wl_rinfo->mrole_type = BTC_WLMROLE_STA_GO;
671 } else if (wl_rinfo->role_map.role.p2p_gc) {
672 if (noa_exist)
673 wl_rinfo->mrole_type = BTC_WLMROLE_STA_GC_NOA;
674 else
675 wl_rinfo->mrole_type = BTC_WLMROLE_STA_GC;
676 } else {
677 wl_rinfo->mrole_type = BTC_WLMROLE_STA_STA;
678 }
679
680 wl_rinfo->mrole_noa_duration = noa_duration;
681 } else {
682 wl_rinfo->mrole_type = BTC_WLMROLE_NONE;
683 wl_rinfo->mrole_noa_duration = 0;
684 }
685
686 hal_btc_fw_set_drv_info(btc, CXDRVINFO_ROLE);
687
688 if (h->dbcc_en) {
689 _set_wl_req_mac(btc, dbcc_2g_phy);
690 _update_dbcc_band(HW_PHY_0);
691 _update_dbcc_band(HW_PHY_1);
692 hal_btc_fw_set_drv_info(btc, CXDRVINFO_DBCC);
693 } else {
694 _set_wl_req_mac(btc, HW_PHY_0);
695 }
696 }
697
_run_coex(struct btc_t * btc,const char * reason)698 void _run_coex(struct btc_t *btc, const char *reason)
699 {
700 struct btc_dm *dm = &btc->dm;
701 struct btc_cx *cx = &btc->cx;
702 struct btc_wl_info *wl = &cx->wl;
703 struct btc_bt_info *bt = &cx->bt;
704 struct btc_wl_role_info *wl_rinfo = &wl->role_info;
705 u8 mode = wl_rinfo->link_mode;
706
707 PHL_INFO("[BTC], %s(): reason = %s, mode=%d\n", __func__, reason, mode);
708 _rsn_cpy(dm->run_reason, (char*)reason);
709 _update_dm_step(btc, reason);
710
711 #if BTC_CX_FW_OFFLOAD
712 if (wl->rfk_info.state != BTC_WRFK_STOP && mode != BTC_WLINK_5G) {
713 _action_wl_rfk(btc);
714 } else if (wl->rfk_info.state == BTC_WRFK_STOP) {
715 PHL_INFO("[BTC], %s(): offload to WL_FW\n", __func__);
716 hal_btc_fw_set_drv_info(btc, CXDRVINFO_SMAP);
717 hal_btc_fw_set_drv_info(btc, CXDRVINFO_RUN);
718 }
719
720 goto exit;
721 #else
722
723 _update_btc_state_map(btc);
724 _get_wl_nhm_dbm(btc);
725
726 /* Be careful to change the following function sequence!! */
727 if (btc->ctrl.manual) {
728 PHL_INFO("[BTC], %s(): return for Manual CTRL!!\n", __func__);
729 return;
730 }
731
732 if (btc->ctrl.igno_bt &&
733 (run_rsn("_update_bt_info") || run_rsn("_update_bt_scbd"))) {
734 PHL_INFO("[BTC], %s(): return for Stop Coex DM!!\n", __func__);
735 return;
736 }
737
738 if (!wl->status.map.init_ok) {
739 PHL_INFO("[BTC], %s(): return for WL init fail!!\n", __func__);
740 return;
741 }
742
743 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
744 wl->status.map.lps_pre == wl->status.map.lps) {
745 if (run_rsn("_ntfy_power_off") ||
746 run_rsn("_ntfy_radio_state")) {
747 PHL_INFO("[BTC], %s(): return for WL rf off state no change!!\n",
748 __func__);
749 return;
750 }
751
752 if (wl->status.map.rf_off == 1 ||
753 wl->status.map.lps == BTC_LPS_RF_OFF) {
754 PHL_INFO("[BTC], %s(): return for WL rf off state!!\n",
755 __func__);
756 return;
757 }
758 }
759
760 dm->cnt_dm[BTC_DCNT_RUN]++;
761 dm->freerun = false;
762 btc->ctrl.igno_bt = false;
763 bt->scan_rx_low_pri = false;
764
765 if (btc->ctrl.always_freerun) {
766 _action_freerun(btc);
767 btc->ctrl.igno_bt = true;
768 goto exit;
769 }
770
771 if (dm->wl_only) {
772 _action_wl_only(btc);
773 btc->ctrl.igno_bt = true;
774 goto exit;
775 }
776
777 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
778 _action_wl_off(btc);
779 btc->ctrl.igno_bt = true;
780 goto exit;
781 }
782
783 if (run_rsn("_ntfy_init_coex")) {
784 _action_wl_init(btc);
785 goto exit;
786 }
787
788 if (!cx->bt.enable.now && !cx->other.type) {
789 _action_bt_off(btc);
790 goto exit;
791 }
792
793 if (cx->bt.whql_test) {
794 _action_bt_whql(btc);
795 goto exit;
796 }
797
798 if (wl->rfk_info.state != BTC_WRFK_STOP) {
799 _action_wl_rfk(btc);
800 goto exit;
801 }
802
803 if (cx->state_map == BTC_WLINKING &&
804 (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
805 mode == BTC_WLINK_5G)) {
806 _action_wl_scan(btc);
807 goto exit;
808 }
809
810 if (wl->status.map.scan) {
811 _action_wl_scan(btc);
812 goto exit;
813 }
814
815 switch (mode) {
816 case BTC_WLINK_NOLINK:
817 _action_wl_nc(btc);
818 break;
819 case BTC_WLINK_2G_STA:
820 _action_wl_2g_sta(btc);
821 break;
822 case BTC_WLINK_2G_AP:
823 bt->scan_rx_low_pri = true;
824 _action_wl_2g_ap(btc);
825 break;
826 case BTC_WLINK_2G_GO:
827 bt->scan_rx_low_pri = true;
828 _action_wl_2g_go(btc);
829 break;
830 case BTC_WLINK_2G_GC:
831 bt->scan_rx_low_pri = true;
832 _action_wl_2g_gc(btc);
833 break;
834 case BTC_WLINK_2G_SCC:
835 bt->scan_rx_low_pri = true;
836 _action_wl_2g_scc(btc);
837 break;
838 case BTC_WLINK_2G_MCC:
839 bt->scan_rx_low_pri = true;
840 _action_wl_2g_mcc(btc);
841 break;
842 case BTC_WLINK_25G_MCC:
843 bt->scan_rx_low_pri = true;
844 _action_wl_25g_mcc(btc);
845 break;
846 case BTC_WLINK_5G:
847 _action_wl_5g(btc);
848 break;
849 case BTC_WLINK_2G_NAN:
850 _action_wl_2g_nan(btc);
851 break;
852 default:
853 _action_wl_other(btc);
854 break;
855 }
856 #endif
857 exit:
858 _action_common(btc);
859 }
860
_update_offload_runinfo(struct btc_t * btc,u8 * buf,u32 len)861 static void _update_offload_runinfo(struct btc_t *btc, u8 *buf, u32 len)
862 {
863 #if BTC_CX_FW_OFFLOAD
864 u32 val;
865 struct btc_cxr_result *r = NULL;
866
867 if (!buf || buf[0] >= BTC_CXR_MAX)
868 return;
869
870 switch(buf[0]) {
871 case BTC_CXR_WSCBD:
872 val = (buf[4] << 24) + (buf[3] << 16) + (buf[2] << 8) + buf[1];
873 if (val & BIT(31)) /* if val & BIT(31) --> write scbd bit false */
874 _write_scbd(btc, val & 0x7fffffff, false);
875 else
876 _write_scbd(btc, val, true);
877 break;
878 case BTC_CXR_RESULT:
879 r = (struct btc_cxr_result*) &buf[1];
880
881 btc->dm.freerun = r->dm.freerun;
882 btc->dm.wl_ps_ctrl = r->dm.wl_ps_ctrl;
883 btc->dm.leak_ap = r->dm.leak_ap;
884 btc->ctrl.igno_bt = (u16)r->dm.igno_bt;
885 btc->dm.noisy_level = r->dm.noisy_level;
886 btc->dm.set_ant_path = r->dm.set_ant_path;
887
888 btc->dm.rf_trx_para = r->rf_trx_para;
889 btc->cx.state_map = r->cx_state_map;
890 btc->policy_type = (u16)r->policy_type;
891 btc->dm.cnt_dm[BTC_DCNT_RUN] = r->run_cnt;
892
893 hal_mem_cpy(btc->hal, btc->dm.run_reason, r->run_reason,
894 BTC_RSN_MAXLEN);
895 hal_mem_cpy(btc->hal, btc->dm.run_action, r->run_action,
896 BTC_ACT_MAXLEN);
897 break;
898 }
899 #endif
900 }
901
_update_bt_scbd(struct btc_t * btc,bool only_update)902 void _update_bt_scbd(struct btc_t *btc, bool only_update)
903 {
904 struct btc_cx *cx = &btc->cx;
905 struct btc_bt_info *bt = &cx->bt;
906 u32 val;
907 bool status_change = false, bt_link_change = false;
908
909 if (!btc->chip->scbd)
910 return;
911
912 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s()\n", __func__);
913
914 val = _read_scbd(btc);
915
916 if (val == 0xffffffff) {
917 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s return by invalid scbd value\n",
918 __func__);
919 return;
920 }
921
922 if (!(val & BTC_BSCB_ON) ||
923 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX)
924 bt->enable.now = 0;
925 else
926 bt->enable.now = 1;
927
928 if (bt->enable.now != bt->enable.last) {
929 status_change = true;
930 bt_link_change = true;
931 }
932
933 /* reset bt info if bt re-enable */
934 if (bt->enable.now && !bt->enable.last) {
935 _reset_btc_var(btc, BTC_RESET_BTINFO);
936 cx->cnt_bt[BTC_BCNT_REENABLE]++;
937 bt->enable.now = 1;
938 }
939
940 bt->enable.last = bt->enable.now;
941
942 bt->scbd = val;
943 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
944
945 if (bt->whql_test != (u32)(!!(val & BTC_BSCB_WHQL)))
946 status_change = true;
947
948 bt->whql_test = !!(val & BTC_BSCB_WHQL);
949
950 bt->btg_type = (val & BTC_BSCB_BT_S1 ? BTC_BT_BTG: BTC_BT_ALONE);
951
952 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT);
953
954 /* if rfk run 1->0 */
955 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
956 status_change = true;
957
958 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
959
960 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
961
962 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
963
964 /* if connect change */
965 if ((bt->link_info.status.map.connect && (!(val & BTC_BSCB_BT_CONNECT))) ||
966 (!bt->link_info.status.map.connect && (val & BTC_BSCB_BT_CONNECT))) {
967 status_change = true;
968 bt_link_change = true;
969 }
970
971 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
972
973 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
974
975 #if !BTC_CX_FW_OFFLOAD
976 if (bt_link_change) {
977 PHL_INFO("[BTC], %s: bt status change!!\n", __func__);
978 hal_btc_send_event(btc, NULL, 0, BTC_HMSG_BT_LINK_CHG);
979 }
980
981 if (!only_update && status_change)
982 _run_coex(btc, __func__);
983 #endif
984 }
985
986 /******************************************************************************
987 *
988 * coexistence operations for external notifications
989 *
990 *****************************************************************************/
_ntfy_power_on(struct btc_t * btc)991 static void _ntfy_power_on(struct btc_t *btc)
992 {
993 /* no action for power on, beacuse power-on move halmac API
994 * the _ntfy_power_on = _ntfy_init_coex
995 */
996 }
997
_ntfy_power_off(struct btc_t * btc)998 static void _ntfy_power_off(struct btc_t *btc)
999 {
1000 PHL_INFO("[BTC], %s()\n", __func__);
1001 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
1002
1003 btc->cx.wl.status.map.rf_off = 1;
1004 btc->cx.wl.status.map.busy = 0;
1005 _write_scbd(btc, BTC_WSCB_ALL, false);
1006 _run_coex(btc, __func__);
1007
1008 hal_btc_fw_en_rpt(btc, RPT_EN_ALL, 0);
1009
1010 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
1011 }
1012
_ntfy_init_coex(struct btc_t * btc,u8 mode)1013 static void _ntfy_init_coex(struct btc_t *btc, u8 mode)
1014 {
1015 struct btc_dm *dm = &btc->dm;
1016 struct btc_wl_info *wl = &btc->cx.wl;
1017 struct btc_chip_ops *ops = btc->chip->ops;
1018
1019 PHL_INFO("[BTC], %s(): mode=%d\n", __func__, mode);
1020 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
1021 dm->wl_only = (mode == BTC_MODE_WL? 1 : 0);
1022 dm->bt_only = (mode == BTC_MODE_BT? 1 : 0);
1023 wl->status.map.rf_off = (mode == BTC_MODE_WLOFF? 1 : 0);
1024
1025 if (!wl->status.map.init_ok) {
1026 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): return for WL init fail!!\n",
1027 __func__);
1028 dm->error.map.init = true;
1029 return;
1030 }
1031
1032 /* Setup RF front end type from EFuse RFE type*/
1033 if (ops && ops->set_rfe)
1034 ops->set_rfe(btc);
1035
1036 if (ops && ops->init_cfg)
1037 ops->init_cfg(btc);
1038
1039 _write_scbd(btc, BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
1040 _update_bt_scbd(btc, true);
1041
1042 /* check PTA control owner to avoid BT coex issue */
1043 if (_read_cx_ctrl(btc) == BTC_CTRL_BY_WL) {
1044 PHL_TRACE(COMP_PHL_BTC, _PHL_ERR_, "[BTC], %s(): PTA owner warning!!\n",
1045 __func__);
1046 dm->error.map.pta_owner = true;
1047 }
1048
1049 _set_init_info(btc);
1050 _set_wl_tx_power(btc, BTC_WL_DEF_TX_PWR); /* original tx power, no Tx power adjust */
1051 hal_btc_fw_set_slots(btc, CXST_MAX, dm->slot);
1052 hal_btc_fw_set_monreg(btc);
1053 hal_btc_fw_set_drv_info(btc, CXDRVINFO_INIT);
1054 hal_btc_fw_set_drv_info(btc, CXDRVINFO_CTRL);
1055
1056 _run_coex(btc, __func__);
1057 _btmr_start(btc);
1058
1059 #if 0
1060 hal_btc_fw_set_gpio_dbg(btc, CXDGPIO_EN_MAP,
1061 BIT(BTC_DBG_GNT_WL) | BIT(BTC_DBG_GNT_BT));
1062 #endif
1063 }
1064
_ntfy_scan_start(struct btc_t * btc,u8 phy_idx,u8 band)1065 static void _ntfy_scan_start(struct btc_t *btc, u8 phy_idx, u8 band)
1066 {
1067 struct btc_wl_info *wl = &btc->cx.wl;
1068
1069 PHL_INFO("[BTC], %s(): phy_idx=%d, band=%d\n", __func__, phy_idx, band);
1070 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
1071
1072 wl->status.map.scan = true;
1073 wl->scan_info.band[phy_idx] = band;
1074 wl->scan_info.phy_map |= BIT(phy_idx);
1075 hal_btc_fw_set_drv_info(btc, CXDRVINFO_SCAN);
1076
1077 if (btc->hal->dbcc_en) {
1078 wl->dbcc_info.scan_band[phy_idx] = band;
1079 _update_dbcc_band(phy_idx);
1080 hal_btc_fw_set_drv_info(btc, CXDRVINFO_DBCC);
1081 }
1082
1083 _run_coex(btc, __func__);
1084 }
1085
_ntfy_scan_finish(struct btc_t * btc,u8 phy_idx)1086 static void _ntfy_scan_finish(struct btc_t *btc, u8 phy_idx)
1087 {
1088 struct btc_wl_info *wl = &btc->cx.wl;
1089
1090 PHL_INFO("[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
1091 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
1092
1093 wl->status.map.scan = false;
1094 wl->scan_info.phy_map &= ~BIT(phy_idx);
1095 hal_btc_fw_set_drv_info(btc, CXDRVINFO_SCAN);
1096
1097 if (btc->hal->dbcc_en) {
1098 _update_dbcc_band(phy_idx);
1099 hal_btc_fw_set_drv_info(btc, CXDRVINFO_DBCC);
1100 }
1101
1102 _run_coex(btc, __func__);
1103 }
1104
_ntfy_switch_band(struct btc_t * btc,u8 phy_idx,u8 band)1105 static void _ntfy_switch_band(struct btc_t *btc, u8 phy_idx, u8 band)
1106 {
1107 struct btc_wl_info *wl = &btc->cx.wl;
1108
1109 PHL_INFO("[BTC], %s(): phy_idx=%d, band=%d\n", __func__, phy_idx, band);
1110 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
1111
1112 wl->scan_info.band[phy_idx] = band;
1113 wl->scan_info.phy_map |= BIT(phy_idx);
1114 hal_btc_fw_set_drv_info(btc, CXDRVINFO_SCAN);
1115
1116 if (btc->hal->dbcc_en) {
1117 wl->dbcc_info.scan_band[phy_idx] = band;
1118 _update_dbcc_band(phy_idx);
1119 hal_btc_fw_set_drv_info(btc, CXDRVINFO_DBCC);
1120 }
1121
1122 _run_coex(btc, __func__);
1123 }
1124
_ntfy_specific_packet(struct btc_t * btc,u8 pkt_type)1125 static void _ntfy_specific_packet(struct btc_t *btc, u8 pkt_type)
1126 {
1127 struct btc_cx *cx = &btc->cx;
1128 struct btc_wl_info *wl = &cx->wl;
1129 struct btc_bt_link_info *b = &cx->bt.link_info;
1130 struct btc_bt_hfp_desc *hfp = &b->hfp_desc;
1131 struct btc_bt_hid_desc *hid = &b->hid_desc;
1132 u32 cnt, delay = BTC_SPECPKT_MAXT;
1133
1134 switch (pkt_type) {
1135 case BTC_PKT_EVT_DHCP:
1136 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
1137 PHL_INFO("[BTC], %s(): pkt_type=%d, DHCP cnt=%d \n", __func__,
1138 pkt_type, cnt);
1139 wl->status.map.connecting = true;
1140 _set_btc_timer(btc, BTC_TIMER_WL_SPECPKT, delay);
1141 break;
1142 case BTC_PKT_EVT_EAPOL:
1143 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
1144 PHL_INFO("[BTC], %s(): pkt_type=%d, EAPOL cnt=%d \n", __func__,
1145 pkt_type, cnt);
1146 wl->status.map._4way = true;
1147
1148 if (hfp->exist || hid->exist)
1149 delay = delay / 2;
1150
1151 _set_btc_timer(btc, BTC_TIMER_WL_SPECPKT, delay);
1152 break;
1153 case BTC_PKT_EVT_ADD_KEY:
1154 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
1155 PHL_INFO("[BTC], %s(): pkt_type=%d, EAPOL_End cnt=%d \n", __func__,
1156 pkt_type, cnt);
1157 wl->status.map._4way = false;
1158 break;
1159 default:
1160 case BTC_PKT_EVT_ARP:
1161 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
1162 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): pkt_type=%d, ARP cnt=%d\n",
1163 __func__, pkt_type, cnt);
1164 return;
1165 }
1166
1167 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
1168
1169 _run_coex(btc, __func__);
1170 }
1171
_update_bt_psd(struct btc_t * btc,u8 * buf,u32 len)1172 static void _update_bt_psd(struct btc_t *btc, u8 *buf, u32 len)
1173 {
1174 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s():\n", __func__);
1175 }
1176
_update_dm_step(struct btc_t * btc,const char * strin)1177 void _update_dm_step(struct btc_t *btc, const char *strin)
1178 {
1179 struct btc_dm *dm = &btc->dm;
1180 u32 store_index = 0;
1181
1182 dm->dm_step.cnt++;
1183 if (dm->dm_step.cnt == 0)
1184 dm->dm_step.cnt = 1;
1185
1186 store_index = ((dm->dm_step.cnt-1) % BTC_DM_MAXSTEP);
1187 _rsn_cpy(dm->dm_step.step[store_index], (char*)strin);
1188 }
1189
_update_bt_info(struct btc_t * btc,u8 * buf,u32 len)1190 static void _update_bt_info(struct btc_t *btc, u8 *buf, u32 len)
1191 {
1192 struct rtw_hal_com_t *h = btc->hal;
1193 struct btc_cx *cx = &btc->cx;
1194 struct btc_bt_info *bt = &cx->bt;
1195 struct btc_bt_link_info *b = &bt->link_info;
1196 struct btc_bt_hfp_desc *hfp = &b->hfp_desc;
1197 struct btc_bt_hid_desc *hid = &b->hid_desc;
1198 struct btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
1199 struct btc_bt_pan_desc *pan = &b->pan_desc;
1200 union btc_btinfo btinfo;
1201 bool bt_link_change = false;
1202
1203 if (buf[BTC_BTINFO_L1] != BTC_BT_INFO_LEN)
1204 return;
1205
1206 /* return if bt info match last bt-info */
1207 if (!hal_mem_cmp(h, bt->raw_info, buf, BTC_BTINFO_MAX)) {
1208 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s return by bt-info duplicate!!\n",
1209 __func__);
1210 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
1211 return;
1212 }
1213
1214 hal_mem_cpy(h, bt->raw_info, buf, BTC_BTINFO_MAX);
1215
1216 PHL_INFO("[BTC], %s: bt_info[2]=0x%02x\n", __func__, bt->raw_info[2]);
1217
1218 /* reset to mo-connect before update */
1219 b->profile_cnt.last = b->profile_cnt.now;
1220 b->relink.last = b->relink.now;
1221 a2dp->exist_last = a2dp->exist;
1222 b->multi_link.last = b->multi_link.now;
1223 bt->inq_pag.last = bt->inq_pag.now;
1224 b->profile_cnt.now = 0;
1225 hid->type = 0;
1226
1227 /* ======= parse raw info low-Byte2 ======= */
1228 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
1229 b->status.map.connect = btinfo.lb2.connect;
1230 b->status.map.sco_busy = btinfo.lb2.sco_busy;
1231 b->status.map.acl_busy = btinfo.lb2.acl_busy;
1232 b->status.map.inq_pag = btinfo.lb2.inq_pag;
1233 bt->inq_pag.now = btinfo.lb2.inq_pag;
1234 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
1235
1236 hfp->exist = btinfo.lb2.hfp;
1237 b->profile_cnt.now += (u8)hfp->exist;
1238 hid->exist = btinfo.lb2.hid;
1239 b->profile_cnt.now += (u8)hid->exist;
1240 a2dp->exist = btinfo.lb2.a2dp;
1241 b->profile_cnt.now += (u8)a2dp->exist;
1242 pan->exist = btinfo.lb2.pan;
1243 b->profile_cnt.now += (u8)pan->exist;
1244
1245 /* ======= parse raw info low-Byte3 ======= */
1246 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
1247 if (btinfo.lb3.retry != 0)
1248 cx->cnt_bt[BTC_BCNT_RETRY]++;
1249 b->cqddr = btinfo.lb3.cqddr;
1250 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
1251 bt->inq = btinfo.lb3.inq;
1252 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
1253 bt->pag = btinfo.lb3.pag;
1254
1255 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
1256 /* ======= parse raw info high-Byte0 ======= */
1257 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
1258 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
1259 b->rssi = btc->chip->ops->bt_rssi(btc, btinfo.hb0.rssi);
1260
1261 /* ======= parse raw info high-Byte1 ======= */
1262 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
1263 b->status.map.ble_connect = btinfo.hb1.ble_connect;
1264 if (btinfo.hb1.ble_connect)
1265 hid->type |= (hid->exist? BTC_HID_BLE : BTC_HID_RCU);
1266
1267 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
1268 bt->reinit = btinfo.hb1.reinit;
1269 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
1270 b->relink.now = btinfo.hb1.relink;
1271 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
1272 bt->igno_wl = btinfo.hb1.igno_wl;
1273
1274 hid->type |= (btinfo.hb1.voice? BTC_HID_RCU_VOICE : 0);
1275 bt->ble_scan_en = btinfo.hb1.ble_scan;
1276
1277 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
1278 b->role_sw = btinfo.hb1.role_sw;
1279
1280 b->multi_link.now = btinfo.hb1.multi_link;
1281
1282 if (b->multi_link.now != b->multi_link.last)
1283 bt_link_change = true;
1284
1285 /* ======= parse raw info high-Byte2 ======= */
1286 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
1287 pan->active = !!btinfo.hb2.pan_active;
1288
1289 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
1290 b->afh_update = btinfo.hb2.afh_update;
1291 a2dp->active = btinfo.hb2.a2dp_active;
1292 b->slave_role = btinfo.hb2.slave;
1293 hid->slot_info = btinfo.hb2.hid_slot;
1294
1295 if (hid->pair_cnt != btinfo.hb2.hid_cnt)
1296 bt_link_change = true;
1297
1298 hid->pair_cnt = btinfo.hb2.hid_cnt;
1299 hid->type |= (hid->slot_info == BTC_HID_218? BTC_HID_218 : BTC_HID_418);
1300
1301 /* ======= parse raw info high-Byte3 ======= */
1302 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
1303 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
1304
1305 if (b->tx_3M != (u32)btinfo.hb3.tx_3M)
1306 cx->cnt_bt[BTC_BCNT_RATECHG]++;
1307 b->tx_3M = (u32)btinfo.hb3.tx_3M;
1308
1309 a2dp->sink = btinfo.hb3.a2dp_sink;
1310
1311 #if !BTC_CX_FW_OFFLOAD
1312 if (bt->igno_wl && !cx->wl.status.map.rf_off)
1313 _set_bt_ignore_wlan_act(btc, false);
1314
1315 if (b->profile_cnt.now || b->status.map.ble_connect)
1316 hal_btc_fw_en_rpt(btc, RPT_EN_BT_AFH_MAP, 1);
1317 else
1318 hal_btc_fw_en_rpt(btc, RPT_EN_BT_AFH_MAP, 0);
1319
1320 if (bt_link_change) {
1321 PHL_INFO("[BTC], %s: bt link change!!\n", __func__);
1322 hal_btc_send_event(btc, NULL, 0, BTC_HMSG_BT_LINK_CHG);
1323 }
1324
1325 /* reset after A2DP stop->play */
1326 if (!a2dp->exist_last && a2dp->exist) {
1327 a2dp->vendor_id = 0;
1328 a2dp->flush_time = 0;
1329 a2dp->play_latency = 1;
1330 _set_btc_timer(btc, BTC_TIMER_BT_A2DPPLAY, BTC_A2DP_RESUME_MAXT);
1331 }
1332
1333 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 ||
1334 a2dp->play_latency == 1))
1335 hal_btc_fw_en_rpt(btc, RPT_EN_BT_DEVICE_INFO, 1);
1336 else
1337 hal_btc_fw_en_rpt(btc, RPT_EN_BT_DEVICE_INFO, 0);
1338
1339 _run_coex(btc, __func__);
1340 #endif
1341 }
1342
_ntfy_role_info(struct btc_t * btc,u8 rid,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta,enum role_state reason)1343 static void _ntfy_role_info(struct btc_t *btc, u8 rid,
1344 struct rtw_wifi_role_t *wrole,
1345 struct rtw_phl_stainfo_t *sta,
1346 enum role_state reason)
1347 {
1348 struct rtw_hal_com_t *h = btc->hal;
1349 struct btc_wl_info *wl = &btc->cx.wl;
1350 struct btc_wl_link_info *r = NULL;
1351 #ifdef CONFIG_PHL_P2PPS
1352 u8 i =0;
1353 #endif /* CONFIG_PHL_P2PPS */
1354
1355 PHL_INFO("[BTC], %s(), role_id=%d, reason=%d\n", __func__, rid, reason);
1356
1357 if (rid >= MAX_WIFI_ROLE_NUMBER)
1358 return;
1359
1360 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
1361
1362 r = &wl->link_info[rid];
1363
1364 if (wrole) {
1365 r->role = wrole->type;
1366 #ifdef RTW_WKARD_ROLE_TYPE
1367 if (wrole->mstate != MLME_NO_LINK &&
1368 wrole->real_type != PHL_RTYPE_NONE) {
1369 r->role = wrole->real_type;
1370 PHL_INFO("[BTC], rtw_hal_btc_update_role_info_ntfy(): set r.role from type(%d) to real_type(%d)\n",
1371 wrole->type, wrole->real_type);
1372 }
1373 #endif /* RTW_WKARD_ROLE_TYPE */
1374 #ifdef CONFIG_PHL_P2PPS
1375 r->noa = 0;
1376 r->noa_duration = 0;
1377 for (i = 0; i < MAX_NOA_DESC; i++) {
1378 if (wrole->noa_desc[i].enable) {
1379 r->noa = 1;
1380 r->noa_duration = wrole->noa_desc[i].duration;
1381 break;
1382 }
1383 }
1384 #endif /* CONFIG_PHL_P2PPS */
1385 r->phy = wrole->hw_band;
1386 r->pid = wrole->hw_port;
1387 r->active = wrole->active;
1388 r->connected = wrole->mstate;
1389 r->mode = wrole->cap.wmode;
1390 r->client_cnt = wrole->assoc_sta_queue.cnt;
1391 #ifdef RTW_PHL_BCN
1392 r->bcn_period = wrole->bcn_cmn.bcn_interval;
1393 r->dtim_period = wrole->dtim_period;
1394 #endif
1395 hal_mem_cpy(h, &r->chdef, &wrole->chandef,
1396 sizeof(struct rtw_chan_def));
1397 hal_mem_cpy(h, r->mac_addr, wrole->mac_addr, MAC_ALEN);
1398 }
1399
1400 if (sta && wrole->type == PHL_RTYPE_STATION) {/*associated node info??*/
1401 r->mac_id = sta->macid;
1402 r->mode = (u8)sta->wmode;
1403 r->stbc_he_tx = (u32)sta->asoc_cap.stbc_he_tx;
1404 r->stbc_vht_tx = (u32)sta->asoc_cap.stbc_vht_tx;
1405 r->stbc_ht_tx = (u32)sta->asoc_cap.stbc_ht_tx;
1406 }
1407
1408 /* refresh wifi info */
1409 _update_wl_info(btc);
1410
1411 if (r->role == PHL_RTYPE_STATION &&
1412 r->connected == MLME_NO_LINK)
1413 btc->dm.leak_ap = 0;
1414
1415 if (reason == PHL_ROLE_MSTS_STA_CONN_START)
1416 wl->status.map.connecting = 1;
1417 else
1418 wl->status.map.connecting = 0;
1419
1420 if (reason == PHL_ROLE_MSTS_STA_DIS_CONN)
1421 wl->status.map._4way = false;
1422
1423 _run_coex(btc, __func__);
1424 }
1425
_ntfy_radio_state(struct btc_t * btc,u8 rf_state)1426 static void _ntfy_radio_state(struct btc_t *btc, u8 rf_state)
1427 {
1428 struct btc_wl_info *wl = &btc->cx.wl;
1429 struct btc_chip_ops *ops = btc->chip->ops;
1430
1431 PHL_INFO("[BTC], %s(): rf_state =%d\n", __func__, rf_state);
1432 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
1433
1434 switch(rf_state) {
1435 case BTC_RFCTRL_WL_OFF:
1436 wl->status.map.rf_off = 1;
1437 wl->status.map.lps = BTC_LPS_OFF;
1438 wl->status.map.busy = 0;
1439 break;
1440 case BTC_RFCTRL_FW_CTRL: /* LPS-PG, LPS-CG */
1441 wl->status.map.rf_off = 0;
1442 wl->status.map.lps = BTC_LPS_RF_OFF;
1443 wl->status.map.busy = 0;
1444 break;
1445 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
1446 wl->status.map.rf_off = 0;
1447 wl->status.map.lps = BTC_LPS_RF_ON;
1448 wl->status.map.busy = 0;
1449 break;
1450 case BTC_RFCTRL_WL_ON:
1451 default:
1452 wl->status.map.rf_off = 0;
1453 wl->status.map.lps = BTC_LPS_OFF;
1454 break;
1455 }
1456
1457 if (rf_state == BTC_RFCTRL_WL_ON) {
1458 hal_btc_fw_en_rpt(btc, RPT_EN_MREG, 1);
1459 _write_scbd(btc, BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
1460 _update_bt_scbd(btc, true);
1461 if (ops && ops->init_cfg)
1462 ops->init_cfg(btc);
1463 } else {
1464 hal_btc_fw_en_rpt(btc, RPT_EN_ALL, 0);
1465 /* for BT only isolated issue,
1466 * clear all scbd if LPS-PG or "LPS-off to LPS-Protocol"
1467 */
1468 if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
1469 wl->status.map.lps_pre != 0) {
1470 _write_scbd(btc, BTC_WSCB_ON, true);
1471 } else {
1472 _write_scbd(btc, BTC_WSCB_ALL, false);
1473 }
1474 }
1475
1476 _run_coex(btc, __func__);
1477
1478 wl->status.map.rf_off_pre = wl->status.map.rf_off;
1479 wl->status.map.lps_pre = wl->status.map.lps;
1480 }
1481
_ntfy_customerize(struct btc_t * btc,u8 type,u16 len,u8 * buf)1482 static void _ntfy_customerize(struct btc_t *btc, u8 type, u16 len, u8 *buf)
1483 {
1484 struct btc_bt_info *bt = &btc->cx.bt;
1485
1486 if (!buf)
1487 return;
1488
1489 PHL_INFO("[BTC], %s !! \n", __func__);
1490 btc->dm.cnt_notify[BTC_NCNT_CUSTOMERIZE]++;
1491
1492 switch (type) {
1493 case PHL_BTC_CNTFY_BTINFO:
1494 if (len != 1)
1495 return;
1496 buf[0] = bt->raw_info[BTC_BTINFO_L2];
1497 break;
1498 }
1499 }
1500
_ntfy_wl_rfk(struct btc_t * btc,u8 phy_path,u8 type,u8 state)1501 static u8 _ntfy_wl_rfk(struct btc_t *btc, u8 phy_path, u8 type, u8 state)
1502 {
1503 struct btc_cx *cx = &btc->cx;
1504 struct btc_wl_info *wl = &cx->wl;
1505 bool result = BTC_WRFK_REJECT;
1506
1507 wl->rfk_info.type = type;
1508 wl->rfk_info.path_map = phy_path & BTC_RFK_PATH_MAP;
1509 wl->rfk_info.phy_map = (phy_path & BTC_RFK_PHY_MAP) >> 4;
1510 wl->rfk_info.band = (phy_path & BTC_RFK_BAND_MAP) >> 6;
1511 state &= (BIT(0) | BIT(1));
1512
1513 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
1514 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
1515 type, state);
1516
1517 switch (state) {
1518 case BTC_WRFK_START:
1519 result = _chk_wl_rfk_request(btc);
1520 wl->rfk_info.state = (result? BTC_WRFK_START : BTC_WRFK_STOP);
1521 #if 0
1522 hal_btc_fw_set_drv_info(btc, CXDRVINFO_RFK);
1523 _write_scbd(btc, BTC_WSCB_WLRFK, result);
1524 #endif
1525
1526 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
1527 break;
1528 case BTC_WRFK_ONESHOT_START:
1529 case BTC_WRFK_ONESHOT_STOP:
1530 if (wl->rfk_info.state == BTC_WRFK_STOP) {
1531 result = BTC_WRFK_REJECT;
1532 } else {
1533 result = BTC_WRFK_ALLOW;
1534 wl->rfk_info.state = state;
1535 }
1536 break;
1537 case BTC_WRFK_STOP:
1538 result = BTC_WRFK_ALLOW;
1539 wl->rfk_info.state = BTC_WRFK_STOP;
1540 #if 0
1541 hal_btc_fw_set_drv_info(btc, CXDRVINFO_RFK);
1542 _write_scbd(btc, BTC_WSCB_WLRFK, false);
1543 #endif
1544 break;
1545 }
1546
1547 if (result == BTC_WRFK_ALLOW) {
1548 /* Only update coex for RFK START and STOP
1549 * because Start -> OneSHOT_START time is short
1550 */
1551 if (wl->rfk_info.state == BTC_WRFK_START ||
1552 wl->rfk_info.state == BTC_WRFK_STOP)
1553 _run_coex(btc, __func__);
1554
1555 if (wl->rfk_info.state == BTC_WRFK_START) /* wait 300ms */
1556 _set_btc_timer(btc, BTC_TIMER_WL_RFKTO, BTC_WRFK_MAXT);
1557
1558 }
1559
1560 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,"[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
1561 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
1562
1563 return result;
1564 }
1565
_ntfy_wl_sta(struct btc_t * btc,struct rtw_stats * phl_stats,u8 ntfy_num,struct rtw_phl_stainfo_t * sta[],u8 reason)1566 static void _ntfy_wl_sta(struct btc_t *btc, struct rtw_stats *phl_stats,
1567 u8 ntfy_num, struct rtw_phl_stainfo_t *sta[],
1568 u8 reason)
1569 {
1570 struct rtw_hal_com_t *h = btc->hal;
1571 struct btc_wl_info *wl = &btc->cx.wl;
1572 struct btc_dm *dm = &btc->dm;
1573 struct btc_module *module = &btc->mdinfo;
1574 struct btc_wl_stat_info w[MAX_WIFI_ROLE_NUMBER] = {0};
1575 struct btc_traffic *t = NULL, *link_info_t = NULL;
1576 struct btc_wl_link_info *link_info = NULL;
1577 struct rtw_phl_rainfo ra_info = {0};
1578 u8 i, j, busy = 0, dir = 0, rssi_map = 0;
1579 u8 busy_all = 0, dir_all = 0, rssi_map_all = 0;
1580 u8 *rssi_state = NULL, rssi_thres = 0;
1581 bool is_sta_change = false, is_traffic_change = false;
1582 u16 last_tx_rate, last_rx_rate, last_tx_lvl, last_rx_lvl;
1583 u32 chk_intvl = 20;
1584
1585 /* rssi_map = 4 bits for rssi locate in which {60, 50, 40, 30}
1586 * if rssi >= 60% (-50dBm) --> map = 4b'0000 --> rssi_level = 0
1587 * if 50% <= rssi < 60% --> map = 4b'0001 --> rssi_level = 1
1588 * if 40% <= rssi < 50% --> map = 4b'0011 --> rssi_level = 2
1589 * if 30% <= rssi < 40% --> map = 4b'0111 --> rssi_level = 3
1590 * if rssi < 20% --> map = 4b'1111 --> rssi_level = 4
1591 */
1592
1593 dm->cnt_notify[BTC_NCNT_WL_STA]++;
1594
1595 for (i = 0; i < ntfy_num; i++) {
1596 /* Extract btc_wl_stat_info from rtw_phl_stainfo_t */
1597 hal_mem_set(h, &ra_info, 0, sizeof(ra_info));
1598 w[i].pid = sta[i]->wrole->id;
1599 w[i].stat.rssi = sta[i]->hal_sta->rssi_stat.rssi >> 1;
1600
1601 t = &w[i].stat.traffic;
1602 t->tx_lvl = phl_stats->tx_traffic.lvl;
1603 t->tx_sts = phl_stats->tx_traffic.sts;
1604
1605 t->rx_lvl = phl_stats->rx_traffic.lvl;
1606 t->rx_sts = phl_stats->rx_traffic.sts;
1607
1608 if (RTW_HAL_STATUS_SUCCESS ==
1609 rtw_hal_bb_query_rainfo(h, sta[i]->hal_sta, &ra_info))
1610 t->tx_rate = ra_info.rate;
1611 else
1612 t->tx_rate = RTW_DATA_RATE_MAX;
1613
1614 t->rx_rate = h->trx_stat.rx_rate_plurality;
1615
1616 /* transfer btc_wl_stat_info to btc_wl_link_info */
1617 link_info = &wl->link_info[w[i].pid];
1618 link_info_t = &link_info->stat.traffic;
1619
1620 if (link_info->connected == MLME_NO_LINK) {
1621 link_info->rx_rate_drop_cnt = 0;
1622 rssi_map_all |= rssi_map;
1623 continue;
1624 }
1625
1626 last_tx_rate = link_info_t->tx_rate;
1627 last_rx_rate = link_info_t->rx_rate;
1628 last_tx_lvl = (u16)link_info_t->tx_lvl;
1629 last_rx_lvl = (u16)link_info_t->rx_lvl;
1630
1631 /* refresh link_info traffic/rssi related info from t */
1632 hal_mem_cpy(h, (void *)link_info_t, (void *)t,
1633 sizeof(struct btc_traffic));
1634
1635 link_info->stat.rssi = w[i].stat.rssi;
1636 rssi_map = 0;
1637
1638 /* check if rssi across wl_rssi_thres boundary */
1639 for (j = 0; j < BTC_WL_RSSI_THMAX; j++) {
1640 if (module->ant.type == BTC_ANT_SHARED && j == 0)
1641 rssi_thres = BTC_WL_RSSI_MAX_BTG;
1642 else
1643 rssi_thres = btc->chip->wl_rssi_thres[j];
1644
1645 rssi_state = &link_info->rssi_state[j];
1646 *rssi_state = _update_rssi_state(btc, *rssi_state,
1647 link_info->stat.rssi,
1648 rssi_thres);
1649
1650 /* fill rssi bit map 0~3 if rssi < threshold */
1651 if (BTC_RSSI_LOW(*rssi_state))
1652 rssi_map |= BIT(j);
1653
1654 if (module->ant.type == BTC_ANT_DEDICATED &&
1655 BTC_RSSI_CHANGE(*rssi_state))
1656 is_sta_change = true;
1657 }
1658
1659 /* OR STA/GC role rssi map */
1660 if (link_info->role == PHL_RTYPE_STATION ||
1661 link_info->role == PHL_RTYPE_P2P_GC)
1662 rssi_map_all |= rssi_map;
1663
1664 /* set busy once idle->busy immediately */
1665 if (t->tx_lvl != RTW_TFC_IDLE || t->rx_lvl != RTW_TFC_IDLE) {
1666 busy = 1;
1667 link_info->busy_t = _os_get_cur_time_ms();
1668
1669 if (t->tx_lvl > t->rx_lvl)
1670 dir = TRAFFIC_UL;
1671 else
1672 dir = TRAFFIC_DL;
1673 } else {/*set idle if busy -> idle after BTC_BUSY2IDLE_THRES*/
1674 if (phl_get_passing_time_ms(link_info->busy_t) >
1675 BTC_BUSY2IDLE_THRES ||
1676 !wl->role_info.role_map.role.station ||
1677 wl->role_info.link_mode == BTC_WLINK_NOLINK) {
1678 busy = 0;
1679 dir = TRAFFIC_DL;
1680 } else {
1681 busy = link_info->busy;
1682 dir = link_info->dir;
1683 }
1684 }
1685
1686 if (link_info->busy != busy || link_info->dir != dir) {
1687 is_sta_change = true;
1688 link_info->busy = busy;
1689 link_info->dir = dir;
1690 }
1691
1692 /* OR all role busy/dir state */
1693 busy_all |= link_info->busy;
1694 dir_all |= BIT(link_info->dir);
1695
1696 if (link_info_t->rx_rate <= RTW_DATA_RATE_CCK2 &&
1697 last_rx_rate > RTW_DATA_RATE_CCK2 &&
1698 link_info_t->rx_lvl > 0)
1699 link_info->rx_rate_drop_cnt++;
1700
1701 if (last_tx_rate != link_info_t->tx_rate ||
1702 last_rx_rate != link_info_t->rx_rate ||
1703 last_tx_lvl != link_info_t->tx_lvl ||
1704 last_rx_lvl != link_info_t->rx_lvl )
1705 is_traffic_change = true;
1706
1707 wl->role_info.active_role[w[i].pid].tx_lvl = (u16)t->tx_lvl;
1708 wl->role_info.active_role[w[i].pid].rx_lvl = (u16)t->rx_lvl;
1709 wl->role_info.active_role[w[i].pid].tx_rate = t->tx_rate;
1710 wl->role_info.active_role[w[i].pid].rx_rate = t->rx_rate;
1711 }
1712
1713 wl->rssi_level = 0;
1714 for (j = BTC_WL_RSSI_THMAX; j > 0; j--) {
1715 /* set RSSI level 4 ~ 0 if rssi bit map match */
1716 if (rssi_map_all & BIT(j-1)) {
1717 wl->rssi_level = j;
1718 break;
1719 }
1720 }
1721
1722 chk_intvl = BTC_RPT_PERIOD/BTC_PERIODIC_TIME;
1723
1724 if (dm->cnt_notify[BTC_NCNT_WL_STA] >=
1725 dm->cnt_dm[BTC_DCNT_WL_STA_LAST] + chk_intvl)
1726 _get_wl_nhm_dbm(btc);
1727
1728 dm->cnt_dm[BTC_DCNT_WL_STA_LAST] = dm->cnt_notify[BTC_NCNT_WL_STA];
1729
1730 /* for TDD/FDD packet estimation in WL FW */
1731 if (is_traffic_change)
1732 hal_btc_fw_set_drv_info(btc, CXDRVINFO_ROLE);
1733
1734 if (is_sta_change) {
1735 wl->status.map.busy = (u32)busy_all;
1736 wl->status.map.traffic_dir = (u32)dir_all;
1737 _write_scbd(btc, BTC_WSCB_WLBUSY, (bool)(!!busy_all));
1738 _run_coex(btc, __func__);
1739 }
1740 }
1741
_ntfy_fwinfo(struct btc_t * btc,u8 * buf,u32 len,u8 cls,u8 func)1742 static void _ntfy_fwinfo(struct btc_t *btc, u8 *buf, u32 len, u8 cls, u8 func)
1743 {
1744 struct btf_fwinfo *pfwinfo = &btc->fwinfo;
1745
1746 if (!buf || !len)
1747 return;
1748
1749 btc->dm.cnt_notify[BTC_NCNT_FWINFO]++;
1750 pfwinfo->cnt_c2h++;
1751
1752 if (cls == BTFC_FW_EVENT) {
1753 switch (func) {
1754 case BTF_EVNT_RPT:
1755 case BTF_EVNT_BUF_OVERFLOW:
1756 pfwinfo->event[func]++;
1757 hal_btc_fw_event(btc, func, buf, len);
1758 break;
1759 case BTF_EVNT_BT_INFO:
1760 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
1761 _update_bt_info(btc, buf, len);
1762 break;
1763 case BTF_EVNT_BT_SCBD:
1764 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
1765 _update_bt_scbd(btc, false);
1766 break;
1767 case BTF_EVNT_BT_PSD:
1768 _update_bt_psd(btc, buf, len);
1769 break;
1770 case BTF_EVNT_BT_REG:
1771 btc->dbg.rb_done = true;
1772 btc->dbg.rb_val = ((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]));
1773 break;
1774 case BTF_EVNT_C2H_LOOPBACK:
1775 btc->dbg.rb_done = true;
1776 btc->dbg.rb_val = buf[0];
1777 break;
1778 case BTF_EVNT_CX_RUNINFO:
1779 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
1780 _update_offload_runinfo(btc, buf, len);
1781 break;
1782 }
1783 }
1784 }
1785
_ntfy_timer(struct btc_t * btc,u16 tmr_id)1786 static void _ntfy_timer(struct btc_t *btc, u16 tmr_id)
1787 {
1788 struct btc_dm *dm = &btc->dm;
1789 struct btc_cx *cx = &btc->cx;
1790 struct btc_wl_info *wl = &cx->wl;
1791 struct btc_bt_a2dp_desc *a2dp = &cx->bt.link_info.a2dp_desc;
1792 bool is_sta_change = false;
1793
1794 PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
1795 "[BTC], %s(): tmr_id =%d\n", __func__, tmr_id);
1796
1797 dm->cnt_notify[BTC_NCNT_TIMER]++;
1798
1799 if (tmr_id == BTC_TIMER_PERIODIC) {
1800 /* start next periodic timer */
1801 _set_btc_timer(btc, BTC_TIMER_PERIODIC, BTC_PERIODIC_TIME);
1802 } else if (tmr_id == BTC_TIMER_WL_RFKTO) {
1803 if (wl->rfk_info.state != BTC_WRFK_STOP) {
1804 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
1805 dm->error.map.wl_rfk_timeout = true;
1806 wl->rfk_info.state = BTC_WRFK_STOP;
1807 /* _write_scbd(btc, BTC_WSCB_WLRFK, false); */
1808 is_sta_change = true;
1809 }
1810 } else if (tmr_id == BTC_TIMER_WL_SPECPKT) {
1811 wl->status.map._4way = false;
1812 wl->status.map.connecting = 0;
1813 is_sta_change = true;
1814 } else if (tmr_id == BTC_TIMER_BT_A2DPPLAY) {
1815 a2dp->play_latency = 0;
1816 is_sta_change = true;
1817 }
1818
1819 if (is_sta_change)
1820 _run_coex(btc, __func__);
1821 }
1822
1823 /******************************************************************************
1824 *
1825 * coexistence extern functions
1826 *
1827 *****************************************************************************/
1828 /*
1829 * btc related sw initialization
1830 */
hal_btc_init(struct btc_t * btc)1831 bool hal_btc_init(struct btc_t *btc)
1832 {
1833 switch (btc->hal->chip_id) {
1834 #ifdef BTC_8852A_SUPPORT
1835 case CHIP_WIFI6_8852A:
1836 PHL_INFO("[BTC], %s(): Init 8852A!!\n", __func__);
1837 btc->chip = &chip_8852a;
1838 break;
1839 #endif
1840 #ifdef BTC_8852B_SUPPORT
1841 case CHIP_WIFI6_8852B:
1842 PHL_INFO("[BTC], %s(): Init 8852B!!\n", __func__);
1843 btc->chip = &chip_8852b;
1844 break;
1845 #endif
1846 #ifdef BTC_8852C_SUPPORT
1847 case CHIP_WIFI6_8852C:
1848 PHL_INFO("[BTC], %s(): Init 8852C!!\n", __func__);
1849 btc->chip = &chip_8852c;
1850 break;
1851 #endif
1852 default:
1853 PHL_ERR("[BTC], %s(): no matched IC!!\n", __func__);
1854 btc->cx.wl.status.map.init_ok = false;
1855 return false;
1856 }
1857
1858 _reset_btc_var(btc, BTC_RESET_ALL);
1859 _btmr_init(btc);
1860
1861 _rsn_cpy(btc->dm.run_reason, "None");
1862 _act_cpy(btc->dm.run_action, "None");
1863
1864 btc->hal->btc_vc.btc_ver = coex_ver;
1865 btc->ops = &_btc_ops;
1866 btc->mlen = BTC_MSG_MAXLEN;
1867 btc->ctrl.igno_bt = true;
1868 btc->cx.wl.status.map.init_ok = true;
1869
1870 return true;
1871 }
1872
hal_btc_deinit(struct btc_t * btc)1873 void hal_btc_deinit(struct btc_t *btc)
1874 {
1875 _btmr_deinit(btc);
1876 }
1877
1878 #endif
1879
1880