xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/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 btc_wl_link_info * info,enum role_state reason)1343 static void _ntfy_role_info(struct btc_t *btc, u8 rid,
1344 			    struct btc_wl_link_info *info,
1345 			    enum role_state reason)
1346 {
1347 	struct rtw_hal_com_t *h = btc->hal;
1348 	struct btc_wl_info *wl = &btc->cx.wl;
1349 	struct btc_wl_link_info *wlinfo = NULL;
1350 
1351 	PHL_INFO("[BTC], %s(), role_id=%d, reason=%d\n", __func__, rid, reason);
1352 
1353 	if (rid >= MAX_WIFI_ROLE_NUMBER)
1354 		return;
1355 
1356 	btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
1357 
1358 	wlinfo = &wl->link_info[rid];
1359 
1360 	hal_mem_cpy(h, wlinfo, info, sizeof(struct btc_wl_link_info));
1361 
1362 	/* update wifi_link_info_ext variable */
1363 	_update_wl_info(btc);
1364 
1365 	if (wlinfo->role == PHL_RTYPE_STATION &&
1366 	    wlinfo->connected == MLME_NO_LINK)
1367 	    btc->dm.leak_ap = 0;
1368 
1369 	if (reason == PHL_ROLE_MSTS_STA_CONN_START)
1370 		wl->status.map.connecting = 1;
1371 	else
1372 		wl->status.map.connecting = 0;
1373 
1374 	if (reason == PHL_ROLE_MSTS_STA_DIS_CONN)
1375 		wl->status.map._4way = false;
1376 
1377 	_run_coex(btc, __func__);
1378 }
1379 
_ntfy_radio_state(struct btc_t * btc,u8 rf_state)1380 static void _ntfy_radio_state(struct btc_t *btc, u8 rf_state)
1381 {
1382 	struct btc_wl_info *wl = &btc->cx.wl;
1383 	struct btc_chip_ops *ops = btc->chip->ops;
1384 
1385 	PHL_INFO("[BTC], %s(): rf_state =%d\n", __func__, rf_state);
1386 	btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
1387 
1388 	switch(rf_state) {
1389 	case BTC_RFCTRL_WL_OFF:
1390 		wl->status.map.rf_off = 1;
1391 		wl->status.map.lps = BTC_LPS_OFF;
1392 		wl->status.map.busy = 0;
1393 		break;
1394 	case BTC_RFCTRL_FW_CTRL: /*  LPS-PG, LPS-CG */
1395 		wl->status.map.rf_off = 0;
1396 		wl->status.map.lps = BTC_LPS_RF_OFF;
1397 		wl->status.map.busy = 0;
1398 		break;
1399 	case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
1400 		wl->status.map.rf_off = 0;
1401 		wl->status.map.lps = BTC_LPS_RF_ON;
1402 		wl->status.map.busy = 0;
1403 		break;
1404 	case BTC_RFCTRL_WL_ON:
1405 	default:
1406 		wl->status.map.rf_off = 0;
1407 		wl->status.map.lps = BTC_LPS_OFF;
1408 		break;
1409 	}
1410 
1411 	if (rf_state == BTC_RFCTRL_WL_ON) {
1412 		hal_btc_fw_en_rpt(btc, RPT_EN_MREG, 1);
1413 		_write_scbd(btc, BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
1414 		_update_bt_scbd(btc, true);
1415 		if (ops && ops->init_cfg)
1416 			ops->init_cfg(btc);
1417 	} else {
1418 		hal_btc_fw_en_rpt(btc, RPT_EN_ALL, 0);
1419 		/* for BT only isolated issue,
1420 		 * clear all scbd if LPS-PG or "LPS-off to LPS-Protocol"
1421 		 */
1422 		if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
1423 		    wl->status.map.lps_pre != 0) {
1424 			_write_scbd(btc, BTC_WSCB_ON, true);
1425 		} else {
1426 			_write_scbd(btc, BTC_WSCB_ALL, false);
1427 		}
1428 	}
1429 
1430 	_run_coex(btc, __func__);
1431 
1432 	wl->status.map.rf_off_pre = wl->status.map.rf_off;
1433 	wl->status.map.lps_pre = wl->status.map.lps;
1434 }
1435 
_ntfy_customerize(struct btc_t * btc,u8 type,u16 len,u8 * buf)1436 static void _ntfy_customerize(struct btc_t *btc, u8 type, u16 len, u8 *buf)
1437 {
1438 	struct btc_bt_info *bt = &btc->cx.bt;
1439 
1440 	if (!buf)
1441 		return;
1442 
1443 	PHL_INFO("[BTC], %s !! \n", __func__);
1444 	btc->dm.cnt_notify[BTC_NCNT_CUSTOMERIZE]++;
1445 
1446 	switch (type) {
1447 	case PHL_BTC_CNTFY_BTINFO:
1448 		if (len != 1)
1449 			return;
1450 		buf[0] = bt->raw_info[BTC_BTINFO_L2];
1451 		break;
1452 	}
1453 }
1454 
_ntfy_wl_rfk(struct btc_t * btc,u8 phy_path,u8 type,u8 state)1455 static u8 _ntfy_wl_rfk(struct btc_t *btc, u8 phy_path, u8 type, u8 state)
1456 {
1457 	struct btc_cx *cx = &btc->cx;
1458 	struct btc_wl_info *wl = &cx->wl;
1459 	bool result = BTC_WRFK_REJECT;
1460 
1461 	wl->rfk_info.type = type;
1462 	wl->rfk_info.path_map = phy_path & BTC_RFK_PATH_MAP;
1463 	wl->rfk_info.phy_map = (phy_path & BTC_RFK_PHY_MAP) >> 4;
1464 	wl->rfk_info.band = (phy_path & BTC_RFK_BAND_MAP) >> 6;
1465 	state &= (BIT(0) | BIT(1));
1466 
1467 	PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
1468 		 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
1469 		 type, state);
1470 
1471 	switch (state) {
1472 	case BTC_WRFK_START:
1473 		result = _chk_wl_rfk_request(btc);
1474 		wl->rfk_info.state = (result? BTC_WRFK_START : BTC_WRFK_STOP);
1475 #if 0
1476 		hal_btc_fw_set_drv_info(btc, CXDRVINFO_RFK);
1477 		_write_scbd(btc, BTC_WSCB_WLRFK, result);
1478 #endif
1479 
1480 		btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
1481 		break;
1482 	case BTC_WRFK_ONESHOT_START:
1483 	case BTC_WRFK_ONESHOT_STOP:
1484 		if (wl->rfk_info.state == BTC_WRFK_STOP) {
1485 			result = BTC_WRFK_REJECT;
1486 		} else {
1487 			result = BTC_WRFK_ALLOW;
1488 			wl->rfk_info.state = state;
1489 		}
1490 		break;
1491 	case BTC_WRFK_STOP:
1492 		result = BTC_WRFK_ALLOW;
1493 		wl->rfk_info.state = BTC_WRFK_STOP;
1494 #if 0
1495 		hal_btc_fw_set_drv_info(btc, CXDRVINFO_RFK);
1496 		_write_scbd(btc, BTC_WSCB_WLRFK, false);
1497 #endif
1498 		break;
1499 	}
1500 
1501 	if (result == BTC_WRFK_ALLOW) {
1502 		/* Only update coex for RFK START and STOP
1503 		 * because Start -> OneSHOT_START time is short
1504 		 */
1505 		if (wl->rfk_info.state == BTC_WRFK_START ||
1506 		    wl->rfk_info.state == BTC_WRFK_STOP)
1507 			_run_coex(btc, __func__);
1508 
1509 		if (wl->rfk_info.state == BTC_WRFK_START) /* wait 300ms */
1510 			_set_btc_timer(btc, BTC_TIMER_WL_RFKTO, BTC_WRFK_MAXT);
1511 
1512 	}
1513 
1514 	PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,"[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
1515 		 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
1516 
1517 	return result;
1518 }
1519 
_ntfy_wl_sta(struct btc_t * btc,u8 ntfy_num,struct btc_wl_stat_info stat_info[],u8 reason)1520 static void _ntfy_wl_sta(struct btc_t *btc, u8 ntfy_num,
1521 			 struct btc_wl_stat_info stat_info[], u8 reason)
1522 {
1523 	struct rtw_hal_com_t *h = btc->hal;
1524 	struct btc_wl_info *wl = &btc->cx.wl;
1525 	struct btc_dm *dm = &btc->dm;
1526 	struct btc_module *module = &btc->mdinfo;
1527 	struct btc_wl_stat_info *w = NULL;
1528 	struct btc_traffic *t = NULL, *link_info_t = NULL;
1529 	struct btc_wl_link_info *link_info = NULL;
1530 	u8 i, j, busy = 0, dir = 0, rssi_map = 0;
1531 	u8 busy_all = 0, dir_all = 0, rssi_map_all = 0;
1532 	u8 *rssi_state = NULL, rssi_thres = 0;
1533 	bool is_sta_change = false, is_traffic_change = false;
1534 	u16 last_tx_rate, last_rx_rate, last_tx_lvl, last_rx_lvl;
1535 	u32 chk_intvl = 20;
1536 
1537 	/* rssi_map = 4 bits for rssi locate in which {60, 50, 40, 30}
1538 	 * if rssi >= 60% (-50dBm) --> map = 4b'0000 --> rssi_level = 0
1539 	 * if 50% <= rssi < 60%    --> map = 4b'0001 --> rssi_level = 1
1540 	 * if 40% <= rssi < 50%    --> map = 4b'0011 --> rssi_level = 2
1541 	 * if 30% <= rssi < 40%    --> map = 4b'0111 --> rssi_level = 3
1542 	 * if rssi < 20%           --> map = 4b'1111 --> rssi_level = 4
1543 	 */
1544 
1545 	dm->cnt_notify[BTC_NCNT_WL_STA]++;
1546 
1547 	for (i = 0; i < ntfy_num; i++) {
1548 		w = &stat_info[i];
1549 		t = &w->stat.traffic;
1550 
1551 		link_info = &wl->link_info[w->pid];
1552 		link_info_t = &link_info->stat.traffic;
1553 
1554 		if (link_info->connected == MLME_NO_LINK) {
1555 			link_info->rx_rate_drop_cnt = 0;
1556 			rssi_map_all |= rssi_map;
1557 			continue;
1558 		}
1559 
1560 		last_tx_rate = link_info_t->tx_rate;
1561 		last_rx_rate = link_info_t->rx_rate;
1562 		last_tx_lvl = (u16)link_info_t->tx_lvl;
1563 		last_rx_lvl = (u16)link_info_t->rx_lvl;
1564 
1565 		/* refresh link_info traffic/rssi related info from t */
1566 		hal_mem_cpy(h, (void *)link_info_t, (void *)t,
1567 			    sizeof(struct btc_traffic));
1568 
1569 		link_info->stat.rssi = w->stat.rssi;
1570 		rssi_map = 0;
1571 
1572 		/* check if rssi across wl_rssi_thres boundary */
1573 		for (j = 0; j < BTC_WL_RSSI_THMAX; j++) {
1574 			if (module->ant.type == BTC_ANT_SHARED && j == 0)
1575 				rssi_thres = BTC_WL_RSSI_MAX_BTG;
1576 			else
1577 				rssi_thres = btc->chip->wl_rssi_thres[j];
1578 
1579 			rssi_state = &link_info->rssi_state[j];
1580 			*rssi_state = _update_rssi_state(btc, *rssi_state,
1581 							link_info->stat.rssi,
1582 							rssi_thres);
1583 
1584 			/* fill rssi bit map 0~3 if rssi < threshold  */
1585 			if (BTC_RSSI_LOW(*rssi_state))
1586 				rssi_map |= BIT(j);
1587 
1588 			if (module->ant.type == BTC_ANT_DEDICATED &&
1589 			    BTC_RSSI_CHANGE(*rssi_state))
1590 				is_sta_change = true;
1591 		}
1592 
1593 		/* OR STA/GC role rssi map */
1594 		if (link_info->role == PHL_RTYPE_STATION ||
1595 		    link_info->role == PHL_RTYPE_P2P_GC)
1596 			rssi_map_all |= rssi_map;
1597 
1598 		/* set busy once idle->busy immediately */
1599 		if (t->tx_lvl != RTW_TFC_IDLE || t->rx_lvl != RTW_TFC_IDLE) {
1600 			busy = 1;
1601 			link_info->busy_t = _os_get_cur_time_ms();
1602 
1603 			if (t->tx_lvl > t->rx_lvl)
1604 				dir = TRAFFIC_UL;
1605 			else
1606 				dir = TRAFFIC_DL;
1607 		} else {/*set idle if busy -> idle after BTC_BUSY2IDLE_THRES*/
1608 			if (phl_get_passing_time_ms(link_info->busy_t) >
1609 			    BTC_BUSY2IDLE_THRES ||
1610 			    !wl->role_info.role_map.role.station ||
1611 			    wl->role_info.link_mode == BTC_WLINK_NOLINK) {
1612 				busy = 0;
1613 				dir = TRAFFIC_DL;
1614 			} else {
1615 				busy = link_info->busy;
1616 				dir = link_info->dir;
1617 			}
1618 		}
1619 
1620 		if (link_info->busy != busy || link_info->dir != dir) {
1621 			is_sta_change = true;
1622 			link_info->busy = busy;
1623 			link_info->dir = dir;
1624 		}
1625 
1626 		/* OR all role busy/dir state */
1627 		busy_all |= link_info->busy;
1628 		dir_all |= BIT(link_info->dir);
1629 
1630 		if (link_info_t->rx_rate <= RTW_DATA_RATE_CCK2 &&
1631 		    last_rx_rate > RTW_DATA_RATE_CCK2 &&
1632 		    link_info_t->rx_lvl > 0)
1633 			link_info->rx_rate_drop_cnt++;
1634 
1635 		if (last_tx_rate != link_info_t->tx_rate ||
1636 		    last_rx_rate != link_info_t->rx_rate ||
1637 		    last_tx_lvl != link_info_t->tx_lvl ||
1638 		    last_rx_lvl != link_info_t->rx_lvl )
1639 			is_traffic_change = true;
1640 
1641 		wl->role_info.active_role[w->pid].tx_lvl = (u16)t->tx_lvl;
1642 		wl->role_info.active_role[w->pid].rx_lvl = (u16)t->rx_lvl;
1643 		wl->role_info.active_role[w->pid].tx_rate = t->tx_rate;
1644 		wl->role_info.active_role[w->pid].rx_rate = t->rx_rate;
1645 	}
1646 
1647 	wl->rssi_level = 0;
1648 	for (j = BTC_WL_RSSI_THMAX; j > 0; j--) {
1649 		/* set RSSI level 4 ~ 0 if rssi bit map match */
1650 		if (rssi_map_all & BIT(j-1)) {
1651 			wl->rssi_level = j;
1652 			break;
1653 		}
1654 	}
1655 
1656 	chk_intvl = BTC_RPT_PERIOD/BTC_PERIODIC_TIME;
1657 
1658 	if (dm->cnt_notify[BTC_NCNT_WL_STA] >=
1659 	    dm->cnt_dm[BTC_DCNT_WL_STA_LAST] + chk_intvl)
1660 		_get_wl_nhm_dbm(btc);
1661 
1662 	dm->cnt_dm[BTC_DCNT_WL_STA_LAST] = dm->cnt_notify[BTC_NCNT_WL_STA];
1663 
1664 	/* for TDD/FDD packet estimation in WL FW */
1665 	if (is_traffic_change)
1666 		hal_btc_fw_set_drv_info(btc, CXDRVINFO_ROLE);
1667 
1668 	if (is_sta_change) {
1669 		wl->status.map.busy = (u32)busy_all;
1670 		wl->status.map.traffic_dir = (u32)dir_all;
1671 		_write_scbd(btc, BTC_WSCB_WLBUSY, (bool)(!!busy_all));
1672 		_run_coex(btc, __func__);
1673 	}
1674 }
1675 
_ntfy_fwinfo(struct btc_t * btc,u8 * buf,u32 len,u8 cls,u8 func)1676 static void _ntfy_fwinfo(struct btc_t *btc, u8 *buf, u32 len, u8 cls, u8 func)
1677 {
1678 	struct btf_fwinfo *pfwinfo = &btc->fwinfo;
1679 
1680 	if (!buf || !len)
1681 		return;
1682 
1683 	btc->dm.cnt_notify[BTC_NCNT_FWINFO]++;
1684 	pfwinfo->cnt_c2h++;
1685 
1686 	if (cls == BTFC_FW_EVENT) {
1687 		switch (func) {
1688 		case BTF_EVNT_RPT:
1689 		case BTF_EVNT_BUF_OVERFLOW:
1690 			pfwinfo->event[func]++;
1691 			hal_btc_fw_event(btc, func, buf, len);
1692 			break;
1693 		case BTF_EVNT_BT_INFO:
1694 			btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
1695 			_update_bt_info(btc, buf, len);
1696 			break;
1697 		case BTF_EVNT_BT_SCBD:
1698 			btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
1699 			_update_bt_scbd(btc, false);
1700 			break;
1701 		case BTF_EVNT_BT_PSD:
1702 			_update_bt_psd(btc, buf, len);
1703 			break;
1704 		case BTF_EVNT_BT_REG:
1705 			btc->dbg.rb_done = true;
1706 			btc->dbg.rb_val = ((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]));
1707 			break;
1708 		case BTF_EVNT_C2H_LOOPBACK:
1709 			btc->dbg.rb_done = true;
1710 			btc->dbg.rb_val = buf[0];
1711 			break;
1712 		case BTF_EVNT_CX_RUNINFO:
1713 			btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
1714 			_update_offload_runinfo(btc, buf, len);
1715 			break;
1716 		}
1717 	}
1718 }
1719 
_ntfy_timer(struct btc_t * btc,u16 tmr_id)1720 static void _ntfy_timer(struct btc_t *btc, u16 tmr_id)
1721 {
1722 	struct btc_dm *dm = &btc->dm;
1723 	struct btc_cx *cx = &btc->cx;
1724 	struct btc_wl_info *wl = &cx->wl;
1725 	struct btc_bt_a2dp_desc *a2dp = &cx->bt.link_info.a2dp_desc;
1726 	bool is_sta_change = false;
1727 
1728 	PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_,
1729 		  "[BTC], %s(): tmr_id =%d\n", __func__, tmr_id);
1730 
1731 	dm->cnt_notify[BTC_NCNT_TIMER]++;
1732 
1733 	if (tmr_id == BTC_TIMER_PERIODIC) {
1734 		/* start next periodic timer */
1735 		_set_btc_timer(btc, BTC_TIMER_PERIODIC, BTC_PERIODIC_TIME);
1736 	} else if (tmr_id == BTC_TIMER_WL_RFKTO) {
1737 		if (wl->rfk_info.state != BTC_WRFK_STOP) {
1738 			cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
1739 			dm->error.map.wl_rfk_timeout = true;
1740 			wl->rfk_info.state = BTC_WRFK_STOP;
1741 			/* _write_scbd(btc, BTC_WSCB_WLRFK, false); */
1742 			is_sta_change = true;
1743 		}
1744 	} else if (tmr_id == BTC_TIMER_WL_SPECPKT) {
1745 		wl->status.map._4way = false;
1746 		wl->status.map.connecting = 0;
1747 		is_sta_change = true;
1748 	} else if (tmr_id == BTC_TIMER_BT_A2DPPLAY) {
1749 		a2dp->play_latency = 0;
1750 		is_sta_change = true;
1751 	}
1752 
1753 	if (is_sta_change)
1754 		_run_coex(btc, __func__);
1755 }
1756 
1757 /******************************************************************************
1758  *
1759  * coexistence extern functions
1760  *
1761  *****************************************************************************/
1762 /*
1763  * btc related sw initialization
1764  */
hal_btc_init(struct btc_t * btc)1765 bool hal_btc_init(struct btc_t *btc)
1766 {
1767 	switch (btc->hal->chip_id) {
1768 #ifdef BTC_8852A_SUPPORT
1769 	case CHIP_WIFI6_8852A:
1770 		PHL_INFO("[BTC], %s(): Init 8852A!!\n", __func__);
1771 		btc->chip = &chip_8852a;
1772 		break;
1773 #endif
1774 #ifdef BTC_8852B_SUPPORT
1775 	case CHIP_WIFI6_8852B:
1776 		PHL_INFO("[BTC], %s(): Init 8852B!!\n", __func__);
1777 		btc->chip = &chip_8852b;
1778 		break;
1779 #endif
1780 #ifdef BTC_8852C_SUPPORT
1781 	case CHIP_WIFI6_8852C:
1782 		PHL_INFO("[BTC], %s(): Init 8852C!!\n", __func__);
1783 		btc->chip = &chip_8852c;
1784 		break;
1785 #endif
1786 	default:
1787 		PHL_ERR("[BTC], %s(): no matched IC!!\n", __func__);
1788 		btc->cx.wl.status.map.init_ok = false;
1789 		return false;
1790 	}
1791 
1792 	_reset_btc_var(btc, BTC_RESET_ALL);
1793 	_btmr_init(btc);
1794 
1795 	_rsn_cpy(btc->dm.run_reason, "None");
1796 	_act_cpy(btc->dm.run_action, "None");
1797 
1798 	btc->hal->btc_vc.btc_ver = coex_ver;
1799 	btc->ops = &_btc_ops;
1800 	btc->mlen = BTC_MSG_MAXLEN;
1801 	btc->ctrl.igno_bt = true;
1802 	btc->cx.wl.status.map.init_ok = true;
1803 
1804 	return true;
1805 }
1806 
hal_btc_deinit(struct btc_t * btc)1807 void hal_btc_deinit(struct btc_t *btc)
1808 {
1809 	_btmr_deinit(btc);
1810 }
1811 
1812 #endif
1813 
1814