xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/hal_g6/btc/hal_btc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _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