• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019  Realtek Corporation
3  */
4 
5 #include "main.h"
6 #include "coex.h"
7 #include "fw.h"
8 #include "ps.h"
9 #include "debug.h"
10 #include "reg.h"
11 
rtw_coex_next_rssi_state(struct rtw_dev * rtwdev,u8 pre_state,u8 rssi,u8 rssi_thresh)12 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
13 				   u8 rssi, u8 rssi_thresh)
14 {
15 	struct rtw_chip_info *chip = rtwdev->chip;
16 	u8 tol = chip->rssi_tolerance;
17 	u8 next_state;
18 
19 	if (pre_state == COEX_RSSI_STATE_LOW ||
20 	    pre_state == COEX_RSSI_STATE_STAY_LOW) {
21 		if (rssi >= (rssi_thresh + tol))
22 			next_state = COEX_RSSI_STATE_HIGH;
23 		else
24 			next_state = COEX_RSSI_STATE_STAY_LOW;
25 	} else {
26 		if (rssi < rssi_thresh)
27 			next_state = COEX_RSSI_STATE_LOW;
28 		else
29 			next_state = COEX_RSSI_STATE_STAY_HIGH;
30 	}
31 
32 	return next_state;
33 }
34 
rtw_coex_limited_tx(struct rtw_dev * rtwdev,bool tx_limit_en,bool ampdu_limit_en)35 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
36 				bool tx_limit_en, bool ampdu_limit_en)
37 {
38 	struct rtw_chip_info *chip = rtwdev->chip;
39 	struct rtw_coex *coex = &rtwdev->coex;
40 	struct rtw_coex_stat *coex_stat = &coex->stat;
41 	bool wifi_under_b_mode = false;
42 
43 	if (!chip->scbd_support)
44 		return;
45 
46 	/* force max tx retry limit = 8 */
47 	if (coex_stat->wl_tx_limit_en == tx_limit_en &&
48 	    coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
49 		return;
50 
51 	if (!coex_stat->wl_tx_limit_en) {
52 		coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
53 		coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
54 		coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
55 	}
56 
57 	if (!coex_stat->wl_ampdu_limit_en)
58 		coex_stat->ampdu_max_time =
59 				rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
60 
61 	coex_stat->wl_tx_limit_en = tx_limit_en;
62 	coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
63 
64 	if (tx_limit_en) {
65 		/* set BT polluted packet on for tx rate adaptive,
66 		 * not including tx retry broken by PTA
67 		 */
68 		rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
69 
70 		/* set queue life time to avoid can't reach tx retry limit
71 		 * if tx is always broken by GNT_BT
72 		 */
73 		rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
74 		rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
75 
76 		/* auto rate fallback step within 8 retries */
77 		if (wifi_under_b_mode) {
78 			rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
79 			rtw_write32(rtwdev, REG_DARFRCH, 0x1010101);
80 		} else {
81 			rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
82 			rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
83 		}
84 	} else {
85 		rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
86 		rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
87 
88 		rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
89 		rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
90 		rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
91 	}
92 
93 	if (ampdu_limit_en)
94 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
95 	else
96 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
97 			   coex_stat->ampdu_max_time);
98 }
99 
rtw_coex_limited_wl(struct rtw_dev * rtwdev)100 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
101 {
102 	struct rtw_coex *coex = &rtwdev->coex;
103 	struct rtw_coex_dm *coex_dm = &coex->dm;
104 	struct rtw_coex_stat *coex_stat = &coex->stat;
105 	bool tx_limit = false;
106 	bool tx_agg_ctrl = false;
107 
108 	if (coex->under_5g ||
109 	    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
110 		/* no need to limit tx */
111 	} else {
112 		tx_limit = true;
113 		if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist ||
114 		    coex_stat->bt_hid_pair_num > 0)
115 			tx_agg_ctrl = true;
116 	}
117 
118 	rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
119 }
120 
rtw_coex_wl_ccklock_action(struct rtw_dev * rtwdev)121 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
122 {
123 	struct rtw_coex *coex = &rtwdev->coex;
124 	struct rtw_coex_stat *coex_stat = &coex->stat;
125 	u8 para[6] = {0};
126 
127 	if (coex->stop_dm)
128 		return;
129 
130 	para[0] = COEX_H2C69_WL_LEAKAP;
131 
132 	if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
133 		para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */
134 		rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
135 		coex_stat->wl_slot_extend = false;
136 		coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
137 		return;
138 	}
139 
140 	if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
141 	    !coex_stat->wl_cck_lock_ever) {
142 		if (coex_stat->wl_fw_dbg_info[7] <= 5)
143 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
144 		else
145 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
146 
147 		if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
148 			para[1] = 0x1; /* disable 5ms extend */
149 			rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
150 			coex_stat->wl_slot_extend = false;
151 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
152 		}
153 	} else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
154 		para[1] = 0x0; /* enable 5ms extend */
155 		rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
156 		coex_stat->wl_slot_extend = true;
157 	}
158 }
159 
rtw_coex_wl_ccklock_detect(struct rtw_dev * rtwdev)160 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
161 {
162 	struct rtw_coex *coex = &rtwdev->coex;
163 	struct rtw_coex_stat *coex_stat = &coex->stat;
164 
165 	/* TODO: wait for rx_rate_change_notify implement */
166 	coex_stat->wl_cck_lock = false;
167 	coex_stat->wl_cck_lock_pre = false;
168 	coex_stat->wl_cck_lock_ever = false;
169 }
170 
rtw_coex_wl_noisy_detect(struct rtw_dev * rtwdev)171 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
172 {
173 	struct rtw_coex *coex = &rtwdev->coex;
174 	struct rtw_coex_stat *coex_stat = &coex->stat;
175 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
176 	u32 cnt_cck;
177 
178 	/* wifi noisy environment identification */
179 	cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
180 
181 	if (!coex_stat->wl_gl_busy) {
182 		if (cnt_cck > 250) {
183 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
184 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
185 
186 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
187 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
188 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
189 			}
190 		} else if (cnt_cck < 100) {
191 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
192 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
193 
194 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
195 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
196 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
197 			}
198 		} else {
199 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
200 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
201 
202 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
203 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
204 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
205 			}
206 		}
207 
208 		if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
209 			coex_stat->wl_noisy_level = 2;
210 		else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
211 			coex_stat->wl_noisy_level = 1;
212 		else
213 			coex_stat->wl_noisy_level = 0;
214 	}
215 }
216 
rtw_coex_tdma_timer_base(struct rtw_dev * rtwdev,u8 type)217 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
218 {
219 	struct rtw_coex *coex = &rtwdev->coex;
220 	struct rtw_coex_stat *coex_stat = &coex->stat;
221 	u8 para[2] = {0};
222 
223 	if (coex_stat->tdma_timer_base == type)
224 		return;
225 
226 	coex_stat->tdma_timer_base = type;
227 
228 	para[0] = COEX_H2C69_TDMA_SLOT;
229 
230 	if (type == 3) /* 4-slot  */
231 		para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
232 	else /* 2-slot  */
233 		para[1] = PARA1_H2C69_TDMA_2SLOT;
234 
235 	rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
236 
237 	/* no 5ms_wl_slot_extend for 4-slot mode  */
238 	if (coex_stat->tdma_timer_base == 3)
239 		rtw_coex_wl_ccklock_action(rtwdev);
240 }
241 
rtw_coex_set_wl_pri_mask(struct rtw_dev * rtwdev,u8 bitmap,u8 data)242 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
243 				     u8 data)
244 {
245 	u32 addr;
246 
247 	addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
248 	bitmap = bitmap % 8;
249 
250 	rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
251 }
252 
rtw_coex_write_scbd(struct rtw_dev * rtwdev,u16 bitpos,bool set)253 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
254 {
255 	struct rtw_chip_info *chip = rtwdev->chip;
256 	struct rtw_coex *coex = &rtwdev->coex;
257 	struct rtw_coex_stat *coex_stat = &coex->stat;
258 	u16 val = 0x2;
259 
260 	if (!chip->scbd_support)
261 		return;
262 
263 	val |= coex_stat->score_board;
264 
265 	/* for 8822b, scbd[10] is CQDDR on
266 	 * for 8822c, scbd[10] is no fix 2M
267 	 */
268 	if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
269 		if (set)
270 			val &= ~COEX_SCBD_FIX2M;
271 		else
272 			val |= COEX_SCBD_FIX2M;
273 	} else {
274 		if (set)
275 			val |= bitpos;
276 		else
277 			val &= ~bitpos;
278 	}
279 
280 	if (val != coex_stat->score_board) {
281 		coex_stat->score_board = val;
282 		val |= BIT_BT_INT_EN;
283 		rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
284 	}
285 }
286 EXPORT_SYMBOL(rtw_coex_write_scbd);
287 
rtw_coex_read_scbd(struct rtw_dev * rtwdev)288 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
289 {
290 	struct rtw_chip_info *chip = rtwdev->chip;
291 
292 	if (!chip->scbd_support)
293 		return 0;
294 
295 	return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
296 }
297 
rtw_coex_check_rfk(struct rtw_dev * rtwdev)298 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
299 {
300 	struct rtw_chip_info *chip = rtwdev->chip;
301 	struct rtw_coex *coex = &rtwdev->coex;
302 	struct rtw_coex_stat *coex_stat = &coex->stat;
303 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
304 	u8 cnt = 0;
305 	u32 wait_cnt;
306 	bool btk, wlk;
307 
308 	if (coex_rfe->wlg_at_btg && chip->scbd_support &&
309 	    coex_stat->bt_iqk_state != 0xff) {
310 		wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
311 		do {
312 			/* BT RFK */
313 			btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
314 
315 			/* WL RFK */
316 			wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
317 
318 			if (!btk && !wlk)
319 				break;
320 
321 			mdelay(COEX_MIN_DELAY);
322 		} while (++cnt < wait_cnt);
323 
324 		if (cnt >= wait_cnt)
325 			coex_stat->bt_iqk_state = 0xff;
326 	}
327 }
328 
rtw_coex_query_bt_info(struct rtw_dev * rtwdev)329 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
330 {
331 	struct rtw_coex *coex = &rtwdev->coex;
332 	struct rtw_coex_stat *coex_stat = &coex->stat;
333 
334 	if (coex_stat->bt_disabled)
335 		return;
336 
337 	rtw_fw_query_bt_info(rtwdev);
338 }
339 
rtw_coex_monitor_bt_enable(struct rtw_dev * rtwdev)340 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
341 {
342 	struct rtw_chip_info *chip = rtwdev->chip;
343 	struct rtw_coex *coex = &rtwdev->coex;
344 	struct rtw_coex_stat *coex_stat = &coex->stat;
345 	struct rtw_coex_dm *coex_dm = &coex->dm;
346 	bool bt_disabled = false;
347 	u16 score_board;
348 
349 	if (chip->scbd_support) {
350 		score_board = rtw_coex_read_scbd(rtwdev);
351 		bt_disabled = !(score_board & COEX_SCBD_ONOFF);
352 	}
353 
354 	if (coex_stat->bt_disabled != bt_disabled) {
355 		rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n",
356 			coex_stat->bt_disabled, bt_disabled);
357 
358 		coex_stat->bt_disabled = bt_disabled;
359 		coex_stat->bt_ble_scan_type = 0;
360 		coex_dm->cur_bt_lna_lvl = 0;
361 	}
362 
363 	if (!coex_stat->bt_disabled) {
364 		coex_stat->bt_reenable = true;
365 		ieee80211_queue_delayed_work(rtwdev->hw,
366 					     &coex->bt_reenable_work, 15 * HZ);
367 	} else {
368 		coex_stat->bt_mailbox_reply = false;
369 		coex_stat->bt_reenable = false;
370 	}
371 }
372 
rtw_coex_update_wl_link_info(struct rtw_dev * rtwdev,u8 reason)373 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
374 {
375 	struct rtw_coex *coex = &rtwdev->coex;
376 	struct rtw_coex_stat *coex_stat = &coex->stat;
377 	struct rtw_coex_dm *coex_dm = &coex->dm;
378 	struct rtw_chip_info *chip = rtwdev->chip;
379 	struct rtw_traffic_stats *stats = &rtwdev->stats;
380 	bool is_5G = false;
381 	bool wl_busy = false;
382 	bool scan = false, link = false;
383 	int i;
384 	u8 rssi_state;
385 	u8 rssi_step;
386 	u8 rssi;
387 
388 	scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
389 	coex_stat->wl_connected = !!rtwdev->sta_cnt;
390 
391 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
392 	if (wl_busy != coex_stat->wl_gl_busy) {
393 		if (wl_busy)
394 			coex_stat->wl_gl_busy = true;
395 		else
396 			ieee80211_queue_delayed_work(rtwdev->hw,
397 						     &coex->wl_remain_work,
398 						     12 * HZ);
399 	}
400 
401 	if (stats->tx_throughput > stats->rx_throughput)
402 		coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
403 	else
404 		coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
405 
406 	if (scan || link || reason == COEX_RSN_2GCONSTART ||
407 	    reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
408 		coex_stat->wl_linkscan_proc = true;
409 	else
410 		coex_stat->wl_linkscan_proc = false;
411 
412 	rtw_coex_wl_noisy_detect(rtwdev);
413 
414 	for (i = 0; i < 4; i++) {
415 		rssi_state = coex_dm->wl_rssi_state[i];
416 		rssi_step = chip->wl_rssi_step[i];
417 		rssi = rtwdev->dm_info.min_rssi;
418 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
419 						      rssi, rssi_step);
420 		coex_dm->wl_rssi_state[i] = rssi_state;
421 	}
422 
423 	switch (reason) {
424 	case COEX_RSN_5GSCANSTART:
425 	case COEX_RSN_5GSWITCHBAND:
426 	case COEX_RSN_5GCONSTART:
427 
428 		is_5G = true;
429 		break;
430 	case COEX_RSN_2GSCANSTART:
431 	case COEX_RSN_2GSWITCHBAND:
432 	case COEX_RSN_2GCONSTART:
433 
434 		is_5G = false;
435 		break;
436 	default:
437 		if (rtwdev->hal.current_band_type == RTW_BAND_5G)
438 			is_5G = true;
439 		else
440 			is_5G = false;
441 		break;
442 	}
443 
444 	coex->under_5g = is_5G;
445 }
446 
get_payload_from_coex_resp(struct sk_buff * resp)447 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
448 {
449 	struct rtw_c2h_cmd *c2h;
450 	u32 pkt_offset;
451 
452 	pkt_offset = *((u32 *)resp->cb);
453 	c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
454 
455 	return c2h->payload;
456 }
457 
rtw_coex_info_response(struct rtw_dev * rtwdev,struct sk_buff * skb)458 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
459 {
460 	struct rtw_coex *coex = &rtwdev->coex;
461 	u8 *payload = get_payload_from_coex_resp(skb);
462 
463 	if (payload[0] != COEX_RESP_ACK_BY_WL_FW)
464 		return;
465 
466 	skb_queue_tail(&coex->queue, skb);
467 	wake_up(&coex->wait);
468 }
469 
rtw_coex_info_request(struct rtw_dev * rtwdev,struct rtw_coex_info_req * req)470 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
471 					     struct rtw_coex_info_req *req)
472 {
473 	struct rtw_coex *coex = &rtwdev->coex;
474 	struct sk_buff *skb_resp = NULL;
475 
476 	mutex_lock(&coex->mutex);
477 
478 	rtw_fw_query_bt_mp_info(rtwdev, req);
479 
480 	if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
481 				COEX_REQUEST_TIMEOUT)) {
482 		rtw_err(rtwdev, "coex request time out\n");
483 		goto out;
484 	}
485 
486 	skb_resp = skb_dequeue(&coex->queue);
487 	if (!skb_resp) {
488 		rtw_err(rtwdev, "failed to get coex info response\n");
489 		goto out;
490 	}
491 
492 out:
493 	mutex_unlock(&coex->mutex);
494 	return skb_resp;
495 }
496 
rtw_coex_get_bt_scan_type(struct rtw_dev * rtwdev,u8 * scan_type)497 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
498 {
499 	struct rtw_coex_info_req req = {0};
500 	struct sk_buff *skb;
501 	u8 *payload;
502 	bool ret = false;
503 
504 	req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
505 	skb = rtw_coex_info_request(rtwdev, &req);
506 	if (!skb)
507 		goto out;
508 
509 	payload = get_payload_from_coex_resp(skb);
510 	*scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
511 	dev_kfree_skb_any(skb);
512 	ret = true;
513 
514 out:
515 	return ret;
516 }
517 
rtw_coex_set_lna_constrain_level(struct rtw_dev * rtwdev,u8 lna_constrain_level)518 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
519 					     u8 lna_constrain_level)
520 {
521 	struct rtw_coex_info_req req = {0};
522 	struct sk_buff *skb;
523 	bool ret = false;
524 
525 	req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
526 	req.para1 = lna_constrain_level;
527 	skb = rtw_coex_info_request(rtwdev, &req);
528 	if (!skb)
529 		goto out;
530 
531 	dev_kfree_skb_any(skb);
532 	ret = true;
533 
534 out:
535 	return ret;
536 }
537 
rtw_coex_update_bt_link_info(struct rtw_dev * rtwdev)538 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
539 {
540 	struct rtw_coex *coex = &rtwdev->coex;
541 	struct rtw_coex_stat *coex_stat = &coex->stat;
542 	struct rtw_coex_dm *coex_dm = &coex->dm;
543 	struct rtw_chip_info *chip = rtwdev->chip;
544 	u8 i;
545 	u8 rssi_state;
546 	u8 rssi_step;
547 	u8 rssi;
548 
549 	/* update wl/bt rssi by btinfo */
550 	for (i = 0; i < COEX_RSSI_STEP; i++) {
551 		rssi_state = coex_dm->bt_rssi_state[i];
552 		rssi_step = chip->bt_rssi_step[i];
553 		rssi = coex_stat->bt_rssi;
554 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
555 						      rssi, rssi_step);
556 		coex_dm->bt_rssi_state[i] = rssi_state;
557 	}
558 
559 	for (i = 0; i < COEX_RSSI_STEP; i++) {
560 		rssi_state = coex_dm->wl_rssi_state[i];
561 		rssi_step = chip->wl_rssi_step[i];
562 		rssi = rtwdev->dm_info.min_rssi;
563 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
564 						      rssi, rssi_step);
565 		coex_dm->wl_rssi_state[i] = rssi_state;
566 	}
567 
568 	if (coex_stat->bt_ble_scan_en &&
569 	    coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
570 		u8 scan_type;
571 
572 		if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
573 			coex_stat->bt_ble_scan_type = scan_type;
574 			if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
575 				coex_stat->bt_init_scan = true;
576 			else
577 				coex_stat->bt_init_scan = false;
578 		}
579 	}
580 
581 	coex_stat->bt_profile_num = 0;
582 
583 	/* set link exist status */
584 	if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
585 		coex_stat->bt_link_exist = false;
586 		coex_stat->bt_pan_exist = false;
587 		coex_stat->bt_a2dp_exist = false;
588 		coex_stat->bt_hid_exist = false;
589 		coex_stat->bt_hfp_exist = false;
590 	} else {
591 		/* connection exists */
592 		coex_stat->bt_link_exist = true;
593 		if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
594 			coex_stat->bt_pan_exist = true;
595 			coex_stat->bt_profile_num++;
596 		} else {
597 			coex_stat->bt_pan_exist = false;
598 		}
599 
600 		if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
601 			coex_stat->bt_a2dp_exist = true;
602 			coex_stat->bt_profile_num++;
603 		} else {
604 			coex_stat->bt_a2dp_exist = false;
605 		}
606 
607 		if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
608 			coex_stat->bt_hid_exist = true;
609 			coex_stat->bt_profile_num++;
610 		} else {
611 			coex_stat->bt_hid_exist = false;
612 		}
613 
614 		if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
615 			coex_stat->bt_hfp_exist = true;
616 			coex_stat->bt_profile_num++;
617 		} else {
618 			coex_stat->bt_hfp_exist = false;
619 		}
620 	}
621 
622 	if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
623 		coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
624 	} else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
625 		coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
626 	} else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
627 		coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
628 	} else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
629 		   (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
630 		if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
631 			coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
632 		else
633 			coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
634 	} else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
635 		coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
636 	} else {
637 		coex_dm->bt_status = COEX_BTSTATUS_MAX;
638 	}
639 
640 	coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
641 
642 	rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status);
643 }
644 
rtw_coex_update_wl_ch_info(struct rtw_dev * rtwdev,u8 type)645 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
646 {
647 	struct rtw_chip_info *chip = rtwdev->chip;
648 	struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
649 	struct rtw_efuse *efuse = &rtwdev->efuse;
650 	u8 link = 0;
651 	u8 center_chan = 0;
652 	u8 bw;
653 	int i;
654 
655 	bw = rtwdev->hal.current_band_width;
656 
657 	if (type != COEX_MEDIA_DISCONNECT)
658 		center_chan = rtwdev->hal.current_channel;
659 
660 	if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) {
661 		link = 0;
662 	} else if (center_chan <= 14) {
663 		link = 0x1;
664 
665 		if (bw == RTW_CHANNEL_WIDTH_40)
666 			bw = chip->bt_afh_span_bw40;
667 		else
668 			bw = chip->bt_afh_span_bw20;
669 	} else if (chip->afh_5g_num > 1) {
670 		for (i = 0; i < chip->afh_5g_num; i++) {
671 			if (center_chan == chip->afh_5g[i].wl_5g_ch) {
672 				link = 0x3;
673 				center_chan = chip->afh_5g[i].bt_skip_ch;
674 				bw = chip->afh_5g[i].bt_skip_span;
675 				break;
676 			}
677 		}
678 	}
679 
680 	coex_dm->wl_ch_info[0] = link;
681 	coex_dm->wl_ch_info[1] = center_chan;
682 	coex_dm->wl_ch_info[2] = bw;
683 
684 	rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
685 }
686 
rtw_coex_set_bt_tx_power(struct rtw_dev * rtwdev,u8 bt_pwr_dec_lvl)687 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
688 {
689 	struct rtw_coex *coex = &rtwdev->coex;
690 	struct rtw_coex_dm *coex_dm = &coex->dm;
691 
692 	if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
693 		return;
694 
695 	coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
696 
697 	rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
698 }
699 
rtw_coex_set_bt_rx_gain(struct rtw_dev * rtwdev,u8 bt_lna_lvl)700 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
701 {
702 	struct rtw_coex *coex = &rtwdev->coex;
703 	struct rtw_coex_dm *coex_dm = &coex->dm;
704 
705 	if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
706 		return;
707 
708 	coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
709 
710 	/* notify BT rx gain table changed */
711 	if (bt_lna_lvl < 7) {
712 		rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
713 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
714 	} else {
715 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
716 	}
717 }
718 
rtw_coex_set_rf_para(struct rtw_dev * rtwdev,struct coex_rf_para para)719 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
720 				 struct coex_rf_para para)
721 {
722 	struct rtw_coex *coex = &rtwdev->coex;
723 	struct rtw_coex_stat *coex_stat = &coex->stat;
724 	u8 offset = 0;
725 
726 	if (coex->freerun && coex_stat->wl_noisy_level <= 1)
727 		offset = 3;
728 
729 	rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
730 	rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
731 	rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
732 	rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
733 }
734 
rtw_coex_read_indirect_reg(struct rtw_dev * rtwdev,u16 addr)735 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
736 {
737 	u32 val;
738 
739 	if (!ltecoex_read_reg(rtwdev, addr, &val)) {
740 		rtw_err(rtwdev, "failed to read indirect register\n");
741 		return 0;
742 	}
743 
744 	return val;
745 }
746 EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
747 
rtw_coex_write_indirect_reg(struct rtw_dev * rtwdev,u16 addr,u32 mask,u32 val)748 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
749 				 u32 mask, u32 val)
750 {
751 	u32 shift = __ffs(mask);
752 	u32 tmp;
753 
754 	tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
755 	tmp = (tmp & (~mask)) | ((val << shift) & mask);
756 
757 	if (!ltecoex_reg_write(rtwdev, addr, tmp))
758 		rtw_err(rtwdev, "failed to write indirect register\n");
759 }
760 EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
761 
rtw_coex_coex_ctrl_owner(struct rtw_dev * rtwdev,bool wifi_control)762 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
763 {
764 	struct rtw_chip_info *chip = rtwdev->chip;
765 	const struct rtw_hw_reg *btg_reg = chip->btg_reg;
766 
767 	if (wifi_control) {
768 		rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
769 		if (btg_reg)
770 			rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
771 	} else {
772 		rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
773 		if (btg_reg)
774 			rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
775 	}
776 }
777 
rtw_coex_set_gnt_bt(struct rtw_dev * rtwdev,u8 state)778 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
779 {
780 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state);
781 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state);
782 }
783 
rtw_coex_set_gnt_wl(struct rtw_dev * rtwdev,u8 state)784 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
785 {
786 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state);
787 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state);
788 }
789 
rtw_coex_set_table(struct rtw_dev * rtwdev,u32 table0,u32 table1)790 static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1)
791 {
792 #define DEF_BRK_TABLE_VAL	0xf0ffffff
793 	rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
794 	rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
795 	rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
796 }
797 
rtw_coex_table(struct rtw_dev * rtwdev,u8 type)798 static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type)
799 {
800 	struct rtw_coex *coex = &rtwdev->coex;
801 	struct rtw_coex_dm *coex_dm = &coex->dm;
802 	struct rtw_chip_info *chip = rtwdev->chip;
803 	struct rtw_efuse *efuse = &rtwdev->efuse;
804 
805 	coex_dm->cur_table = type;
806 
807 	if (efuse->share_ant) {
808 		if (type < chip->table_sant_num)
809 			rtw_coex_set_table(rtwdev,
810 					   chip->table_sant[type].bt,
811 					   chip->table_sant[type].wl);
812 	} else {
813 		type = type - 100;
814 		if (type < chip->table_nsant_num)
815 			rtw_coex_set_table(rtwdev,
816 					   chip->table_nsant[type].bt,
817 					   chip->table_nsant[type].wl);
818 	}
819 }
820 
rtw_coex_ignore_wlan_act(struct rtw_dev * rtwdev,bool enable)821 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
822 {
823 	struct rtw_coex *coex = &rtwdev->coex;
824 
825 	if (coex->stop_dm)
826 		return;
827 
828 	rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
829 }
830 
rtw_coex_power_save_state(struct rtw_dev * rtwdev,u8 ps_type,u8 lps_val,u8 rpwm_val)831 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
832 				      u8 lps_val, u8 rpwm_val)
833 {
834 	struct rtw_coex *coex = &rtwdev->coex;
835 	struct rtw_coex_stat *coex_stat = &coex->stat;
836 	u8 lps_mode = 0x0;
837 
838 	lps_mode = rtwdev->lps_conf.mode;
839 
840 	switch (ps_type) {
841 	case COEX_PS_WIFI_NATIVE:
842 		/* recover to original 32k low power setting */
843 		coex_stat->wl_force_lps_ctrl = false;
844 
845 		rtw_leave_lps(rtwdev);
846 		break;
847 	case COEX_PS_LPS_OFF:
848 		coex_stat->wl_force_lps_ctrl = true;
849 		if (lps_mode)
850 			rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
851 
852 		rtw_leave_lps(rtwdev);
853 		break;
854 	default:
855 		break;
856 	}
857 }
858 
rtw_coex_set_tdma(struct rtw_dev * rtwdev,u8 byte1,u8 byte2,u8 byte3,u8 byte4,u8 byte5)859 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
860 			      u8 byte3, u8 byte4, u8 byte5)
861 {
862 	struct rtw_coex *coex = &rtwdev->coex;
863 	struct rtw_coex_dm *coex_dm = &coex->dm;
864 	struct rtw_chip_info *chip = rtwdev->chip;
865 	u8 ps_type = COEX_PS_WIFI_NATIVE;
866 	bool ap_enable = false;
867 
868 	if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
869 		byte1 &= ~BIT(4);
870 		byte1 |= BIT(5);
871 
872 		byte5 |= BIT(5);
873 		byte5 &= ~BIT(6);
874 
875 		ps_type = COEX_PS_WIFI_NATIVE;
876 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
877 	} else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
878 		if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
879 			ps_type = COEX_PS_LPS_OFF;
880 		else
881 			ps_type = COEX_PS_LPS_ON;
882 		rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
883 	} else {
884 		ps_type = COEX_PS_WIFI_NATIVE;
885 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
886 	}
887 
888 	coex_dm->ps_tdma_para[0] = byte1;
889 	coex_dm->ps_tdma_para[1] = byte2;
890 	coex_dm->ps_tdma_para[2] = byte3;
891 	coex_dm->ps_tdma_para[3] = byte4;
892 	coex_dm->ps_tdma_para[4] = byte5;
893 
894 	rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
895 }
896 
rtw_coex_tdma(struct rtw_dev * rtwdev,bool force,u32 tcase)897 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
898 {
899 	struct rtw_coex *coex = &rtwdev->coex;
900 	struct rtw_coex_dm *coex_dm = &coex->dm;
901 	struct rtw_coex_stat *coex_stat = &coex->stat;
902 	struct rtw_chip_info *chip = rtwdev->chip;
903 	struct rtw_efuse *efuse = &rtwdev->efuse;
904 	u8 n, type;
905 	bool turn_on;
906 	bool wl_busy = false;
907 
908 	if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
909 		rtw_coex_tdma_timer_base(rtwdev, 3);
910 	else
911 		rtw_coex_tdma_timer_base(rtwdev, 0);
912 
913 	type = (u8)(tcase & 0xff);
914 
915 	turn_on = (type == 0 || type == 100) ? false : true;
916 
917 	if (!force) {
918 		if (turn_on == coex_dm->cur_ps_tdma_on &&
919 		    type == coex_dm->cur_ps_tdma) {
920 			return;
921 		}
922 	}
923 
924 	/* enable TBTT interrupt */
925 	if (turn_on)
926 		rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
927 
928 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
929 
930 	if ((coex_stat->bt_a2dp_exist &&
931 	     (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
932 	    !wl_busy)
933 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
934 	else
935 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
936 
937 	if (efuse->share_ant) {
938 		if (type < chip->tdma_sant_num)
939 			rtw_coex_set_tdma(rtwdev,
940 					  chip->tdma_sant[type].para[0],
941 					  chip->tdma_sant[type].para[1],
942 					  chip->tdma_sant[type].para[2],
943 					  chip->tdma_sant[type].para[3],
944 					  chip->tdma_sant[type].para[4]);
945 	} else {
946 		n = type - 100;
947 		if (n < chip->tdma_nsant_num)
948 			rtw_coex_set_tdma(rtwdev,
949 					  chip->tdma_nsant[n].para[0],
950 					  chip->tdma_nsant[n].para[1],
951 					  chip->tdma_nsant[n].para[2],
952 					  chip->tdma_nsant[n].para[3],
953 					  chip->tdma_nsant[n].para[4]);
954 	}
955 
956 	/* update pre state */
957 	coex_dm->cur_ps_tdma_on = turn_on;
958 	coex_dm->cur_ps_tdma = type;
959 
960 	rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type);
961 }
962 
rtw_coex_set_ant_path(struct rtw_dev * rtwdev,bool force,u8 phase)963 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
964 {
965 	struct rtw_coex *coex = &rtwdev->coex;
966 	struct rtw_coex_stat *coex_stat = &coex->stat;
967 	struct rtw_coex_dm *coex_dm = &coex->dm;
968 	u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
969 	u8 pos_type = COEX_SWITCH_TO_MAX;
970 
971 	if (!force && coex_dm->cur_ant_pos_type == phase)
972 		return;
973 
974 	coex_dm->cur_ant_pos_type = phase;
975 
976 	/* avoid switch coex_ctrl_owner during BT IQK */
977 	rtw_coex_check_rfk(rtwdev);
978 
979 	switch (phase) {
980 	case COEX_SET_ANT_POWERON:
981 		/* set path control owner to BT at power-on */
982 		if (coex_stat->bt_disabled)
983 			rtw_coex_coex_ctrl_owner(rtwdev, true);
984 		else
985 			rtw_coex_coex_ctrl_owner(rtwdev, false);
986 
987 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
988 		pos_type = COEX_SWITCH_TO_BT;
989 		break;
990 	case COEX_SET_ANT_INIT:
991 		if (coex_stat->bt_disabled) {
992 			/* set GNT_BT to SW low */
993 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
994 
995 			/* set GNT_WL to SW high */
996 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
997 		} else {
998 			/* set GNT_BT to SW high */
999 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1000 
1001 			/* set GNT_WL to SW low */
1002 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1003 		}
1004 
1005 		/* set path control owner to wl at initial step */
1006 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1007 
1008 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1009 		pos_type = COEX_SWITCH_TO_BT;
1010 		break;
1011 	case COEX_SET_ANT_WONLY:
1012 		/* set GNT_BT to SW Low */
1013 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1014 
1015 		/* Set GNT_WL to SW high */
1016 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1017 
1018 		/* set path control owner to wl at initial step */
1019 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1020 
1021 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1022 		pos_type = COEX_SWITCH_TO_WLG;
1023 		break;
1024 	case COEX_SET_ANT_WOFF:
1025 		/* set path control owner to BT */
1026 		rtw_coex_coex_ctrl_owner(rtwdev, false);
1027 
1028 		ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1029 		pos_type = COEX_SWITCH_TO_NOCARE;
1030 		break;
1031 	case COEX_SET_ANT_2G:
1032 		/* set GNT_BT to PTA */
1033 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1034 
1035 		/* set GNT_WL to PTA */
1036 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1037 
1038 		/* set path control owner to wl at runtime step */
1039 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1040 
1041 		ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1042 		pos_type = COEX_SWITCH_TO_NOCARE;
1043 		break;
1044 	case COEX_SET_ANT_5G:
1045 		/* set GNT_BT to PTA */
1046 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1047 
1048 		/* set GNT_WL to SW high */
1049 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1050 
1051 		/* set path control owner to wl at runtime step */
1052 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1053 
1054 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1055 		pos_type = COEX_SWITCH_TO_WLA;
1056 		break;
1057 	case COEX_SET_ANT_2G_FREERUN:
1058 		/* set GNT_BT to SW high */
1059 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1060 
1061 		/* Set GNT_WL to SW high */
1062 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1063 
1064 		/* set path control owner to wl at runtime step */
1065 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1066 
1067 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1068 		pos_type = COEX_SWITCH_TO_WLG_BT;
1069 		break;
1070 	case COEX_SET_ANT_2G_WLBT:
1071 		/* set GNT_BT to SW high */
1072 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1073 
1074 		/* Set GNT_WL to SW high */
1075 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1076 
1077 		/* set path control owner to wl at runtime step */
1078 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1079 
1080 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1081 		pos_type = COEX_SWITCH_TO_WLG_BT;
1082 		break;
1083 	default:
1084 		WARN(1, "unknown phase when setting antenna path\n");
1085 		return;
1086 	}
1087 
1088 	if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX)
1089 		rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1090 }
1091 
rtw_coex_algorithm(struct rtw_dev * rtwdev)1092 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1093 {
1094 	struct rtw_coex *coex = &rtwdev->coex;
1095 	struct rtw_coex_stat *coex_stat = &coex->stat;
1096 	u8 algorithm = COEX_ALGO_NOPROFILE;
1097 	u8 profile_map = 0;
1098 
1099 	if (coex_stat->bt_hfp_exist)
1100 		profile_map |= BPM_HFP;
1101 	if (coex_stat->bt_hid_exist)
1102 		profile_map |= BPM_HID;
1103 	if (coex_stat->bt_a2dp_exist)
1104 		profile_map |= BPM_A2DP;
1105 	if (coex_stat->bt_pan_exist)
1106 		profile_map |= BPM_PAN;
1107 
1108 	switch (profile_map) {
1109 	case BPM_HFP:
1110 		algorithm = COEX_ALGO_HFP;
1111 		break;
1112 	case           BPM_HID:
1113 	case BPM_HFP + BPM_HID:
1114 		algorithm = COEX_ALGO_HID;
1115 		break;
1116 	case BPM_HFP           + BPM_A2DP:
1117 	case           BPM_HID + BPM_A2DP:
1118 	case BPM_HFP + BPM_HID + BPM_A2DP:
1119 		algorithm = COEX_ALGO_A2DP_HID;
1120 		break;
1121 	case BPM_HFP                      + BPM_PAN:
1122 	case           BPM_HID            + BPM_PAN:
1123 	case BPM_HFP + BPM_HID            + BPM_PAN:
1124 		algorithm = COEX_ALGO_PAN_HID;
1125 		break;
1126 	case BPM_HFP           + BPM_A2DP + BPM_PAN:
1127 	case           BPM_HID + BPM_A2DP + BPM_PAN:
1128 	case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1129 		algorithm = COEX_ALGO_A2DP_PAN_HID;
1130 		break;
1131 	case                                BPM_PAN:
1132 		algorithm = COEX_ALGO_PAN;
1133 		break;
1134 	case                     BPM_A2DP + BPM_PAN:
1135 		algorithm = COEX_ALGO_A2DP_PAN;
1136 		break;
1137 	case                     BPM_A2DP:
1138 		if (coex_stat->bt_multi_link) {
1139 			if (coex_stat->bt_hid_pair_num > 0)
1140 				algorithm = COEX_ALGO_A2DP_HID;
1141 			else
1142 				algorithm = COEX_ALGO_A2DP_PAN;
1143 		} else {
1144 			algorithm = COEX_ALGO_A2DP;
1145 		}
1146 		break;
1147 	default:
1148 		algorithm = COEX_ALGO_NOPROFILE;
1149 		break;
1150 	}
1151 
1152 	return algorithm;
1153 }
1154 
rtw_coex_action_coex_all_off(struct rtw_dev * rtwdev)1155 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1156 {
1157 	struct rtw_efuse *efuse = &rtwdev->efuse;
1158 	struct rtw_chip_info *chip = rtwdev->chip;
1159 	u8 table_case, tdma_case;
1160 
1161 	if (efuse->share_ant) {
1162 		/* Shared-Ant */
1163 		table_case = 2;
1164 		tdma_case = 0;
1165 	} else {
1166 		/* Non-Shared-Ant */
1167 		table_case = 100;
1168 		tdma_case = 100;
1169 	}
1170 
1171 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1172 	rtw_coex_table(rtwdev, table_case);
1173 	rtw_coex_tdma(rtwdev, false, tdma_case);
1174 }
1175 
rtw_coex_action_freerun(struct rtw_dev * rtwdev)1176 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1177 {
1178 	struct rtw_coex *coex = &rtwdev->coex;
1179 	struct rtw_coex_stat *coex_stat = &coex->stat;
1180 	struct rtw_coex_dm *coex_dm = &coex->dm;
1181 	struct rtw_efuse *efuse = &rtwdev->efuse;
1182 	struct rtw_chip_info *chip = rtwdev->chip;
1183 	u8 level = 0;
1184 
1185 	if (efuse->share_ant)
1186 		return;
1187 
1188 	coex->freerun = true;
1189 
1190 	if (coex_stat->wl_connected)
1191 		rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1192 
1193 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1194 
1195 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1196 
1197 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1198 		level = 2;
1199 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1200 		level = 3;
1201 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1202 		level = 4;
1203 	else
1204 		level = 5;
1205 
1206 	if (level > chip->wl_rf_para_num - 1)
1207 		level = chip->wl_rf_para_num - 1;
1208 
1209 	if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1210 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1211 	else
1212 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1213 
1214 	rtw_coex_table(rtwdev, 100);
1215 	rtw_coex_tdma(rtwdev, false, 100);
1216 }
1217 
rtw_coex_action_bt_whql_test(struct rtw_dev * rtwdev)1218 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1219 {
1220 	struct rtw_efuse *efuse = &rtwdev->efuse;
1221 	struct rtw_chip_info *chip = rtwdev->chip;
1222 	u8 table_case, tdma_case;
1223 
1224 	if (efuse->share_ant) {
1225 		/* Shared-Ant */
1226 		table_case = 2;
1227 		tdma_case = 0;
1228 	} else {
1229 		/* Non-Shared-Ant */
1230 		table_case = 100;
1231 		tdma_case = 100;
1232 	}
1233 
1234 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1235 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1236 	rtw_coex_table(rtwdev, table_case);
1237 	rtw_coex_tdma(rtwdev, false, tdma_case);
1238 }
1239 
rtw_coex_action_bt_relink(struct rtw_dev * rtwdev)1240 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1241 {
1242 	struct rtw_efuse *efuse = &rtwdev->efuse;
1243 	struct rtw_chip_info *chip = rtwdev->chip;
1244 	u8 table_case, tdma_case;
1245 
1246 	if (efuse->share_ant) {
1247 		/* Shared-Ant */
1248 		table_case = 1;
1249 		tdma_case = 0;
1250 	} else {
1251 		/* Non-Shared-Ant */
1252 		table_case = 100;
1253 		tdma_case = 100;
1254 	}
1255 
1256 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1257 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1258 	rtw_coex_table(rtwdev, table_case);
1259 	rtw_coex_tdma(rtwdev, false, tdma_case);
1260 }
1261 
rtw_coex_action_bt_idle(struct rtw_dev * rtwdev)1262 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1263 {
1264 	struct rtw_coex *coex = &rtwdev->coex;
1265 	struct rtw_coex_stat *coex_stat = &coex->stat;
1266 	struct rtw_coex_dm *coex_dm = &coex->dm;
1267 	struct rtw_efuse *efuse = &rtwdev->efuse;
1268 	struct rtw_chip_info *chip = rtwdev->chip;
1269 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1270 	u8 table_case = 0xff, tdma_case = 0xff;
1271 
1272 	if (coex_rfe->ant_switch_with_bt &&
1273 	    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1274 		if (efuse->share_ant &&
1275 		    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) {
1276 			table_case = 0;
1277 			tdma_case = 0;
1278 		} else if (!efuse->share_ant) {
1279 			table_case = 100;
1280 			tdma_case = 100;
1281 		}
1282 	}
1283 
1284 	if (table_case != 0xff && tdma_case != 0xff) {
1285 		rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1286 		rtw_coex_table(rtwdev, table_case);
1287 		rtw_coex_tdma(rtwdev, false, tdma_case);
1288 		return;
1289 	}
1290 
1291 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1292 
1293 	if (efuse->share_ant) {
1294 		/* Shared-Ant */
1295 		if (!coex_stat->wl_gl_busy) {
1296 			table_case = 10;
1297 			tdma_case = 3;
1298 		} else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1299 			table_case = 6;
1300 			tdma_case = 7;
1301 		} else {
1302 			table_case = 12;
1303 			tdma_case = 7;
1304 		}
1305 	} else {
1306 		/* Non-Shared-Ant */
1307 		if (!coex_stat->wl_gl_busy) {
1308 			table_case = 112;
1309 			tdma_case = 104;
1310 		} else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1311 			    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1312 			table_case = 114;
1313 			tdma_case = 103;
1314 		} else {
1315 			table_case = 112;
1316 			tdma_case = 103;
1317 		}
1318 	}
1319 
1320 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1321 	rtw_coex_table(rtwdev, table_case);
1322 	rtw_coex_tdma(rtwdev, false, tdma_case);
1323 }
1324 
rtw_coex_action_bt_inquiry(struct rtw_dev * rtwdev)1325 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1326 {
1327 	struct rtw_coex *coex = &rtwdev->coex;
1328 	struct rtw_coex_stat *coex_stat = &coex->stat;
1329 	struct rtw_efuse *efuse = &rtwdev->efuse;
1330 	struct rtw_chip_info *chip = rtwdev->chip;
1331 	bool wl_hi_pri = false;
1332 	u8 table_case, tdma_case;
1333 	u32 slot_type = 0;
1334 
1335 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1336 	    coex_stat->wl_hi_pri_task2)
1337 		wl_hi_pri = true;
1338 
1339 	if (efuse->share_ant) {
1340 		/* Shared-Ant */
1341 		if (wl_hi_pri) {
1342 			table_case = 15;
1343 			if (coex_stat->bt_profile_num > 0)
1344 				tdma_case = 10;
1345 			else if (coex_stat->wl_hi_pri_task1)
1346 				tdma_case = 6;
1347 			else if (!coex_stat->bt_page)
1348 				tdma_case = 8;
1349 			else
1350 				tdma_case = 9;
1351 		} else if (coex_stat->wl_gl_busy) {
1352 			if (coex_stat->bt_profile_num == 0) {
1353 				table_case = 12;
1354 				tdma_case = 18;
1355 			} else if (coex_stat->bt_profile_num == 1 &&
1356 				   !coex_stat->bt_a2dp_exist) {
1357 				slot_type = TDMA_4SLOT;
1358 				table_case = 12;
1359 				tdma_case = 20;
1360 			} else {
1361 				slot_type = TDMA_4SLOT;
1362 				table_case = 12;
1363 				tdma_case = 26;
1364 			}
1365 		} else if (coex_stat->wl_connected) {
1366 			table_case = 9;
1367 			tdma_case = 27;
1368 		} else {
1369 			table_case = 1;
1370 			tdma_case = 0;
1371 		}
1372 	} else {
1373 		/* Non_Shared-Ant */
1374 		if (wl_hi_pri) {
1375 			table_case = 113;
1376 			if (coex_stat->bt_a2dp_exist &&
1377 			    !coex_stat->bt_pan_exist)
1378 				tdma_case = 111;
1379 			else if (coex_stat->wl_hi_pri_task1)
1380 				tdma_case = 106;
1381 			else if (!coex_stat->bt_page)
1382 				tdma_case = 108;
1383 			else
1384 				tdma_case = 109;
1385 		} else if (coex_stat->wl_gl_busy) {
1386 			table_case = 114;
1387 			tdma_case = 121;
1388 		} else if (coex_stat->wl_connected) {
1389 			table_case = 100;
1390 			tdma_case = 100;
1391 		} else {
1392 			table_case = 101;
1393 			tdma_case = 100;
1394 		}
1395 	}
1396 
1397 	rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
1398 		wl_hi_pri, coex_stat->bt_page);
1399 
1400 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1401 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1402 	rtw_coex_table(rtwdev, table_case);
1403 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1404 }
1405 
rtw_coex_action_bt_hfp(struct rtw_dev * rtwdev)1406 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1407 {
1408 	struct rtw_coex *coex = &rtwdev->coex;
1409 	struct rtw_coex_stat *coex_stat = &coex->stat;
1410 	struct rtw_efuse *efuse = &rtwdev->efuse;
1411 	struct rtw_chip_info *chip = rtwdev->chip;
1412 	u8 table_case, tdma_case;
1413 
1414 	if (efuse->share_ant) {
1415 		/* Shared-Ant */
1416 		if (coex_stat->bt_multi_link) {
1417 			table_case = 10;
1418 			tdma_case = 17;
1419 		} else {
1420 			table_case = 10;
1421 			tdma_case = 5;
1422 		}
1423 	} else {
1424 		/* Non-Shared-Ant */
1425 		if (coex_stat->bt_multi_link) {
1426 			table_case = 112;
1427 			tdma_case = 117;
1428 		} else {
1429 			table_case = 105;
1430 			tdma_case = 100;
1431 		}
1432 	}
1433 
1434 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1435 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1436 	rtw_coex_table(rtwdev, table_case);
1437 	rtw_coex_tdma(rtwdev, false, tdma_case);
1438 }
1439 
rtw_coex_action_bt_hid(struct rtw_dev * rtwdev)1440 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1441 {
1442 	struct rtw_coex *coex = &rtwdev->coex;
1443 	struct rtw_coex_stat *coex_stat = &coex->stat;
1444 	struct rtw_efuse *efuse = &rtwdev->efuse;
1445 	struct rtw_chip_info *chip = rtwdev->chip;
1446 	u8 table_case, tdma_case;
1447 	u32 wl_bw;
1448 
1449 	wl_bw = rtwdev->hal.current_band_width;
1450 
1451 	if (efuse->share_ant) {
1452 		/* Shared-Ant */
1453 		if (coex_stat->bt_ble_exist) {
1454 			/* RCU */
1455 			if (!coex_stat->wl_gl_busy)
1456 				table_case = 14;
1457 			else
1458 				table_case = 15;
1459 
1460 			if (coex_stat->bt_a2dp_active || wl_bw == 0)
1461 				tdma_case = 18;
1462 			else if (coex_stat->wl_gl_busy)
1463 				tdma_case = 8;
1464 			else
1465 				tdma_case = 4;
1466 		} else {
1467 			if (coex_stat->bt_a2dp_active || wl_bw == 0) {
1468 				table_case = 8;
1469 				tdma_case = 4;
1470 			} else {
1471 				/* for 4/18 HID */
1472 				if (coex_stat->bt_418_hid_exist &&
1473 				    coex_stat->wl_gl_busy)
1474 					table_case = 12;
1475 				else
1476 					table_case = 10;
1477 				tdma_case = 4;
1478 			}
1479 		}
1480 	} else {
1481 		/* Non-Shared-Ant */
1482 		if (coex_stat->bt_a2dp_active) {
1483 			table_case = 113;
1484 			tdma_case = 118;
1485 		} else if (coex_stat->bt_ble_exist) {
1486 			/* BLE */
1487 			table_case = 113;
1488 
1489 			if (coex_stat->wl_gl_busy)
1490 				tdma_case = 106;
1491 			else
1492 				tdma_case = 104;
1493 		} else {
1494 			table_case = 113;
1495 			tdma_case = 104;
1496 		}
1497 	}
1498 
1499 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1500 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1501 	rtw_coex_table(rtwdev, table_case);
1502 	rtw_coex_tdma(rtwdev, false, tdma_case);
1503 }
1504 
rtw_coex_action_bt_a2dp(struct rtw_dev * rtwdev)1505 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1506 {
1507 	struct rtw_coex *coex = &rtwdev->coex;
1508 	struct rtw_coex_stat *coex_stat = &coex->stat;
1509 	struct rtw_coex_dm *coex_dm = &coex->dm;
1510 	struct rtw_efuse *efuse = &rtwdev->efuse;
1511 	struct rtw_chip_info *chip = rtwdev->chip;
1512 	u8 table_case, tdma_case;
1513 	u32 slot_type = 0;
1514 
1515 	if (efuse->share_ant) {
1516 		/* Shared-Ant */
1517 		slot_type = TDMA_4SLOT;
1518 
1519 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1520 			table_case = 10;
1521 		else
1522 			table_case = 9;
1523 
1524 		if (coex_stat->wl_gl_busy)
1525 			tdma_case = 13;
1526 		else
1527 			tdma_case = 14;
1528 	} else {
1529 		/* Non-Shared-Ant */
1530 		table_case = 112;
1531 
1532 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1533 			tdma_case = 112;
1534 		else
1535 			tdma_case = 113;
1536 	}
1537 
1538 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1539 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1540 	rtw_coex_table(rtwdev, table_case);
1541 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1542 }
1543 
rtw_coex_action_bt_a2dpsink(struct rtw_dev * rtwdev)1544 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1545 {
1546 	struct rtw_coex *coex = &rtwdev->coex;
1547 	struct rtw_coex_stat *coex_stat = &coex->stat;
1548 	struct rtw_efuse *efuse = &rtwdev->efuse;
1549 	struct rtw_chip_info *chip = rtwdev->chip;
1550 	u8 table_case, tdma_case;
1551 	bool ap_enable = false;
1552 
1553 	if (efuse->share_ant) { /* Shared-Ant */
1554 		if (ap_enable) {
1555 			table_case = 2;
1556 			tdma_case = 0;
1557 		} else if (coex_stat->wl_gl_busy) {
1558 			table_case = 28;
1559 			tdma_case = 20;
1560 		} else {
1561 			table_case = 28;
1562 			tdma_case = 26;
1563 		}
1564 	} else { /* Non-Shared-Ant */
1565 		if (ap_enable) {
1566 			table_case = 100;
1567 			tdma_case = 100;
1568 		} else {
1569 			table_case = 119;
1570 			tdma_case = 120;
1571 		}
1572 	}
1573 
1574 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1575 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1576 	rtw_coex_table(rtwdev, table_case);
1577 	rtw_coex_tdma(rtwdev, false, tdma_case);
1578 }
1579 
rtw_coex_action_bt_pan(struct rtw_dev * rtwdev)1580 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
1581 {
1582 	struct rtw_coex *coex = &rtwdev->coex;
1583 	struct rtw_coex_stat *coex_stat = &coex->stat;
1584 	struct rtw_efuse *efuse = &rtwdev->efuse;
1585 	struct rtw_chip_info *chip = rtwdev->chip;
1586 	u8 table_case, tdma_case;
1587 
1588 	if (efuse->share_ant) {
1589 		/* Shared-Ant */
1590 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1591 			table_case = 14;
1592 		else
1593 			table_case = 10;
1594 
1595 		if (coex_stat->wl_gl_busy)
1596 			tdma_case = 17;
1597 		else
1598 			tdma_case = 19;
1599 	} else {
1600 		/* Non-Shared-Ant */
1601 		table_case = 112;
1602 
1603 		if (coex_stat->wl_gl_busy)
1604 			tdma_case = 117;
1605 		else
1606 			tdma_case = 119;
1607 	}
1608 
1609 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1610 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1611 	rtw_coex_table(rtwdev, table_case);
1612 	rtw_coex_tdma(rtwdev, false, tdma_case);
1613 }
1614 
rtw_coex_action_bt_a2dp_hid(struct rtw_dev * rtwdev)1615 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
1616 {
1617 	struct rtw_coex *coex = &rtwdev->coex;
1618 	struct rtw_coex_stat *coex_stat = &coex->stat;
1619 	struct rtw_coex_dm *coex_dm = &coex->dm;
1620 	struct rtw_efuse *efuse = &rtwdev->efuse;
1621 	struct rtw_chip_info *chip = rtwdev->chip;
1622 	u8 table_case, tdma_case;
1623 	u32 slot_type = 0;
1624 
1625 	if (efuse->share_ant) {
1626 		/* Shared-Ant */
1627 		slot_type = TDMA_4SLOT;
1628 
1629 		if (coex_stat->bt_ble_exist)
1630 			table_case = 26;
1631 		else
1632 			table_case = 9;
1633 
1634 		if (coex_stat->wl_gl_busy) {
1635 			tdma_case = 13;
1636 		} else {
1637 			tdma_case = 14;
1638 		}
1639 	} else {
1640 		/* Non-Shared-Ant */
1641 		if (coex_stat->bt_ble_exist)
1642 			table_case = 121;
1643 		else
1644 			table_case = 113;
1645 
1646 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1647 			tdma_case = 112;
1648 		else
1649 			tdma_case = 113;
1650 	}
1651 
1652 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1653 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1654 	rtw_coex_table(rtwdev, table_case);
1655 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1656 }
1657 
rtw_coex_action_bt_a2dp_pan(struct rtw_dev * rtwdev)1658 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
1659 {
1660 	struct rtw_coex *coex = &rtwdev->coex;
1661 	struct rtw_coex_stat *coex_stat = &coex->stat;
1662 	struct rtw_efuse *efuse = &rtwdev->efuse;
1663 	struct rtw_chip_info *chip = rtwdev->chip;
1664 	u8 table_case, tdma_case;
1665 
1666 	if (efuse->share_ant) {
1667 		/* Shared-Ant */
1668 		if (coex_stat->wl_gl_busy &&
1669 		    coex_stat->wl_noisy_level == 0)
1670 			table_case = 14;
1671 		else
1672 			table_case = 10;
1673 
1674 		if (coex_stat->wl_gl_busy)
1675 			tdma_case = 15;
1676 		else
1677 			tdma_case = 20;
1678 	} else {
1679 		/* Non-Shared-Ant */
1680 		table_case = 112;
1681 
1682 		if (coex_stat->wl_gl_busy)
1683 			tdma_case = 115;
1684 		else
1685 			tdma_case = 120;
1686 	}
1687 
1688 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1689 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1690 	rtw_coex_table(rtwdev, table_case);
1691 	rtw_coex_tdma(rtwdev, false, tdma_case);
1692 }
1693 
rtw_coex_action_bt_pan_hid(struct rtw_dev * rtwdev)1694 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
1695 {
1696 	struct rtw_coex *coex = &rtwdev->coex;
1697 	struct rtw_coex_stat *coex_stat = &coex->stat;
1698 	struct rtw_efuse *efuse = &rtwdev->efuse;
1699 	struct rtw_chip_info *chip = rtwdev->chip;
1700 	u8 table_case, tdma_case;
1701 
1702 	if (efuse->share_ant) {
1703 		/* Shared-Ant */
1704 		table_case = 9;
1705 
1706 		if (coex_stat->wl_gl_busy)
1707 			tdma_case = 18;
1708 		else
1709 			tdma_case = 19;
1710 	} else {
1711 		/* Non-Shared-Ant */
1712 		table_case = 113;
1713 
1714 		if (coex_stat->wl_gl_busy)
1715 			tdma_case = 117;
1716 		else
1717 			tdma_case = 119;
1718 	}
1719 
1720 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1721 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1722 	rtw_coex_table(rtwdev, table_case);
1723 	rtw_coex_tdma(rtwdev, false, tdma_case);
1724 }
1725 
rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev * rtwdev)1726 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
1727 {
1728 	struct rtw_coex *coex = &rtwdev->coex;
1729 	struct rtw_coex_stat *coex_stat = &coex->stat;
1730 	struct rtw_efuse *efuse = &rtwdev->efuse;
1731 	struct rtw_chip_info *chip = rtwdev->chip;
1732 	u8 table_case, tdma_case;
1733 
1734 	if (efuse->share_ant) {
1735 		/* Shared-Ant */
1736 		table_case = 10;
1737 
1738 		if (coex_stat->wl_gl_busy)
1739 			tdma_case = 15;
1740 		else
1741 			tdma_case = 20;
1742 	} else {
1743 		/* Non-Shared-Ant */
1744 		table_case = 113;
1745 
1746 		if (coex_stat->wl_gl_busy)
1747 			tdma_case = 115;
1748 		else
1749 			tdma_case = 120;
1750 	}
1751 
1752 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1753 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1754 	rtw_coex_table(rtwdev, table_case);
1755 	rtw_coex_tdma(rtwdev, false, tdma_case);
1756 }
1757 
rtw_coex_action_wl_under5g(struct rtw_dev * rtwdev)1758 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
1759 {
1760 	struct rtw_efuse *efuse = &rtwdev->efuse;
1761 	struct rtw_chip_info *chip = rtwdev->chip;
1762 	u8 table_case, tdma_case;
1763 
1764 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1765 
1766 	if (efuse->share_ant) {
1767 		/* Shared-Ant */
1768 		table_case = 0;
1769 		tdma_case = 0;
1770 	} else {
1771 		/* Non-Shared-Ant */
1772 		table_case = 100;
1773 		tdma_case = 100;
1774 	}
1775 
1776 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
1777 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1778 	rtw_coex_table(rtwdev, table_case);
1779 	rtw_coex_tdma(rtwdev, false, tdma_case);
1780 }
1781 
rtw_coex_action_wl_only(struct rtw_dev * rtwdev)1782 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
1783 {
1784 	struct rtw_efuse *efuse = &rtwdev->efuse;
1785 	struct rtw_chip_info *chip = rtwdev->chip;
1786 	u8 table_case, tdma_case;
1787 
1788 	if (efuse->share_ant) {
1789 		/* Shared-Ant */
1790 		table_case = 2;
1791 		tdma_case = 0;
1792 	} else {
1793 		/* Non-Shared-Ant */
1794 		table_case = 100;
1795 		tdma_case = 100;
1796 	}
1797 
1798 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1799 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1800 	rtw_coex_table(rtwdev, table_case);
1801 	rtw_coex_tdma(rtwdev, false, tdma_case);
1802 }
1803 
rtw_coex_action_wl_native_lps(struct rtw_dev * rtwdev)1804 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
1805 {
1806 	struct rtw_coex *coex = &rtwdev->coex;
1807 	struct rtw_efuse *efuse = &rtwdev->efuse;
1808 	struct rtw_chip_info *chip = rtwdev->chip;
1809 	u8 table_case, tdma_case;
1810 
1811 	if (coex->under_5g)
1812 		return;
1813 
1814 	if (efuse->share_ant) {
1815 		/* Shared-Ant */
1816 		table_case = 28;
1817 		tdma_case = 0;
1818 	} else {
1819 		/* Non-Shared-Ant */
1820 		table_case = 100;
1821 		tdma_case = 100;
1822 	}
1823 
1824 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1825 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1826 	rtw_coex_table(rtwdev, table_case);
1827 	rtw_coex_tdma(rtwdev, false, tdma_case);
1828 }
1829 
rtw_coex_action_wl_linkscan(struct rtw_dev * rtwdev)1830 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
1831 {
1832 	struct rtw_coex *coex = &rtwdev->coex;
1833 	struct rtw_coex_stat *coex_stat = &coex->stat;
1834 	struct rtw_efuse *efuse = &rtwdev->efuse;
1835 	struct rtw_chip_info *chip = rtwdev->chip;
1836 	u8 table_case, tdma_case;
1837 	u32 slot_type = 0;
1838 
1839 	if (efuse->share_ant) {
1840 		/* Shared-Ant */
1841 		if (coex_stat->bt_a2dp_exist) {
1842 			slot_type = TDMA_4SLOT;
1843 			table_case = 9;
1844 			tdma_case = 11;
1845 		} else {
1846 			table_case = 9;
1847 			tdma_case = 7;
1848 		}
1849 	} else {
1850 		/* Non-Shared-Ant */
1851 		if (coex_stat->bt_a2dp_exist) {
1852 			table_case = 112;
1853 			tdma_case = 111;
1854 		} else {
1855 			table_case = 112;
1856 			tdma_case = 107;
1857 		}
1858 	}
1859 
1860 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1861 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1862 	rtw_coex_table(rtwdev, table_case);
1863 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1864 }
1865 
rtw_coex_action_wl_not_connected(struct rtw_dev * rtwdev)1866 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
1867 {
1868 	struct rtw_efuse *efuse = &rtwdev->efuse;
1869 	struct rtw_chip_info *chip = rtwdev->chip;
1870 	u8 table_case, tdma_case;
1871 
1872 	if (efuse->share_ant) {
1873 		/* Shared-Ant */
1874 		table_case = 1;
1875 		tdma_case = 0;
1876 	} else {
1877 		/* Non-Shared-Ant */
1878 		table_case = 100;
1879 		tdma_case = 100;
1880 	}
1881 
1882 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1883 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1884 	rtw_coex_table(rtwdev, table_case);
1885 	rtw_coex_tdma(rtwdev, false, tdma_case);
1886 }
1887 
rtw_coex_action_wl_connected(struct rtw_dev * rtwdev)1888 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
1889 {
1890 	struct rtw_coex *coex = &rtwdev->coex;
1891 	struct rtw_coex_stat *coex_stat = &coex->stat;
1892 	struct rtw_coex_dm *coex_dm = &coex->dm;
1893 	struct rtw_efuse *efuse = &rtwdev->efuse;
1894 	u8 algorithm;
1895 
1896 	/* Non-Shared-Ant */
1897 	if (!efuse->share_ant && coex_stat->wl_gl_busy &&
1898 	    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1899 	    COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
1900 		rtw_coex_action_freerun(rtwdev);
1901 		return;
1902 	}
1903 
1904 	algorithm = rtw_coex_algorithm(rtwdev);
1905 
1906 	switch (algorithm) {
1907 	case COEX_ALGO_HFP:
1908 		rtw_coex_action_bt_hfp(rtwdev);
1909 		break;
1910 	case COEX_ALGO_HID:
1911 		rtw_coex_action_bt_hid(rtwdev);
1912 		break;
1913 	case COEX_ALGO_A2DP:
1914 		if (coex_stat->bt_a2dp_sink)
1915 			rtw_coex_action_bt_a2dpsink(rtwdev);
1916 		else
1917 			rtw_coex_action_bt_a2dp(rtwdev);
1918 		break;
1919 	case COEX_ALGO_PAN:
1920 		rtw_coex_action_bt_pan(rtwdev);
1921 		break;
1922 	case COEX_ALGO_A2DP_HID:
1923 		rtw_coex_action_bt_a2dp_hid(rtwdev);
1924 		break;
1925 	case COEX_ALGO_A2DP_PAN:
1926 		rtw_coex_action_bt_a2dp_pan(rtwdev);
1927 		break;
1928 	case COEX_ALGO_PAN_HID:
1929 		rtw_coex_action_bt_pan_hid(rtwdev);
1930 		break;
1931 	case COEX_ALGO_A2DP_PAN_HID:
1932 		rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
1933 		break;
1934 	default:
1935 	case COEX_ALGO_NOPROFILE:
1936 		rtw_coex_action_bt_idle(rtwdev);
1937 		break;
1938 	}
1939 }
1940 
rtw_coex_run_coex(struct rtw_dev * rtwdev,u8 reason)1941 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
1942 {
1943 	struct rtw_coex *coex = &rtwdev->coex;
1944 	struct rtw_coex_dm *coex_dm = &coex->dm;
1945 	struct rtw_coex_stat *coex_stat = &coex->stat;
1946 
1947 	lockdep_assert_held(&rtwdev->mutex);
1948 
1949 	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
1950 		return;
1951 
1952 	coex_dm->reason = reason;
1953 
1954 	/* update wifi_link_info_ext variable */
1955 	rtw_coex_update_wl_link_info(rtwdev, reason);
1956 
1957 	rtw_coex_monitor_bt_enable(rtwdev);
1958 
1959 	if (coex->stop_dm)
1960 		return;
1961 
1962 	if (coex_stat->wl_under_ips)
1963 		return;
1964 
1965 	if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
1966 	    !coex_stat->bt_setup_link)
1967 		return;
1968 
1969 	coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
1970 	coex->freerun = false;
1971 
1972 	/* Pure-5G Coex Process */
1973 	if (coex->under_5g) {
1974 		coex_stat->wl_coex_mode = COEX_WLINK_5G;
1975 		rtw_coex_action_wl_under5g(rtwdev);
1976 		goto exit;
1977 	}
1978 
1979 	coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
1980 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1981 	if (coex_stat->bt_disabled) {
1982 		rtw_coex_action_wl_only(rtwdev);
1983 		goto exit;
1984 	}
1985 
1986 	if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
1987 		rtw_coex_action_wl_native_lps(rtwdev);
1988 		goto exit;
1989 	}
1990 
1991 	if (coex_stat->bt_whck_test) {
1992 		rtw_coex_action_bt_whql_test(rtwdev);
1993 		goto exit;
1994 	}
1995 
1996 	if (coex_stat->bt_setup_link) {
1997 		rtw_coex_action_bt_relink(rtwdev);
1998 		goto exit;
1999 	}
2000 
2001 	if (coex_stat->bt_inq_page) {
2002 		rtw_coex_action_bt_inquiry(rtwdev);
2003 		goto exit;
2004 	}
2005 
2006 	if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2007 	     coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2008 	     coex_stat->wl_connected) {
2009 		rtw_coex_action_bt_idle(rtwdev);
2010 		goto exit;
2011 	}
2012 
2013 	if (coex_stat->wl_linkscan_proc) {
2014 		rtw_coex_action_wl_linkscan(rtwdev);
2015 		goto exit;
2016 	}
2017 
2018 	if (coex_stat->wl_connected)
2019 		rtw_coex_action_wl_connected(rtwdev);
2020 	else
2021 		rtw_coex_action_wl_not_connected(rtwdev);
2022 
2023 exit:
2024 	rtw_coex_set_gnt_fix(rtwdev);
2025 	rtw_coex_limited_wl(rtwdev);
2026 }
2027 
rtw_coex_init_coex_var(struct rtw_dev * rtwdev)2028 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2029 {
2030 	struct rtw_coex *coex = &rtwdev->coex;
2031 	struct rtw_coex_stat *coex_stat = &coex->stat;
2032 	struct rtw_coex_dm *coex_dm = &coex->dm;
2033 	u8 i;
2034 
2035 	memset(coex_dm, 0, sizeof(*coex_dm));
2036 	memset(coex_stat, 0, sizeof(*coex_stat));
2037 
2038 	for (i = 0; i < COEX_CNT_WL_MAX; i++)
2039 		coex_stat->cnt_wl[i] = 0;
2040 
2041 	for (i = 0; i < COEX_CNT_BT_MAX; i++)
2042 		coex_stat->cnt_bt[i] = 0;
2043 
2044 	for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2045 		coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2046 
2047 	for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2048 		coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2049 
2050 	coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2051 }
2052 
__rtw_coex_init_hw_config(struct rtw_dev * rtwdev,bool wifi_only)2053 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2054 {
2055 	struct rtw_coex *coex = &rtwdev->coex;
2056 
2057 	rtw_coex_init_coex_var(rtwdev);
2058 	rtw_coex_monitor_bt_enable(rtwdev);
2059 	rtw_coex_set_rfe_type(rtwdev);
2060 	rtw_coex_set_init(rtwdev);
2061 
2062 	/* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2063 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2064 
2065 	/* set Tx beacon = Hi-Pri */
2066 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2067 
2068 	/* set Tx beacon queue = Hi-Pri */
2069 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2070 
2071 	/* antenna config */
2072 	if (coex->wl_rf_off) {
2073 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2074 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2075 		coex->stop_dm = true;
2076 	} else if (wifi_only) {
2077 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2078 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2079 				    true);
2080 		coex->stop_dm = true;
2081 	} else {
2082 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2083 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2084 				    true);
2085 		coex->stop_dm = false;
2086 		coex->freeze = true;
2087 	}
2088 
2089 	/* PTA parameter */
2090 	rtw_coex_table(rtwdev, 0);
2091 	rtw_coex_tdma(rtwdev, true, 0);
2092 	rtw_coex_query_bt_info(rtwdev);
2093 }
2094 
rtw_coex_power_on_setting(struct rtw_dev * rtwdev)2095 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2096 {
2097 	struct rtw_coex *coex = &rtwdev->coex;
2098 
2099 	coex->stop_dm = true;
2100 	coex->wl_rf_off = false;
2101 
2102 	/* enable BB, we can write 0x948 */
2103 	rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
2104 
2105 	rtw_coex_monitor_bt_enable(rtwdev);
2106 	rtw_coex_set_rfe_type(rtwdev);
2107 
2108 	/* set antenna path to BT */
2109 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2110 
2111 	/* red x issue */
2112 	rtw_write8(rtwdev, 0xff1a, 0x0);
2113 }
2114 
rtw_coex_init_hw_config(struct rtw_dev * rtwdev,bool wifi_only)2115 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2116 {
2117 	__rtw_coex_init_hw_config(rtwdev, wifi_only);
2118 }
2119 
rtw_coex_ips_notify(struct rtw_dev * rtwdev,u8 type)2120 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2121 {
2122 	struct rtw_coex *coex = &rtwdev->coex;
2123 	struct rtw_coex_stat *coex_stat = &coex->stat;
2124 
2125 	if (coex->stop_dm)
2126 		return;
2127 
2128 	if (type == COEX_IPS_ENTER) {
2129 		coex_stat->wl_under_ips = true;
2130 
2131 		/* for lps off */
2132 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2133 
2134 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2135 		rtw_coex_action_coex_all_off(rtwdev);
2136 	} else if (type == COEX_IPS_LEAVE) {
2137 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2138 
2139 		/* run init hw config (exclude wifi only) */
2140 		__rtw_coex_init_hw_config(rtwdev, false);
2141 		/* sw all off */
2142 
2143 		coex_stat->wl_under_ips = false;
2144 	}
2145 }
2146 
rtw_coex_lps_notify(struct rtw_dev * rtwdev,u8 type)2147 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2148 {
2149 	struct rtw_coex *coex = &rtwdev->coex;
2150 	struct rtw_coex_stat *coex_stat = &coex->stat;
2151 
2152 	if (coex->stop_dm)
2153 		return;
2154 
2155 	if (type == COEX_LPS_ENABLE) {
2156 		coex_stat->wl_under_lps = true;
2157 
2158 		if (coex_stat->wl_force_lps_ctrl) {
2159 			/* for ps-tdma */
2160 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2161 		} else {
2162 			/* for native ps */
2163 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2164 
2165 			rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2166 		}
2167 	} else if (type == COEX_LPS_DISABLE) {
2168 		coex_stat->wl_under_lps = false;
2169 
2170 		/* for lps off */
2171 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2172 
2173 		if (!coex_stat->wl_force_lps_ctrl)
2174 			rtw_coex_query_bt_info(rtwdev);
2175 	}
2176 }
2177 
rtw_coex_scan_notify(struct rtw_dev * rtwdev,u8 type)2178 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2179 {
2180 	struct rtw_coex *coex = &rtwdev->coex;
2181 	struct rtw_coex_stat *coex_stat = &coex->stat;
2182 
2183 	if (coex->stop_dm)
2184 		return;
2185 
2186 	coex->freeze = false;
2187 
2188 	if (type != COEX_SCAN_FINISH)
2189 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2190 				    COEX_SCBD_ONOFF, true);
2191 
2192 	if (type == COEX_SCAN_START_5G) {
2193 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2194 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2195 	} else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2196 		coex_stat->wl_hi_pri_task2 = true;
2197 
2198 		/* Force antenna setup for no scan result issue */
2199 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2200 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2201 	} else {
2202 		coex_stat->wl_hi_pri_task2 = false;
2203 		rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2204 	}
2205 }
2206 
rtw_coex_switchband_notify(struct rtw_dev * rtwdev,u8 type)2207 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2208 {
2209 	struct rtw_coex *coex = &rtwdev->coex;
2210 
2211 	if (coex->stop_dm)
2212 		return;
2213 
2214 	if (type == COEX_SWITCH_TO_5G)
2215 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2216 	else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2217 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2218 	else
2219 		rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2220 }
2221 
rtw_coex_connect_notify(struct rtw_dev * rtwdev,u8 type)2222 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2223 {
2224 	struct rtw_coex *coex = &rtwdev->coex;
2225 	struct rtw_coex_stat *coex_stat = &coex->stat;
2226 
2227 	if (coex->stop_dm)
2228 		return;
2229 
2230 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2231 			    COEX_SCBD_ONOFF, true);
2232 
2233 	if (type == COEX_ASSOCIATE_5G_START) {
2234 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2235 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2236 	} else if (type == COEX_ASSOCIATE_5G_FINISH) {
2237 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2238 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2239 	} else if (type == COEX_ASSOCIATE_START) {
2240 		coex_stat->wl_hi_pri_task1 = true;
2241 		coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2242 
2243 		/* Force antenna setup for no scan result issue */
2244 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2245 
2246 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2247 
2248 		/* To keep TDMA case during connect process,
2249 		 * to avoid changed by Btinfo and runcoexmechanism
2250 		 */
2251 		coex->freeze = true;
2252 		ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2253 					     5 * HZ);
2254 	} else {
2255 		coex_stat->wl_hi_pri_task1 = false;
2256 		coex->freeze = false;
2257 
2258 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2259 	}
2260 }
2261 
rtw_coex_media_status_notify(struct rtw_dev * rtwdev,u8 type)2262 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2263 {
2264 	struct rtw_coex *coex = &rtwdev->coex;
2265 	struct rtw_coex_stat *coex_stat = &coex->stat;
2266 	u8 para[6] = {0};
2267 
2268 	if (coex->stop_dm)
2269 		return;
2270 
2271 	if (type == COEX_MEDIA_CONNECT_5G) {
2272 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2273 
2274 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2275 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2276 	} else if (type == COEX_MEDIA_CONNECT) {
2277 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2278 
2279 		/* Force antenna setup for no scan result issue */
2280 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2281 
2282 		/* Set CCK Rx high Pri */
2283 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2284 
2285 		/* always enable 5ms extend if connect */
2286 		para[0] = COEX_H2C69_WL_LEAKAP;
2287 		para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */
2288 		rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
2289 		coex_stat->wl_slot_extend = true;
2290 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2291 	} else {
2292 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2293 
2294 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2295 
2296 		rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2297 	}
2298 
2299 	rtw_coex_update_wl_ch_info(rtwdev, type);
2300 }
2301 
rtw_coex_bt_info_notify(struct rtw_dev * rtwdev,u8 * buf,u8 length)2302 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2303 {
2304 	struct rtw_coex *coex = &rtwdev->coex;
2305 	struct rtw_coex_stat *coex_stat = &coex->stat;
2306 	struct rtw_chip_info *chip = rtwdev->chip;
2307 	unsigned long bt_relink_time;
2308 	u8 i, rsp_source = 0, type;
2309 	bool inq_page = false;
2310 
2311 	rsp_source = buf[0] & 0xf;
2312 	if (rsp_source >= COEX_BTINFO_SRC_MAX)
2313 		rsp_source = COEX_BTINFO_SRC_WL_FW;
2314 
2315 	if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2316 		coex_stat->bt_iqk_state = buf[1];
2317 		if (coex_stat->bt_iqk_state == 1)
2318 			coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2319 		else if (coex_stat->bt_iqk_state == 2)
2320 			coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2321 
2322 		return;
2323 	}
2324 
2325 	if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2326 		rtw_coex_monitor_bt_enable(rtwdev);
2327 		if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2328 			coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2329 			rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2330 		}
2331 		return;
2332 	}
2333 
2334 	if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2335 	    rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2336 		if (coex_stat->bt_disabled) {
2337 			coex_stat->bt_disabled = false;
2338 			coex_stat->bt_reenable = true;
2339 			ieee80211_queue_delayed_work(rtwdev->hw,
2340 						     &coex->bt_reenable_work,
2341 						     15 * HZ);
2342 		}
2343 	}
2344 
2345 	for (i = 0; i < length; i++) {
2346 		if (i < COEX_BTINFO_LENGTH_MAX)
2347 			coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2348 		else
2349 			break;
2350 	}
2351 
2352 	if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2353 		rtw_coex_update_bt_link_info(rtwdev);
2354 		rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2355 		return;
2356 	}
2357 
2358 	/* get the same info from bt, skip it */
2359 	if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2360 	    coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2361 	    coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2362 	    coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2363 	    coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2364 	    coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
2365 		return;
2366 
2367 	coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2368 	coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2369 	coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2370 	coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2371 	coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2372 	coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2373 
2374 	/* 0xff means BT is under WHCK test */
2375 	coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2376 
2377 	inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2378 
2379 	if (inq_page != coex_stat->bt_inq_page) {
2380 		cancel_delayed_work_sync(&coex->bt_remain_work);
2381 		coex_stat->bt_inq_page = inq_page;
2382 
2383 		if (inq_page)
2384 			coex_stat->bt_inq_remain = true;
2385 		else
2386 			ieee80211_queue_delayed_work(rtwdev->hw,
2387 						     &coex->bt_remain_work,
2388 						     4 * HZ);
2389 	}
2390 	coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
2391 	coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
2392 	if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
2393 		coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
2394 
2395 	coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
2396 	coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
2397 	if (coex_stat->bt_inq)
2398 		coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
2399 
2400 	coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
2401 	if (coex_stat->bt_page) {
2402 		coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
2403 		if (coex_stat->wl_linkscan_proc ||
2404 		    coex_stat->wl_hi_pri_task1 ||
2405 		    coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
2406 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
2407 		else
2408 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2409 	} else {
2410 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2411 	}
2412 
2413 	/* unit: % (value-100 to translate to unit: dBm in coex info) */
2414 	if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
2415 		coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
2416 	} else { /* original unit: dbm -> unit: % ->  value-100 in coex info */
2417 		if (coex_stat->bt_info_hb0 <= 127)
2418 			coex_stat->bt_rssi = 100;
2419 		else if (256 - coex_stat->bt_info_hb0 <= 100)
2420 			coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
2421 		else
2422 			coex_stat->bt_rssi = 0;
2423 	}
2424 
2425 	coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
2426 	if (coex_stat->bt_info_hb1 & BIT(1))
2427 		coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
2428 
2429 	if (coex_stat->bt_info_hb1 & BIT(2)) {
2430 		coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
2431 		coex_stat->bt_setup_link = true;
2432 		if (coex_stat->bt_reenable)
2433 			bt_relink_time = 6 * HZ;
2434 		else
2435 			bt_relink_time = 2 * HZ;
2436 
2437 		ieee80211_queue_delayed_work(rtwdev->hw,
2438 					     &coex->bt_relink_work,
2439 					     bt_relink_time);
2440 	}
2441 
2442 	if (coex_stat->bt_info_hb1 & BIT(3))
2443 		coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
2444 
2445 	coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
2446 	coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
2447 	if (coex_stat->bt_info_hb1 & BIT(6))
2448 		coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
2449 
2450 	coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
2451 	/* resend wifi info to bt, it is reset and lost the info */
2452 	if ((coex_stat->bt_info_hb1 & BIT(1))) {
2453 		if (coex_stat->wl_connected)
2454 			type = COEX_MEDIA_CONNECT;
2455 		else
2456 			type = COEX_MEDIA_DISCONNECT;
2457 		rtw_coex_update_wl_ch_info(rtwdev, type);
2458 	}
2459 
2460 	/* if ignore_wlan_act && not set_up_link */
2461 	if ((coex_stat->bt_info_hb1 & BIT(3)) &&
2462 	    (!(coex_stat->bt_info_hb1 & BIT(2))))
2463 		rtw_coex_ignore_wlan_act(rtwdev, false);
2464 
2465 	coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
2466 	if (coex_stat->bt_info_hb2 & BIT(1))
2467 		coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
2468 
2469 	coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
2470 	coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
2471 	coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
2472 	coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
2473 	if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
2474 		coex_stat->bt_418_hid_exist = true;
2475 	else if (coex_stat->bt_hid_pair_num == 0)
2476 		coex_stat->bt_418_hid_exist = false;
2477 
2478 	if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
2479 		coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
2480 	else
2481 		coex_stat->bt_a2dp_bitpool = 0;
2482 
2483 	coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
2484 
2485 	rtw_coex_update_bt_link_info(rtwdev);
2486 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2487 }
2488 
rtw_coex_wl_fwdbginfo_notify(struct rtw_dev * rtwdev,u8 * buf,u8 length)2489 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2490 {
2491 	struct rtw_coex *coex = &rtwdev->coex;
2492 	struct rtw_coex_stat *coex_stat = &coex->stat;
2493 	u8 val;
2494 	int i;
2495 
2496 	if (WARN(length < 8, "invalid wl info c2h length\n"))
2497 		return;
2498 
2499 	if (buf[0] != 0x08)
2500 		return;
2501 
2502 	for (i = 1; i < 8; i++) {
2503 		val = coex_stat->wl_fw_dbg_info_pre[i];
2504 		if (buf[i] >= val)
2505 			coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
2506 		else
2507 			coex_stat->wl_fw_dbg_info[i] = val - buf[i];
2508 
2509 		coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
2510 	}
2511 
2512 	coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
2513 	rtw_coex_wl_ccklock_action(rtwdev);
2514 	rtw_coex_wl_ccklock_detect(rtwdev);
2515 }
2516 
rtw_coex_wl_status_change_notify(struct rtw_dev * rtwdev)2517 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
2518 {
2519 	struct rtw_coex *coex = &rtwdev->coex;
2520 
2521 	if (coex->stop_dm)
2522 		return;
2523 
2524 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2525 }
2526 
rtw_coex_bt_relink_work(struct work_struct * work)2527 void rtw_coex_bt_relink_work(struct work_struct *work)
2528 {
2529 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2530 					      coex.bt_relink_work.work);
2531 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2532 
2533 	mutex_lock(&rtwdev->mutex);
2534 	coex_stat->bt_setup_link = false;
2535 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2536 	mutex_unlock(&rtwdev->mutex);
2537 }
2538 
rtw_coex_bt_reenable_work(struct work_struct * work)2539 void rtw_coex_bt_reenable_work(struct work_struct *work)
2540 {
2541 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2542 					      coex.bt_reenable_work.work);
2543 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2544 
2545 	mutex_lock(&rtwdev->mutex);
2546 	coex_stat->bt_reenable = false;
2547 	mutex_unlock(&rtwdev->mutex);
2548 }
2549 
rtw_coex_defreeze_work(struct work_struct * work)2550 void rtw_coex_defreeze_work(struct work_struct *work)
2551 {
2552 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2553 					      coex.defreeze_work.work);
2554 	struct rtw_coex *coex = &rtwdev->coex;
2555 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2556 
2557 	mutex_lock(&rtwdev->mutex);
2558 	coex->freeze = false;
2559 	coex_stat->wl_hi_pri_task1 = false;
2560 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2561 	mutex_unlock(&rtwdev->mutex);
2562 }
2563 
rtw_coex_wl_remain_work(struct work_struct * work)2564 void rtw_coex_wl_remain_work(struct work_struct *work)
2565 {
2566 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2567 					      coex.wl_remain_work.work);
2568 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2569 
2570 	mutex_lock(&rtwdev->mutex);
2571 	coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
2572 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2573 	mutex_unlock(&rtwdev->mutex);
2574 }
2575 
rtw_coex_bt_remain_work(struct work_struct * work)2576 void rtw_coex_bt_remain_work(struct work_struct *work)
2577 {
2578 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2579 					      coex.bt_remain_work.work);
2580 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2581 
2582 	mutex_lock(&rtwdev->mutex);
2583 	coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
2584 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
2585 	mutex_unlock(&rtwdev->mutex);
2586 }
2587 
2588 #ifdef CONFIG_RTW88_DEBUGFS
2589 #define INFO_SIZE	80
2590 
2591 #define case_BTINFO(src) \
2592 	case COEX_BTINFO_SRC_##src: return #src
2593 
rtw_coex_get_bt_info_src_string(u8 bt_info_src)2594 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
2595 {
2596 	switch (bt_info_src) {
2597 	case_BTINFO(WL_FW);
2598 	case_BTINFO(BT_RSP);
2599 	case_BTINFO(BT_ACT);
2600 	default:
2601 		return "Unknown";
2602 	}
2603 }
2604 
2605 #define case_RSN(src) \
2606 	case COEX_RSN_##src: return #src
2607 
rtw_coex_get_reason_string(u8 reason)2608 static const char *rtw_coex_get_reason_string(u8 reason)
2609 {
2610 	switch (reason) {
2611 	case_RSN(2GSCANSTART);
2612 	case_RSN(5GSCANSTART);
2613 	case_RSN(SCANFINISH);
2614 	case_RSN(2GSWITCHBAND);
2615 	case_RSN(5GSWITCHBAND);
2616 	case_RSN(2GCONSTART);
2617 	case_RSN(5GCONSTART);
2618 	case_RSN(2GCONFINISH);
2619 	case_RSN(5GCONFINISH);
2620 	case_RSN(2GMEDIA);
2621 	case_RSN(5GMEDIA);
2622 	case_RSN(MEDIADISCON);
2623 	case_RSN(BTINFO);
2624 	case_RSN(LPS);
2625 	case_RSN(WLSTATUS);
2626 	default:
2627 		return "Unknown";
2628 	}
2629 }
2630 
rtw_coex_addr_info(struct rtw_dev * rtwdev,const struct rtw_reg_domain * reg,char addr_info[],int n)2631 static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
2632 			      const struct rtw_reg_domain *reg,
2633 			      char addr_info[], int n)
2634 {
2635 	const char *rf_prefix = "";
2636 	const char *sep = n == 0 ? "" : "/ ";
2637 	int ffs, fls;
2638 	int max_fls;
2639 
2640 	if (INFO_SIZE - n <= 0)
2641 		return 0;
2642 
2643 	switch (reg->domain) {
2644 	case RTW_REG_DOMAIN_MAC32:
2645 		max_fls = 31;
2646 		break;
2647 	case RTW_REG_DOMAIN_MAC16:
2648 		max_fls = 15;
2649 		break;
2650 	case RTW_REG_DOMAIN_MAC8:
2651 		max_fls = 7;
2652 		break;
2653 	case RTW_REG_DOMAIN_RF_A:
2654 	case RTW_REG_DOMAIN_RF_B:
2655 		rf_prefix = "RF_";
2656 		max_fls = 19;
2657 		break;
2658 	default:
2659 		return 0;
2660 	}
2661 
2662 	ffs = __ffs(reg->mask);
2663 	fls = __fls(reg->mask);
2664 
2665 	if (ffs == 0 && fls == max_fls)
2666 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
2667 				 sep, rf_prefix, reg->addr);
2668 	else if (ffs == fls)
2669 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
2670 				 sep, rf_prefix, reg->addr, ffs);
2671 	else
2672 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
2673 				 sep, rf_prefix, reg->addr, fls, ffs);
2674 }
2675 
rtw_coex_val_info(struct rtw_dev * rtwdev,const struct rtw_reg_domain * reg,char val_info[],int n)2676 static int rtw_coex_val_info(struct rtw_dev *rtwdev,
2677 			     const struct rtw_reg_domain *reg,
2678 			     char val_info[], int n)
2679 {
2680 	const char *sep = n == 0 ? "" : "/ ";
2681 	u8 rf_path;
2682 
2683 	if (INFO_SIZE - n <= 0)
2684 		return 0;
2685 
2686 	switch (reg->domain) {
2687 	case RTW_REG_DOMAIN_MAC32:
2688 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2689 				 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
2690 	case RTW_REG_DOMAIN_MAC16:
2691 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2692 				 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
2693 	case RTW_REG_DOMAIN_MAC8:
2694 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2695 				 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
2696 	case RTW_REG_DOMAIN_RF_A:
2697 		rf_path = RF_PATH_A;
2698 		break;
2699 	case RTW_REG_DOMAIN_RF_B:
2700 		rf_path = RF_PATH_B;
2701 		break;
2702 	default:
2703 		return 0;
2704 	}
2705 
2706 	/* only RF go through here */
2707 	return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2708 			 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
2709 }
2710 
rtw_coex_set_coexinfo_hw(struct rtw_dev * rtwdev,struct seq_file * m)2711 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
2712 {
2713 	struct rtw_chip_info *chip = rtwdev->chip;
2714 	const struct rtw_reg_domain *reg;
2715 	char addr_info[INFO_SIZE];
2716 	int n_addr = 0;
2717 	char val_info[INFO_SIZE];
2718 	int n_val = 0;
2719 	int i;
2720 
2721 	for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
2722 		reg = &chip->coex_info_hw_regs[i];
2723 
2724 		n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
2725 		n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
2726 
2727 		if (reg->domain == RTW_REG_DOMAIN_NL) {
2728 			seq_printf(m, "%-40s = %s\n", addr_info, val_info);
2729 			n_addr = 0;
2730 			n_val = 0;
2731 		}
2732 	}
2733 
2734 	if (n_addr != 0 && n_val != 0)
2735 		seq_printf(m, "%-40s = %s\n", addr_info, val_info);
2736 }
2737 
rtw_coex_get_bt_reg(struct rtw_dev * rtwdev,u8 type,u16 addr,u16 * val)2738 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
2739 				u8 type, u16 addr, u16 *val)
2740 {
2741 	struct rtw_coex_info_req req = {0};
2742 	struct sk_buff *skb;
2743 	__le16 le_addr;
2744 	u8 *payload;
2745 
2746 	le_addr = cpu_to_le16(addr);
2747 	req.op_code = BT_MP_INFO_OP_READ_REG;
2748 	req.para1 = type;
2749 	req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
2750 	req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
2751 	skb = rtw_coex_info_request(rtwdev, &req);
2752 	if (!skb) {
2753 		*val = 0xeaea;
2754 		return false;
2755 	}
2756 
2757 	payload = get_payload_from_coex_resp(skb);
2758 	*val = GET_COEX_RESP_BT_REG_VAL(payload);
2759 
2760 	return true;
2761 }
2762 
rtw_coex_get_bt_patch_version(struct rtw_dev * rtwdev,u32 * patch_version)2763 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
2764 					  u32 *patch_version)
2765 {
2766 	struct rtw_coex_info_req req = {0};
2767 	struct sk_buff *skb;
2768 	u8 *payload;
2769 	bool ret = false;
2770 
2771 	req.op_code = BT_MP_INFO_OP_PATCH_VER;
2772 	skb = rtw_coex_info_request(rtwdev, &req);
2773 	if (!skb)
2774 		goto out;
2775 
2776 	payload = get_payload_from_coex_resp(skb);
2777 	*patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
2778 	ret = true;
2779 
2780 out:
2781 	return ret;
2782 }
2783 
rtw_coex_get_bt_supported_version(struct rtw_dev * rtwdev,u32 * supported_version)2784 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
2785 					      u32 *supported_version)
2786 {
2787 	struct rtw_coex_info_req req = {0};
2788 	struct sk_buff *skb;
2789 	u8 *payload;
2790 	bool ret = false;
2791 
2792 	req.op_code = BT_MP_INFO_OP_SUPP_VER;
2793 	skb = rtw_coex_info_request(rtwdev, &req);
2794 	if (!skb)
2795 		goto out;
2796 
2797 	payload = get_payload_from_coex_resp(skb);
2798 	*supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
2799 	ret = true;
2800 
2801 out:
2802 	return ret;
2803 }
2804 
rtw_coex_get_bt_supported_feature(struct rtw_dev * rtwdev,u32 * supported_feature)2805 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
2806 					      u32 *supported_feature)
2807 {
2808 	struct rtw_coex_info_req req = {0};
2809 	struct sk_buff *skb;
2810 	u8 *payload;
2811 	bool ret = false;
2812 
2813 	req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
2814 	skb = rtw_coex_info_request(rtwdev, &req);
2815 	if (!skb)
2816 		goto out;
2817 
2818 	payload = get_payload_from_coex_resp(skb);
2819 	*supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
2820 	ret = true;
2821 
2822 out:
2823 	return ret;
2824 }
2825 
2826 struct rtw_coex_sta_stat_iter_data {
2827 	struct rtw_vif *rtwvif;
2828 	struct seq_file *file;
2829 };
2830 
rtw_coex_sta_stat_iter(void * data,struct ieee80211_sta * sta)2831 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
2832 {
2833 	struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
2834 	struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
2835 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
2836 	struct seq_file *m = sta_iter_data->file;
2837 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
2838 	u8 rssi;
2839 
2840 	if (si->vif != vif)
2841 		return;
2842 
2843 	rssi = ewma_rssi_read(&si->avg_rssi);
2844 	seq_printf(m, "\tPeer %3d\n", si->mac_id);
2845 	seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
2846 	seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
2847 }
2848 
2849 struct rtw_coex_vif_stat_iter_data {
2850 	struct rtw_dev *rtwdev;
2851 	struct seq_file *file;
2852 };
2853 
rtw_coex_vif_stat_iter(void * data,u8 * mac,struct ieee80211_vif * vif)2854 static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
2855 				   struct ieee80211_vif *vif)
2856 {
2857 	struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
2858 	struct rtw_coex_sta_stat_iter_data sta_iter_data;
2859 	struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
2860 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
2861 	struct seq_file *m = vif_iter_data->file;
2862 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
2863 
2864 	seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
2865 	seq_printf(m, "\t%-32s = %d\n",
2866 		   "Beacon interval", bss_conf->beacon_int);
2867 	seq_printf(m, "\t%-32s = %d\n",
2868 		   "Network Type", rtwvif->net_type);
2869 
2870 	sta_iter_data.rtwvif = rtwvif;
2871 	sta_iter_data.file = m;
2872 	rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
2873 				&sta_iter_data);
2874 }
2875 
rtw_coex_display_coex_info(struct rtw_dev * rtwdev,struct seq_file * m)2876 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
2877 {
2878 	struct rtw_chip_info *chip = rtwdev->chip;
2879 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
2880 	struct rtw_coex *coex = &rtwdev->coex;
2881 	struct rtw_coex_stat *coex_stat = &coex->stat;
2882 	struct rtw_coex_dm *coex_dm = &coex->dm;
2883 	struct rtw_hal *hal = &rtwdev->hal;
2884 	struct rtw_efuse *efuse = &rtwdev->efuse;
2885 	struct rtw_fw_state *fw = &rtwdev->fw;
2886 	struct rtw_coex_vif_stat_iter_data vif_iter_data;
2887 	u8 reason = coex_dm->reason;
2888 	u8 sys_lte;
2889 	u16 score_board_WB, score_board_BW;
2890 	u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
2891 	u32 lte_coex, bt_coex;
2892 	u32 bt_hi_pri, bt_lo_pri;
2893 	int i;
2894 
2895 	score_board_BW = rtw_coex_read_scbd(rtwdev);
2896 	score_board_WB = coex_stat->score_board;
2897 	wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0);
2898 	wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4);
2899 	wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8);
2900 	wl_reg_6cc = rtw_read32(rtwdev, 0x6cc);
2901 	wl_reg_778 = rtw_read32(rtwdev, 0x778);
2902 	bt_hi_pri = rtw_read32(rtwdev, 0x770);
2903 	bt_lo_pri = rtw_read32(rtwdev, 0x774);
2904 	rtw_write8(rtwdev, 0x76e, 0xc);
2905 	sys_lte = rtw_read8(rtwdev, 0x73);
2906 	lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
2907 	bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
2908 
2909 	if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
2910 		rtw_coex_get_bt_supported_version(rtwdev,
2911 				&coex_stat->bt_supported_version);
2912 		rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
2913 		rtw_coex_get_bt_supported_feature(rtwdev,
2914 				&coex_stat->bt_supported_feature);
2915 		rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
2916 		rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
2917 
2918 		if (coex_stat->patch_ver != 0)
2919 			coex_stat->bt_mailbox_reply = true;
2920 	}
2921 
2922 	seq_printf(m, "**********************************************\n");
2923 	seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
2924 	seq_printf(m, "**********************************************\n");
2925 	seq_printf(m, "%-40s = %s/ %d\n",
2926 		   "Mech/ RFE",
2927 		   efuse->share_ant ? "Shared" : "Non-Shared",
2928 		   efuse->rfe_option);
2929 	seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
2930 		   "Coex Ver/ BT Dez/ BT Rpt",
2931 		   chip->coex_para_ver, chip->bt_desired_ver,
2932 		   coex_stat->bt_supported_version,
2933 		   coex_stat->bt_disabled ? "(BT disabled)" :
2934 		   coex_stat->bt_supported_version >= chip->bt_desired_ver ?
2935 		   "(Match)" : "(Mismatch)");
2936 	seq_printf(m, "%-40s = %s/ %u/ %d\n",
2937 		   "Role/ RoleSwCnt/ IgnWL/ Feature",
2938 		   coex_stat->bt_slave ? "Slave" : "Master",
2939 		   coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
2940 		   coex_dm->ignore_wl_act);
2941 	seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n",
2942 		   "WL FW/ BT FW/ KT",
2943 		   fw->version, fw->sub_version,
2944 		   coex_stat->patch_ver, coex_stat->kt_ver + 65);
2945 	seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
2946 		   "AFH Map",
2947 		   coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
2948 		   coex_dm->wl_ch_info[2], hal->current_channel);
2949 
2950 	seq_printf(m, "**********************************************\n");
2951 	seq_printf(m, "\t\tBT Status\n");
2952 	seq_printf(m, "**********************************************\n");
2953 	seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
2954 		   "BT status/ rssi/ retry/ pop",
2955 		   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
2956 		   coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
2957 		   coex_stat->bt_rssi - 100,
2958 		   coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
2959 		   coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
2960 	seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
2961 		   "Profiles",
2962 		   coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
2963 					       "A2DP sink," : "A2DP,") : "",
2964 		   coex_stat->bt_hfp_exist ? "HFP," : "",
2965 		   coex_stat->bt_hid_exist ?
2966 		   (coex_stat->bt_ble_exist ? "HID(RCU)," :
2967 		    coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
2968 		    "HID(2/18),") : "",
2969 		   coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
2970 		   "OPP," : "PAN," : "",
2971 		   coex_stat->bt_ble_voice ? "Voice," : "",
2972 		   coex_stat->bt_multi_link);
2973 	seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
2974 		   "Reinit/ Relink/ IgnWl/ Feature",
2975 		   coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
2976 		   coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
2977 		   coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
2978 		   coex_stat->bt_supported_feature);
2979 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
2980 		   "Page/ Inq/ iqk/ iqk fail",
2981 		   coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
2982 		   coex_stat->cnt_bt[COEX_CNT_BT_INQ],
2983 		   coex_stat->cnt_bt[COEX_CNT_BT_IQK],
2984 		   coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
2985 	seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
2986 		   "0xae/ 0xac/ score board (W->B)/ (B->W)",
2987 		   coex_stat->bt_reg_vendor_ae,
2988 		   coex_stat->bt_reg_vendor_ac,
2989 		   score_board_WB, score_board_BW);
2990 	seq_printf(m, "%-40s = %u/%u, %u/%u\n",
2991 		   "Hi-Pri TX/RX, Lo-Pri TX/RX",
2992 		   bt_hi_pri & 0xffff, bt_hi_pri >> 16,
2993 		   bt_lo_pri & 0xffff, bt_lo_pri >> 16);
2994 	for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
2995 		seq_printf(m, "%-40s = %7ph\n",
2996 			   rtw_coex_get_bt_info_src_string(i),
2997 			   coex_stat->bt_info_c2h[i]);
2998 
2999 	seq_printf(m, "**********************************************\n");
3000 	seq_printf(m, "\t\tWiFi Status\n");
3001 	seq_printf(m, "**********************************************\n");
3002 	seq_printf(m, "%-40s = %d\n",
3003 		   "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
3004 	seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
3005 		   "G_busy/ TX/ RX",
3006 		   coex_stat->wl_gl_busy,
3007 		   rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
3008 	seq_printf(m, "%-40s = %u/ %u/ %u\n",
3009 		   "IPS/ Low Power/ PS mode",
3010 		   test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
3011 		   test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
3012 		   rtwdev->lps_conf.mode);
3013 
3014 	vif_iter_data.rtwdev = rtwdev;
3015 	vif_iter_data.file = m;
3016 	rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
3017 
3018 	seq_printf(m, "**********************************************\n");
3019 	seq_printf(m, "\t\tMechanism\n");
3020 	seq_printf(m, "**********************************************\n");
3021 	seq_printf(m, "%-40s = %5ph (case-%d)\n",
3022 		   "TDMA",
3023 		   coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
3024 	seq_printf(m, "%-40s = %d\n",
3025 		   "Timer base", coex_stat->tdma_timer_base);
3026 	seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n",
3027 		   "Table/ 0x6c0/ 0x6c4/ 0x6c8",
3028 		   coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
3029 	seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n",
3030 		   "0x778/ 0x6cc/ Reason",
3031 		   wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason));
3032 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
3033 		   "Null All/ Retry/ Ack/ BT Empty/ BT Late",
3034 		   coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
3035 		   coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
3036 		   coex_stat->wl_fw_dbg_info[5]);
3037 	seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
3038 		   "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
3039 		   coex_stat->wl_fw_dbg_info[6],
3040 		   coex_stat->wl_fw_dbg_info[7],
3041 		   coex_stat->wl_slot_extend ? "Yes" : "No",
3042 		   coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
3043 
3044 	seq_printf(m, "**********************************************\n");
3045 	seq_printf(m, "\t\tHW setting\n");
3046 	seq_printf(m, "**********************************************\n");
3047 	seq_printf(m, "%-40s = %s/ %s\n",
3048 		   "LTE Coex/ Path Owner",
3049 		   lte_coex & BIT(7) ? "ON" : "OFF",
3050 		   sys_lte & BIT(2) ? "WL" : "BT");
3051 	seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
3052 		   "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
3053 		   lte_coex & BIT(12) ? "SW" : "HW",
3054 		   lte_coex & BIT(8) ? "SW" : "HW",
3055 		   lte_coex & BIT(14) ? "SW" : "HW",
3056 		   lte_coex & BIT(10) ? "SW" : "HW",
3057 		   sys_lte & BIT(3) ? "On" : "Off");
3058 	seq_printf(m, "%-40s = %lu/ %lu\n",
3059 		   "GNT_WL/ GNT_BT",
3060 		   (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
3061 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3062 		   "CRC OK CCK/ OFDM/ HT/ VHT",
3063 		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3064 		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3065 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3066 		   "CRC ERR CCK/ OFDM/ HT/ VHT",
3067 		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3068 		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3069 	seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
3070 		   "HiPr/ Locking/ Locked/ Noisy",
3071 		   coex_stat->wl_hi_pri_task1 ? "Y" : "N",
3072 		   coex_stat->wl_cck_lock ? "Y" : "N",
3073 		   coex_stat->wl_cck_lock_ever ? "Y" : "N",
3074 		   coex_stat->wl_noisy_level);
3075 
3076 	rtw_coex_set_coexinfo_hw(rtwdev, m);
3077 }
3078 #endif /* CONFIG_RTW88_DEBUGFS */
3079