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