4160 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause2/* Copyright(c) 2018-2019 Realtek Corporation3 */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#include "phy.h"12 13static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,14 u8 rssi, u8 rssi_thresh)15{16 const struct rtw_chip_info *chip = rtwdev->chip;17 u8 tol = chip->rssi_tolerance;18 u8 next_state;19 20 if (pre_state == COEX_RSSI_STATE_LOW ||21 pre_state == COEX_RSSI_STATE_STAY_LOW) {22 if (rssi >= (rssi_thresh + tol))23 next_state = COEX_RSSI_STATE_HIGH;24 else25 next_state = COEX_RSSI_STATE_STAY_LOW;26 } else {27 if (rssi < rssi_thresh)28 next_state = COEX_RSSI_STATE_LOW;29 else30 next_state = COEX_RSSI_STATE_STAY_HIGH;31 }32 33 return next_state;34}35 36static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,37 bool tx_limit_en, bool ampdu_limit_en)38{39 const struct rtw_chip_info *chip = rtwdev->chip;40 struct rtw_coex *coex = &rtwdev->coex;41 struct rtw_coex_stat *coex_stat = &coex->stat;42 u8 num_of_active_port = 1;43 44 if (!chip->scbd_support)45 return;46 47 /* force max tx retry limit = 8 */48 if (coex_stat->wl_tx_limit_en == tx_limit_en &&49 coex_stat->wl_ampdu_limit_en == ampdu_limit_en)50 return;51 52 if (!coex_stat->wl_tx_limit_en) {53 coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);54 coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);55 coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);56 }57 58 if (!coex_stat->wl_ampdu_limit_en)59 coex_stat->ampdu_max_time =60 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);61 62 coex_stat->wl_tx_limit_en = tx_limit_en;63 coex_stat->wl_ampdu_limit_en = ampdu_limit_en;64 65 if (tx_limit_en) {66 /* set BT polluted packet on for tx rate adaptive,67 * not including tx retry broken by PTA68 */69 rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);70 71 /* set queue life time to avoid can't reach tx retry limit72 * if tx is always broken by GNT_BT73 */74 if (num_of_active_port <= 1)75 rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);76 rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);77 78 /* auto rate fallback step within 8 retries */79 rtw_write32(rtwdev, REG_DARFRC, 0x1000000);80 rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);81 } else {82 rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);83 rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);84 85 rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);86 rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);87 rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);88 }89 90 if (ampdu_limit_en)91 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);92 else93 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,94 coex_stat->ampdu_max_time);95}96 97static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)98{99 struct rtw_coex *coex = &rtwdev->coex;100 struct rtw_coex_dm *coex_dm = &coex->dm;101 bool tx_limit = false;102 bool tx_agg_ctrl = false;103 104 if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) {105 tx_limit = true;106 tx_agg_ctrl = true;107 }108 109 rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);110}111 112static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev)113{114 struct rtw_coex *coex = &rtwdev->coex;115 struct rtw_coex_dm *coex_dm = &coex->dm;116 struct rtw_coex_stat *coex_stat = &coex->stat;117 struct rtw_efuse *efuse = &rtwdev->efuse;118 u8 bt_rssi;119 u8 ant_distance = 10;120 121 if (coex_stat->bt_disabled)122 return false;123 124 if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy)125 return false;126 127 if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2)128 return true;129 130 /* ant_distance = 5 ~ 40 */131 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) &&132 COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0]))133 return true;134 135 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)136 bt_rssi = coex_dm->bt_rssi_state[0];137 else138 bt_rssi = coex_dm->bt_rssi_state[1];139 140 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&141 COEX_RSSI_HIGH(bt_rssi) &&142 coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)143 return true;144 145 return false;146}147 148static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable)149{150 struct rtw_coex *coex = &rtwdev->coex;151 struct rtw_coex_stat *coex_stat = &coex->stat;152 u8 para[6] = {0};153 154 para[0] = COEX_H2C69_WL_LEAKAP;155 para[1] = PARA1_H2C69_DIS_5MS;156 157 if (enable)158 para[1] = PARA1_H2C69_EN_5MS;159 else160 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;161 162 coex_stat->wl_slot_extend = enable;163 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);164}165 166static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)167{168 struct rtw_coex *coex = &rtwdev->coex;169 struct rtw_coex_stat *coex_stat = &coex->stat;170 171 if (coex->manual_control || coex->stop_dm)172 return;173 174 175 if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {176 rtw_dbg(rtwdev, RTW_DBG_COEX,177 "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");178 rtw_coex_wl_slot_extend(rtwdev, false);179 return;180 }181 182 if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&183 !coex_stat->wl_cck_lock_ever) {184 if (coex_stat->wl_fw_dbg_info[7] <= 5)185 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;186 else187 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;188 189 rtw_dbg(rtwdev, RTW_DBG_COEX,190 "[BTCoex], 5ms WL slot extend cnt = %d!!\n",191 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]);192 193 if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {194 rtw_dbg(rtwdev, RTW_DBG_COEX,195 "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");196 rtw_coex_wl_slot_extend(rtwdev, false);197 }198 } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {199 rtw_dbg(rtwdev, RTW_DBG_COEX,200 "[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n");201 202 rtw_coex_wl_slot_extend(rtwdev, true);203 }204}205 206static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)207{208 struct rtw_coex *coex = &rtwdev->coex;209 struct rtw_coex_stat *coex_stat = &coex->stat;210 struct rtw_coex_dm *coex_dm = &coex->dm;211 212 bool is_cck_lock_rate = false;213 214 if (coex_stat->wl_coex_mode != COEX_WLINK_2G1PORT &&215 coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)216 return;217 218 if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE ||219 coex_stat->bt_setup_link) {220 coex_stat->wl_cck_lock = false;221 coex_stat->wl_cck_lock_pre = false;222 return;223 }224 225 if (coex_stat->wl_rx_rate <= COEX_CCK_2 ||226 coex_stat->wl_rts_rx_rate <= COEX_CCK_2)227 is_cck_lock_rate = true;228 229 if (coex_stat->wl_connected && coex_stat->wl_gl_busy &&230 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&231 (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY ||232 coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY ||233 coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) {234 if (is_cck_lock_rate) {235 coex_stat->wl_cck_lock = true;236 237 rtw_dbg(rtwdev, RTW_DBG_COEX,238 "[BTCoex], cck locking...\n");239 240 } else {241 coex_stat->wl_cck_lock = false;242 243 rtw_dbg(rtwdev, RTW_DBG_COEX,244 "[BTCoex], cck unlock...\n");245 }246 } else {247 coex_stat->wl_cck_lock = false;248 }249 250 /* CCK lock identification */251 if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre)252 ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work,253 3 * HZ);254 255 coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock;256}257 258static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)259{260 struct rtw_coex *coex = &rtwdev->coex;261 struct rtw_coex_stat *coex_stat = &coex->stat;262 struct rtw_dm_info *dm_info = &rtwdev->dm_info;263 u32 cnt_cck;264 bool wl_cck_lock = false;265 266 /* wifi noisy environment identification */267 cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;268 269 if (!coex_stat->wl_gl_busy && !wl_cck_lock) {270 if (cnt_cck > 250) {271 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)272 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;273 274 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {275 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;276 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;277 }278 } else if (cnt_cck < 100) {279 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)280 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;281 282 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {283 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;284 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;285 }286 } else {287 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)288 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;289 290 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {291 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;292 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;293 }294 }295 296 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)297 coex_stat->wl_noisy_level = 2;298 else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)299 coex_stat->wl_noisy_level = 1;300 else301 coex_stat->wl_noisy_level = 0;302 303 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n",304 coex_stat->wl_noisy_level);305 }306}307 308static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)309{310 struct rtw_coex *coex = &rtwdev->coex;311 struct rtw_coex_stat *coex_stat = &coex->stat;312 u8 para[2] = {0};313 u8 times;314 u16 tbtt_interval = coex_stat->wl_beacon_interval;315 316 if (coex_stat->tdma_timer_base == type)317 return;318 319 coex_stat->tdma_timer_base = type;320 321 para[0] = COEX_H2C69_TDMA_SLOT;322 323 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n",324 tbtt_interval);325 326 if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) {327 para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */328 } else if (tbtt_interval < 80 && tbtt_interval > 0) {329 times = 100 / tbtt_interval;330 if (100 % tbtt_interval != 0)331 times++;332 333 para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times);334 } else if (tbtt_interval >= 180) {335 times = tbtt_interval / 100;336 if (tbtt_interval % 100 <= 80)337 times--;338 339 para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) |340 FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1);341 } else {342 para[1] = PARA1_H2C69_TDMA_2SLOT;343 }344 345 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);346 347 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n",348 __func__, para[1]);349 350 /* no 5ms_wl_slot_extend for 4-slot mode */351 if (coex_stat->tdma_timer_base == 3)352 rtw_coex_wl_ccklock_action(rtwdev);353}354 355static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,356 u8 data)357{358 u32 addr;359 360 addr = REG_BT_COEX_TABLE_H + (bitmap / 8);361 bitmap = bitmap % 8;362 363 rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);364}365 366void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)367{368 const struct rtw_chip_info *chip = rtwdev->chip;369 struct rtw_coex *coex = &rtwdev->coex;370 struct rtw_coex_stat *coex_stat = &coex->stat;371 u16 val = 0x2;372 373 if (!chip->scbd_support)374 return;375 376 val |= coex_stat->score_board;377 378 /* for 8822b, scbd[10] is CQDDR on379 * for 8822c, scbd[10] is no fix 2M380 */381 if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {382 if (set)383 val &= ~COEX_SCBD_FIX2M;384 else385 val |= COEX_SCBD_FIX2M;386 } else {387 if (set)388 val |= bitpos;389 else390 val &= ~bitpos;391 }392 393 if (val != coex_stat->score_board) {394 coex_stat->score_board = val;395 val |= BIT_BT_INT_EN;396 rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);397 }398}399EXPORT_SYMBOL(rtw_coex_write_scbd);400 401static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)402{403 const struct rtw_chip_info *chip = rtwdev->chip;404 405 if (!chip->scbd_support)406 return 0;407 408 return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);409}410 411static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)412{413 const struct rtw_chip_info *chip = rtwdev->chip;414 struct rtw_coex *coex = &rtwdev->coex;415 struct rtw_coex_stat *coex_stat = &coex->stat;416 struct rtw_coex_rfe *coex_rfe = &coex->rfe;417 u8 cnt = 0;418 u32 wait_cnt;419 bool btk, wlk;420 421 if (coex_rfe->wlg_at_btg && chip->scbd_support &&422 coex_stat->bt_iqk_state != 0xff) {423 rtw_dbg(rtwdev, RTW_DBG_COEX,424 "[BTCoex], (Before Ant Setup) Delay by IQK\n");425 426 wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;427 do {428 /* BT RFK */429 btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);430 431 /* WL RFK */432 wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);433 434 if (!btk && !wlk)435 break;436 437 rtw_dbg(rtwdev, RTW_DBG_COEX,438 "[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n",439 wlk, btk);440 441 mdelay(COEX_MIN_DELAY);442 } while (++cnt < wait_cnt);443 444 if (cnt >= wait_cnt)445 coex_stat->bt_iqk_state = 0xff;446 }447}448 449static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)450{451 struct rtw_coex *coex = &rtwdev->coex;452 struct rtw_coex_stat *coex_stat = &coex->stat;453 454 if (coex_stat->bt_disabled)455 return;456 457 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);458 459 rtw_fw_query_bt_info(rtwdev);460}461 462static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)463{464 rtw_coex_set_gnt_fix(rtwdev);465}466 467static void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev)468{469 struct rtw_coex *coex = &rtwdev->coex;470 struct rtw_coex_stat *coex_stat = &coex->stat;471 u32 tmp;472 473 tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);474 coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, tmp);475 coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, tmp);476 477 tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);478 coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, tmp);479 coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, tmp);480 481 rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,482 BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);483 484 rtw_dbg(rtwdev, RTW_DBG_COEX,485 "[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n",486 coex_stat->hi_pri_rx, coex_stat->hi_pri_tx,487 coex_stat->lo_pri_rx, coex_stat->lo_pri_tx);488}489 490static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)491{492 const struct rtw_chip_info *chip = rtwdev->chip;493 struct rtw_coex *coex = &rtwdev->coex;494 struct rtw_coex_stat *coex_stat = &coex->stat;495 struct rtw_coex_dm *coex_dm = &coex->dm;496 bool bt_disabled = false;497 u16 score_board;498 499 if (chip->scbd_support) {500 score_board = rtw_coex_read_scbd(rtwdev);501 bt_disabled = !(score_board & COEX_SCBD_ONOFF);502 }503 504 if (coex_stat->bt_disabled != bt_disabled) {505 rtw_dbg(rtwdev, RTW_DBG_COEX,506 "[BTCoex], BT state changed (%d) -> (%d)\n",507 coex_stat->bt_disabled, bt_disabled);508 509 coex_stat->bt_disabled = bt_disabled;510 coex_stat->bt_ble_scan_type = 0;511 coex_dm->cur_bt_lna_lvl = 0;512 513 if (!coex_stat->bt_disabled) {514 coex_stat->bt_reenable = true;515 ieee80211_queue_delayed_work(rtwdev->hw,516 &coex->bt_reenable_work,517 15 * HZ);518 } else {519 coex_stat->bt_mailbox_reply = false;520 coex_stat->bt_reenable = false;521 }522 }523}524 525static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)526{527 const struct rtw_chip_info *chip = rtwdev->chip;528 struct rtw_coex *coex = &rtwdev->coex;529 struct rtw_coex_stat *coex_stat = &coex->stat;530 struct rtw_coex_dm *coex_dm = &coex->dm;531 struct rtw_traffic_stats *stats = &rtwdev->stats;532 bool is_5G = false;533 bool wl_busy = false;534 bool scan = false, link = false;535 int i;536 u8 rssi_state;537 u8 rssi_step;538 u8 rssi;539 540 scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);541 coex_stat->wl_connected = !!rtwdev->sta_cnt;542 543 wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);544 if (wl_busy != coex_stat->wl_gl_busy) {545 if (wl_busy)546 coex_stat->wl_gl_busy = true;547 else548 ieee80211_queue_delayed_work(rtwdev->hw,549 &coex->wl_remain_work,550 12 * HZ);551 }552 553 if (stats->tx_throughput > stats->rx_throughput)554 coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;555 else556 coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;557 558 if (scan || link || reason == COEX_RSN_2GCONSTART ||559 reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)560 coex_stat->wl_linkscan_proc = true;561 else562 coex_stat->wl_linkscan_proc = false;563 564 rtw_coex_wl_noisy_detect(rtwdev);565 566 for (i = 0; i < 4; i++) {567 rssi_state = coex_dm->wl_rssi_state[i];568 rssi_step = chip->wl_rssi_step[i];569 rssi = rtwdev->dm_info.min_rssi;570 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,571 rssi, rssi_step);572 coex_dm->wl_rssi_state[i] = rssi_state;573 }574 575 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||576 coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)577 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);578 else579 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);580 581 switch (reason) {582 case COEX_RSN_5GSCANSTART:583 case COEX_RSN_5GSWITCHBAND:584 case COEX_RSN_5GCONSTART:585 586 is_5G = true;587 break;588 case COEX_RSN_2GSCANSTART:589 case COEX_RSN_2GSWITCHBAND:590 case COEX_RSN_2GCONSTART:591 592 is_5G = false;593 break;594 default:595 if (rtwdev->hal.current_band_type == RTW_BAND_5G)596 is_5G = true;597 else598 is_5G = false;599 break;600 }601 602 coex->under_5g = is_5G;603}604 605static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)606{607 struct rtw_c2h_cmd *c2h;608 u32 pkt_offset;609 610 pkt_offset = *((u32 *)resp->cb);611 c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);612 613 return c2h->payload;614}615 616void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)617{618 struct rtw_coex *coex = &rtwdev->coex;619 u8 *payload = get_payload_from_coex_resp(skb);620 621 if (payload[0] != COEX_RESP_ACK_BY_WL_FW) {622 dev_kfree_skb_any(skb);623 return;624 }625 626 skb_queue_tail(&coex->queue, skb);627 wake_up(&coex->wait);628}629 630static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,631 struct rtw_coex_info_req *req)632{633 struct rtw_coex *coex = &rtwdev->coex;634 struct sk_buff *skb_resp = NULL;635 636 lockdep_assert_held(&rtwdev->mutex);637 638 rtw_fw_query_bt_mp_info(rtwdev, req);639 640 if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),641 COEX_REQUEST_TIMEOUT)) {642 rtw_err(rtwdev, "coex request time out\n");643 goto out;644 }645 646 skb_resp = skb_dequeue(&coex->queue);647 if (!skb_resp) {648 rtw_err(rtwdev, "failed to get coex info response\n");649 goto out;650 }651 652out:653 return skb_resp;654}655 656static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)657{658 struct rtw_coex_info_req req = {0};659 struct sk_buff *skb;660 u8 *payload;661 662 req.op_code = BT_MP_INFO_OP_SCAN_TYPE;663 skb = rtw_coex_info_request(rtwdev, &req);664 if (!skb)665 return false;666 667 payload = get_payload_from_coex_resp(skb);668 *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);669 dev_kfree_skb_any(skb);670 return true;671}672 673static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,674 u8 lna_constrain_level)675{676 struct rtw_coex_info_req req = {0};677 struct sk_buff *skb;678 679 req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;680 req.para1 = lna_constrain_level;681 skb = rtw_coex_info_request(rtwdev, &req);682 if (!skb)683 return false;684 685 dev_kfree_skb_any(skb);686 return true;687}688 689#define case_BTSTATUS(src) \690 case COEX_BTSTATUS_##src: return #src691 692static const char *rtw_coex_get_bt_status_string(u8 bt_status)693{694 switch (bt_status) {695 case_BTSTATUS(NCON_IDLE);696 case_BTSTATUS(CON_IDLE);697 case_BTSTATUS(INQ_PAGE);698 case_BTSTATUS(ACL_BUSY);699 case_BTSTATUS(SCO_BUSY);700 case_BTSTATUS(ACL_SCO_BUSY);701 default:702 return "Unknown";703 }704}705 706static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)707{708 const struct rtw_chip_info *chip = rtwdev->chip;709 struct rtw_coex *coex = &rtwdev->coex;710 struct rtw_coex_stat *coex_stat = &coex->stat;711 struct rtw_coex_dm *coex_dm = &coex->dm;712 u8 i;713 u8 rssi_state;714 u8 rssi_step;715 u8 rssi;716 717 /* update wl/bt rssi by btinfo */718 for (i = 0; i < COEX_RSSI_STEP; i++) {719 rssi_state = coex_dm->bt_rssi_state[i];720 rssi_step = chip->bt_rssi_step[i];721 rssi = coex_stat->bt_rssi;722 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi,723 rssi_step);724 coex_dm->bt_rssi_state[i] = rssi_state;725 }726 727 if (coex_stat->bt_ble_scan_en &&728 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {729 u8 scan_type;730 731 if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {732 coex_stat->bt_ble_scan_type = scan_type;733 if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)734 coex_stat->bt_init_scan = true;735 else736 coex_stat->bt_init_scan = false;737 }738 }739 740 coex_stat->bt_profile_num = 0;741 742 /* set link exist status */743 if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {744 coex_stat->bt_link_exist = false;745 coex_stat->bt_pan_exist = false;746 coex_stat->bt_a2dp_exist = false;747 coex_stat->bt_hid_exist = false;748 coex_stat->bt_hfp_exist = false;749 } else {750 /* connection exists */751 coex_stat->bt_link_exist = true;752 if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {753 coex_stat->bt_pan_exist = true;754 coex_stat->bt_profile_num++;755 } else {756 coex_stat->bt_pan_exist = false;757 }758 759 if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {760 coex_stat->bt_a2dp_exist = true;761 coex_stat->bt_profile_num++;762 } else {763 coex_stat->bt_a2dp_exist = false;764 }765 766 if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {767 coex_stat->bt_hid_exist = true;768 coex_stat->bt_profile_num++;769 } else {770 coex_stat->bt_hid_exist = false;771 }772 773 if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {774 coex_stat->bt_hfp_exist = true;775 coex_stat->bt_profile_num++;776 } else {777 coex_stat->bt_hfp_exist = false;778 }779 }780 781 if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {782 coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;783 } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {784 coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;785 coex_stat->bt_multi_link_remain = false;786 } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {787 coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;788 } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||789 (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {790 if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)791 coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;792 else793 coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;794 } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {795 coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;796 } else {797 coex_dm->bt_status = COEX_BTSTATUS_MAX;798 }799 800 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;801 802 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__,803 rtw_coex_get_bt_status_string(coex_dm->bt_status));804}805 806static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)807{808 const struct rtw_chip_info *chip = rtwdev->chip;809 struct rtw_efuse *efuse = &rtwdev->efuse;810 struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;811 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;812 u8 link = 0;813 u8 center_chan = 0;814 u8 bw;815 int i;816 817 bw = rtwdev->hal.current_band_width;818 819 if (type != COEX_MEDIA_DISCONNECT)820 center_chan = rtwdev->hal.current_channel;821 822 if (center_chan == 0 ||823 (efuse->share_ant && center_chan <= 14 &&824 coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)) {825 link = 0;826 center_chan = 0;827 bw = 0;828 } else if (center_chan <= 14) {829 link = 0x1;830 831 if (bw == RTW_CHANNEL_WIDTH_40)832 bw = chip->bt_afh_span_bw40;833 else834 bw = chip->bt_afh_span_bw20;835 } else if (chip->afh_5g_num > 1) {836 for (i = 0; i < chip->afh_5g_num; i++) {837 if (center_chan == chip->afh_5g[i].wl_5g_ch) {838 link = 0x3;839 center_chan = chip->afh_5g[i].bt_skip_ch;840 bw = chip->afh_5g[i].bt_skip_span;841 break;842 }843 }844 }845 846 coex_dm->wl_ch_info[0] = link;847 coex_dm->wl_ch_info[1] = center_chan;848 coex_dm->wl_ch_info[2] = bw;849 850 rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);851 rtw_dbg(rtwdev, RTW_DBG_COEX,852 "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link,853 center_chan, bw);854}855 856static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)857{858 struct rtw_coex *coex = &rtwdev->coex;859 struct rtw_coex_dm *coex_dm = &coex->dm;860 861 if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)862 return;863 864 coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;865 866 rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);867}868 869static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)870{871 struct rtw_coex *coex = &rtwdev->coex;872 struct rtw_coex_dm *coex_dm = &coex->dm;873 874 if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)875 return;876 877 coex_dm->cur_bt_lna_lvl = bt_lna_lvl;878 879 /* notify BT rx gain table changed */880 if (bt_lna_lvl < 7) {881 rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);882 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);883 } else {884 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);885 }886 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",887 __func__, bt_lna_lvl);888}889 890static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,891 struct coex_rf_para para)892{893 struct rtw_coex *coex = &rtwdev->coex;894 struct rtw_coex_stat *coex_stat = &coex->stat;895 u8 offset = 0;896 897 if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)898 offset = 3;899 900 rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);901 rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);902 rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);903 rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);904}905 906u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)907{908 u32 val;909 910 if (!ltecoex_read_reg(rtwdev, addr, &val)) {911 rtw_err(rtwdev, "failed to read indirect register\n");912 return 0;913 }914 915 return val;916}917EXPORT_SYMBOL(rtw_coex_read_indirect_reg);918 919void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,920 u32 mask, u32 val)921{922 u32 shift = __ffs(mask);923 u32 tmp;924 925 tmp = rtw_coex_read_indirect_reg(rtwdev, addr);926 tmp = (tmp & (~mask)) | ((val << shift) & mask);927 928 if (!ltecoex_reg_write(rtwdev, addr, tmp))929 rtw_err(rtwdev, "failed to write indirect register\n");930}931EXPORT_SYMBOL(rtw_coex_write_indirect_reg);932 933static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)934{935 const struct rtw_chip_info *chip = rtwdev->chip;936 const struct rtw_hw_reg *btg_reg = chip->btg_reg;937 938 if (wifi_control) {939 rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3,940 BIT_LTE_MUX_CTRL_PATH >> 24);941 if (btg_reg)942 rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);943 } else {944 rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3,945 BIT_LTE_MUX_CTRL_PATH >> 24);946 if (btg_reg)947 rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);948 }949}950 951static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)952{953 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);954 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);955}956 957static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)958{959 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);960 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);961}962 963static void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state)964{965 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;966 967 if (!force && state == coex_stat->wl_mimo_ps)968 return;969 970 coex_stat->wl_mimo_ps = state;971 972 rtw_set_txrx_1ss(rtwdev, state);973 974 rtw_coex_update_wl_ch_info(rtwdev, (u8)coex_stat->wl_connected);975 976 rtw_dbg(rtwdev, RTW_DBG_COEX,977 "[BTCoex], %s(): state = %d\n", __func__, state);978}979 980static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,981 u8 table_case)982{983 const struct rtw_chip_info *chip = rtwdev->chip;984 struct rtw_efuse *efuse = &rtwdev->efuse;985 u8 h2c_para[6] = {0};986 u32 table_wl = 0x5a5a5a5a;987 988 h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A;989 /* no definition */990 h2c_para[1] = 0x1;991 992 if (efuse->share_ant) {993 if (table_case < chip->table_sant_num)994 table_wl = chip->table_sant[table_case].wl;995 } else {996 if (table_case < chip->table_nsant_num)997 table_wl = chip->table_nsant[table_case].wl;998 }999 1000 /* tell WL FW WL slot toggle table-A*/1001 h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0));1002 h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8));1003 h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16));1004 h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24));1005 1006 rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]);1007 1008 rtw_dbg(rtwdev, RTW_DBG_COEX,1009 "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",1010 __func__, h2c_para[0], h2c_para[1], h2c_para[2],1011 h2c_para[3], h2c_para[4], h2c_para[5]);1012}1013 1014#define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa1015static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force,1016 u8 interval, u32 table)1017{1018 struct rtw_coex *coex = &rtwdev->coex;1019 struct rtw_coex_stat *coex_stat = &coex->stat;1020 u8 cur_h2c_para[6] = {0};1021 u8 i;1022 1023 cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B;1024 cur_h2c_para[1] = interval;1025 cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0));1026 cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8));1027 cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16));1028 cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24));1029 1030 coex_stat->wl_toggle_interval = interval;1031 1032 for (i = 0; i <= 5; i++)1033 coex_stat->wl_toggle_para[i] = cur_h2c_para[i];1034 1035 rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]);1036 1037 rtw_dbg(rtwdev, RTW_DBG_COEX,1038 "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",1039 __func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2],1040 cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]);1041}1042 1043static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,1044 u32 table1)1045{1046#define DEF_BRK_TABLE_VAL 0xf0ffffff1047 struct rtw_coex *coex = &rtwdev->coex;1048 struct rtw_coex_dm *coex_dm = &coex->dm;1049 1050 /* If last tdma is wl slot toggle, force write table*/1051 if (!force && coex_dm->reason != COEX_RSN_LPS) {1052 if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) &&1053 table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1))1054 return;1055 }1056 rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);1057 rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);1058 rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);1059 1060 rtw_dbg(rtwdev, RTW_DBG_COEX,1061 "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0,1062 table1);1063}1064 1065static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)1066{1067 const struct rtw_chip_info *chip = rtwdev->chip;1068 struct rtw_coex *coex = &rtwdev->coex;1069 struct rtw_coex_dm *coex_dm = &coex->dm;1070 struct rtw_efuse *efuse = &rtwdev->efuse;1071 struct rtw_coex_stat *coex_stat = &coex->stat;1072 1073 coex_dm->cur_table = type;1074 1075 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type);1076 1077 if (efuse->share_ant) {1078 if (type < chip->table_sant_num)1079 rtw_coex_set_table(rtwdev, force,1080 chip->table_sant[type].bt,1081 chip->table_sant[type].wl);1082 } else {1083 type = type - 100;1084 if (type < chip->table_nsant_num)1085 rtw_coex_set_table(rtwdev, force,1086 chip->table_nsant[type].bt,1087 chip->table_nsant[type].wl);1088 }1089 if (coex_stat->wl_slot_toggle_change)1090 rtw_btc_wltoggle_table_a(rtwdev, true, type);1091}1092 1093static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)1094{1095 struct rtw_coex *coex = &rtwdev->coex;1096 1097 if (coex->manual_control || coex->stop_dm)1098 return;1099 1100 rtw_fw_bt_ignore_wlan_action(rtwdev, enable);1101}1102 1103static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,1104 u8 lps_val, u8 rpwm_val)1105{1106 struct rtw_coex *coex = &rtwdev->coex;1107 struct rtw_coex_stat *coex_stat = &coex->stat;1108 u8 lps_mode = 0x0;1109 1110 lps_mode = rtwdev->lps_conf.mode;1111 1112 switch (ps_type) {1113 case COEX_PS_WIFI_NATIVE:1114 /* recover to original 32k low power setting */1115 coex_stat->wl_force_lps_ctrl = false;1116 rtw_dbg(rtwdev, RTW_DBG_COEX,1117 "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__);1118 rtw_leave_lps(rtwdev);1119 break;1120 case COEX_PS_LPS_OFF:1121 coex_stat->wl_force_lps_ctrl = true;1122 if (lps_mode)1123 rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0);1124 1125 rtw_leave_lps(rtwdev);1126 rtw_dbg(rtwdev, RTW_DBG_COEX,1127 "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__);1128 break;1129 default:1130 break;1131 }1132}1133 1134static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,1135 u8 byte3, u8 byte4, u8 byte5)1136{1137 const struct rtw_chip_info *chip = rtwdev->chip;1138 struct rtw_coex *coex = &rtwdev->coex;1139 struct rtw_coex_dm *coex_dm = &coex->dm;1140 struct rtw_coex_stat *coex_stat = &coex->stat;1141 u8 ps_type = COEX_PS_WIFI_NATIVE;1142 bool ap_enable = false;1143 1144 if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {1145 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n",1146 __func__);1147 1148 byte1 &= ~BIT(4);1149 byte1 |= BIT(5);1150 1151 byte5 |= BIT(5);1152 byte5 &= ~BIT(6);1153 1154 ps_type = COEX_PS_WIFI_NATIVE;1155 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);1156 } else if ((byte1 & BIT(4) && !(byte1 & BIT(5))) ||1157 coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {1158 rtw_dbg(rtwdev, RTW_DBG_COEX,1159 "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,1160 byte1);1161 1162 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)1163 ps_type = COEX_PS_LPS_OFF;1164 else1165 ps_type = COEX_PS_LPS_ON;1166 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);1167 } else {1168 rtw_dbg(rtwdev, RTW_DBG_COEX,1169 "[BTCoex], %s(): native power save (byte1 = 0x%x)\n",1170 __func__, byte1);1171 1172 ps_type = COEX_PS_WIFI_NATIVE;1173 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);1174 }1175 1176 coex_dm->ps_tdma_para[0] = byte1;1177 coex_dm->ps_tdma_para[1] = byte2;1178 coex_dm->ps_tdma_para[2] = byte3;1179 coex_dm->ps_tdma_para[3] = byte4;1180 coex_dm->ps_tdma_para[4] = byte5;1181 1182 rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);1183 1184 if (byte1 & BIT(2)) {1185 coex_stat->wl_slot_toggle = true;1186 coex_stat->wl_slot_toggle_change = false;1187 } else {1188 coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle;1189 coex_stat->wl_slot_toggle = false;1190 }1191}1192 1193static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)1194{1195 const struct rtw_chip_info *chip = rtwdev->chip;1196 struct rtw_coex *coex = &rtwdev->coex;1197 struct rtw_coex_dm *coex_dm = &coex->dm;1198 struct rtw_coex_stat *coex_stat = &coex->stat;1199 struct rtw_efuse *efuse = &rtwdev->efuse;1200 u8 n, type;1201 bool turn_on;1202 bool wl_busy = false;1203 1204 if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */1205 rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT);1206 else1207 rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT);1208 1209 type = (u8)(tcase & 0xff);1210 1211 turn_on = (type == 0 || type == 100) ? false : true;1212 1213 if (!force && turn_on == coex_dm->cur_ps_tdma_on &&1214 type == coex_dm->cur_ps_tdma) {1215 rtw_dbg(rtwdev, RTW_DBG_COEX,1216 "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",1217 (coex_dm->cur_ps_tdma_on ? "on" : "off"),1218 coex_dm->cur_ps_tdma);1219 1220 return;1221 }1222 wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);1223 1224 if ((coex_stat->bt_a2dp_exist &&1225 (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||1226 !wl_busy)1227 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);1228 else1229 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);1230 1231 /* update pre state */1232 coex_dm->cur_ps_tdma_on = turn_on;1233 coex_dm->cur_ps_tdma = type;1234 1235 if (efuse->share_ant) {1236 if (type < chip->tdma_sant_num)1237 rtw_coex_set_tdma(rtwdev,1238 chip->tdma_sant[type].para[0],1239 chip->tdma_sant[type].para[1],1240 chip->tdma_sant[type].para[2],1241 chip->tdma_sant[type].para[3],1242 chip->tdma_sant[type].para[4]);1243 } else {1244 n = type - 100;1245 if (n < chip->tdma_nsant_num)1246 rtw_coex_set_tdma(rtwdev,1247 chip->tdma_nsant[n].para[0],1248 chip->tdma_nsant[n].para[1],1249 chip->tdma_nsant[n].para[2],1250 chip->tdma_nsant[n].para[3],1251 chip->tdma_nsant[n].para[4]);1252 }1253 1254 1255 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n",1256 turn_on ? "on" : "off", type);1257}1258 1259static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)1260{1261 struct rtw_coex *coex = &rtwdev->coex;1262 struct rtw_coex_stat *coex_stat = &coex->stat;1263 struct rtw_coex_rfe *coex_rfe = &coex->rfe;1264 struct rtw_coex_dm *coex_dm = &coex->dm;1265 u8 ctrl_type = COEX_SWITCH_CTRL_MAX;1266 u8 pos_type = COEX_SWITCH_TO_MAX;1267 1268 if (!force && coex_dm->cur_ant_pos_type == phase)1269 return;1270 1271 coex_dm->cur_ant_pos_type = phase;1272 1273 /* avoid switch coex_ctrl_owner during BT IQK */1274 rtw_coex_check_rfk(rtwdev);1275 1276 rtw_dbg(rtwdev, RTW_DBG_COEX,1277 "[BTCoex], coex_stat->bt_disabled = 0x%x\n",1278 coex_stat->bt_disabled);1279 1280 switch (phase) {1281 case COEX_SET_ANT_POWERON:1282 rtw_dbg(rtwdev, RTW_DBG_COEX,1283 "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__);1284 /* set path control owner to BT at power-on */1285 if (coex_stat->bt_disabled)1286 rtw_coex_coex_ctrl_owner(rtwdev, true);1287 else1288 rtw_coex_coex_ctrl_owner(rtwdev, false);1289 1290 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;1291 pos_type = COEX_SWITCH_TO_BT;1292 break;1293 case COEX_SET_ANT_INIT:1294 rtw_dbg(rtwdev, RTW_DBG_COEX,1295 "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__);1296 if (coex_stat->bt_disabled) {1297 /* set GNT_BT to SW low */1298 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);1299 1300 /* set GNT_WL to SW high */1301 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);1302 } else {1303 /* set GNT_BT to SW high */1304 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);1305 1306 /* set GNT_WL to SW low */1307 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);1308 }1309 1310 /* set path control owner to wl at initial step */1311 rtw_coex_coex_ctrl_owner(rtwdev, true);1312 1313 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;1314 pos_type = COEX_SWITCH_TO_BT;1315 break;1316 case COEX_SET_ANT_WONLY:1317 rtw_dbg(rtwdev, RTW_DBG_COEX,1318 "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__);1319 /* set GNT_BT to SW Low */1320 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);1321 1322 /* set GNT_WL to SW high */1323 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);1324 1325 /* set path control owner to wl at initial step */1326 rtw_coex_coex_ctrl_owner(rtwdev, true);1327 1328 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;1329 pos_type = COEX_SWITCH_TO_WLG;1330 break;1331 case COEX_SET_ANT_WOFF:1332 rtw_dbg(rtwdev, RTW_DBG_COEX,1333 "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__);1334 /* set path control owner to BT */1335 rtw_coex_coex_ctrl_owner(rtwdev, false);1336 1337 ctrl_type = COEX_SWITCH_CTRL_BY_BT;1338 pos_type = COEX_SWITCH_TO_NOCARE;1339 break;1340 case COEX_SET_ANT_2G:1341 rtw_dbg(rtwdev, RTW_DBG_COEX,1342 "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__);1343 /* set GNT_BT to PTA */1344 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);1345 1346 /* set GNT_WL to PTA */1347 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);1348 1349 /* set path control owner to wl at runtime step */1350 rtw_coex_coex_ctrl_owner(rtwdev, true);1351 1352 ctrl_type = COEX_SWITCH_CTRL_BY_PTA;1353 pos_type = COEX_SWITCH_TO_NOCARE;1354 break;1355 case COEX_SET_ANT_5G:1356 rtw_dbg(rtwdev, RTW_DBG_COEX,1357 "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__);1358 1359 /* set GNT_BT to HW PTA */1360 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);1361 1362 /* set GNT_WL to SW high */1363 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);1364 1365 /* set path control owner to wl at runtime step */1366 rtw_coex_coex_ctrl_owner(rtwdev, true);1367 1368 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;1369 pos_type = COEX_SWITCH_TO_WLA;1370 break;1371 case COEX_SET_ANT_2G_FREERUN:1372 rtw_dbg(rtwdev, RTW_DBG_COEX,1373 "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__);1374 1375 /* set GNT_BT to HW PTA */1376 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);1377 1378 /* Set GNT_WL to SW high */1379 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);1380 1381 /* set path control owner to wl at runtime step */1382 rtw_coex_coex_ctrl_owner(rtwdev, true);1383 1384 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;1385 pos_type = COEX_SWITCH_TO_WLG_BT;1386 break;1387 case COEX_SET_ANT_2G_WLBT:1388 rtw_dbg(rtwdev, RTW_DBG_COEX,1389 "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__);1390 /* set GNT_BT to HW PTA */1391 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);1392 1393 /* Set GNT_WL to HW PTA */1394 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);1395 1396 /* set path control owner to wl at runtime step */1397 rtw_coex_coex_ctrl_owner(rtwdev, true);1398 1399 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;1400 pos_type = COEX_SWITCH_TO_WLG_BT;1401 break;1402 default:1403 WARN(1, "unknown phase when setting antenna path\n");1404 return;1405 }1406 1407 if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX &&1408 coex_rfe->ant_switch_exist)1409 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);1410}1411 1412#define case_ALGO(src) \1413 case COEX_ALGO_##src: return #src1414 1415static const char *rtw_coex_get_algo_string(u8 algo)1416{1417 switch (algo) {1418 case_ALGO(NOPROFILE);1419 case_ALGO(HFP);1420 case_ALGO(HID);1421 case_ALGO(A2DP);1422 case_ALGO(PAN);1423 case_ALGO(A2DP_HID);1424 case_ALGO(A2DP_PAN);1425 case_ALGO(PAN_HID);1426 case_ALGO(A2DP_PAN_HID);1427 default:1428 return "Unknown";1429 }1430}1431 1432#define case_BT_PROFILE(src) \1433 case BPM_##src: return #src1434 1435static const char *rtw_coex_get_bt_profile_string(u8 bt_profile)1436{1437 switch (bt_profile) {1438 case_BT_PROFILE(NOPROFILE);1439 case_BT_PROFILE(HFP);1440 case_BT_PROFILE(HID);1441 case_BT_PROFILE(A2DP);1442 case_BT_PROFILE(PAN);1443 case_BT_PROFILE(HID_HFP);1444 case_BT_PROFILE(A2DP_HFP);1445 case_BT_PROFILE(A2DP_HID);1446 case_BT_PROFILE(A2DP_HID_HFP);1447 case_BT_PROFILE(PAN_HFP);1448 case_BT_PROFILE(PAN_HID);1449 case_BT_PROFILE(PAN_HID_HFP);1450 case_BT_PROFILE(PAN_A2DP);1451 case_BT_PROFILE(PAN_A2DP_HFP);1452 case_BT_PROFILE(PAN_A2DP_HID);1453 case_BT_PROFILE(PAN_A2DP_HID_HFP);1454 default:1455 return "Unknown";1456 }1457}1458 1459static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)1460{1461 struct rtw_coex *coex = &rtwdev->coex;1462 struct rtw_coex_stat *coex_stat = &coex->stat;1463 u8 algorithm = COEX_ALGO_NOPROFILE;1464 u8 profile_map = 0;1465 1466 if (coex_stat->bt_hfp_exist)1467 profile_map |= BPM_HFP;1468 if (coex_stat->bt_hid_exist)1469 profile_map |= BPM_HID;1470 if (coex_stat->bt_a2dp_exist)1471 profile_map |= BPM_A2DP;1472 if (coex_stat->bt_pan_exist)1473 profile_map |= BPM_PAN;1474 1475 switch (profile_map) {1476 case BPM_HFP:1477 algorithm = COEX_ALGO_HFP;1478 break;1479 case BPM_HID:1480 case BPM_HFP + BPM_HID:1481 algorithm = COEX_ALGO_HID;1482 break;1483 case BPM_HFP + BPM_A2DP:1484 case BPM_HID + BPM_A2DP:1485 case BPM_HFP + BPM_HID + BPM_A2DP:1486 algorithm = COEX_ALGO_A2DP_HID;1487 break;1488 case BPM_HFP + BPM_PAN:1489 case BPM_HID + BPM_PAN:1490 case BPM_HFP + BPM_HID + BPM_PAN:1491 algorithm = COEX_ALGO_PAN_HID;1492 break;1493 case BPM_HFP + BPM_A2DP + BPM_PAN:1494 case BPM_HID + BPM_A2DP + BPM_PAN:1495 case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:1496 algorithm = COEX_ALGO_A2DP_PAN_HID;1497 break;1498 case BPM_PAN:1499 algorithm = COEX_ALGO_PAN;1500 break;1501 case BPM_A2DP + BPM_PAN:1502 algorithm = COEX_ALGO_A2DP_PAN;1503 break;1504 case BPM_A2DP:1505 if (coex_stat->bt_multi_link) {1506 if (coex_stat->bt_hid_pair_num > 0)1507 algorithm = COEX_ALGO_A2DP_HID;1508 else1509 algorithm = COEX_ALGO_A2DP_PAN;1510 } else {1511 algorithm = COEX_ALGO_A2DP;1512 }1513 break;1514 default:1515 algorithm = COEX_ALGO_NOPROFILE;1516 break;1517 }1518 1519 rtw_dbg(rtwdev, RTW_DBG_COEX,1520 "[BTCoex], BT Profile = %s => Algorithm = %s\n",1521 rtw_coex_get_bt_profile_string(profile_map),1522 rtw_coex_get_algo_string(algorithm));1523 return algorithm;1524}1525 1526static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)1527{1528 const struct rtw_chip_info *chip = rtwdev->chip;1529 struct rtw_efuse *efuse = &rtwdev->efuse;1530 u8 table_case, tdma_case;1531 1532 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1533 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1534 1535 if (efuse->share_ant) {1536 /* Shared-Ant */1537 table_case = 2;1538 tdma_case = 0;1539 } else {1540 /* Non-Shared-Ant */1541 table_case = 100;1542 tdma_case = 100;1543 }1544 1545 rtw_coex_table(rtwdev, false, table_case);1546 rtw_coex_tdma(rtwdev, false, tdma_case);1547}1548 1549static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)1550{1551 const struct rtw_chip_info *chip = rtwdev->chip;1552 struct rtw_coex *coex = &rtwdev->coex;1553 struct rtw_coex_stat *coex_stat = &coex->stat;1554 struct rtw_coex_dm *coex_dm = &coex->dm;1555 struct rtw_efuse *efuse = &rtwdev->efuse;1556 u8 level = 0;1557 bool bt_afh_loss = true;1558 1559 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1560 1561 if (efuse->share_ant)1562 return;1563 1564 coex->freerun = true;1565 1566 if (bt_afh_loss)1567 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);1568 1569 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);1570 1571 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);1572 1573 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))1574 level = 2;1575 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))1576 level = 3;1577 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))1578 level = 4;1579 else1580 level = 5;1581 1582 if (level > chip->wl_rf_para_num - 1)1583 level = chip->wl_rf_para_num - 1;1584 1585 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)1586 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);1587 else1588 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);1589 1590 rtw_coex_table(rtwdev, false, 100);1591 rtw_coex_tdma(rtwdev, false, 100);1592}1593 1594static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)1595{1596 const struct rtw_chip_info *chip = rtwdev->chip;1597 struct rtw_efuse *efuse = &rtwdev->efuse;1598 u8 table_case, tdma_case;1599 1600 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1601 1602 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1603 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1604 1605 if (efuse->share_ant) {1606 /* Shared-Ant */1607 table_case = 9;1608 tdma_case = 16;1609 } else {1610 /* Non-Shared-Ant */1611 table_case = 100;1612 tdma_case = 100;1613 }1614 1615 rtw_coex_table(rtwdev, false, table_case);1616 rtw_coex_tdma(rtwdev, false, tdma_case);1617}1618 1619static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)1620{1621 const struct rtw_chip_info *chip = rtwdev->chip;1622 struct rtw_efuse *efuse = &rtwdev->efuse;1623 u8 table_case, tdma_case;1624 1625 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1626 1627 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1628 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1629 1630 if (efuse->share_ant) {1631 /* Shared-Ant */1632 table_case = 2;1633 tdma_case = 0;1634 } else {1635 /* Non-Shared-Ant */1636 table_case = 100;1637 tdma_case = 100;1638 }1639 1640 rtw_coex_table(rtwdev, false, table_case);1641 rtw_coex_tdma(rtwdev, false, tdma_case);1642}1643 1644static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)1645{1646 const struct rtw_chip_info *chip = rtwdev->chip;1647 struct rtw_coex *coex = &rtwdev->coex;1648 struct rtw_coex_stat *coex_stat = &coex->stat;1649 struct rtw_efuse *efuse = &rtwdev->efuse;1650 u8 table_case, tdma_case;1651 u32 slot_type = 0;1652 1653 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1654 1655 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1656 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1657 1658 if (efuse->share_ant) { /* Shared-Ant */1659 if (coex_stat->wl_gl_busy) {1660 table_case = 26;1661 if (coex_stat->bt_hid_exist &&1662 coex_stat->bt_profile_num == 1) {1663 slot_type = TDMA_4SLOT;1664 tdma_case = 20;1665 } else {1666 tdma_case = 20;1667 }1668 } else {1669 table_case = 1;1670 tdma_case = 0;1671 }1672 } else { /* Non-Shared-Ant */1673 if (coex_stat->wl_gl_busy)1674 table_case = 115;1675 else1676 table_case = 100;1677 tdma_case = 100;1678 }1679 1680 rtw_coex_table(rtwdev, false, table_case);1681 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);1682}1683 1684static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)1685{1686 const struct rtw_chip_info *chip = rtwdev->chip;1687 struct rtw_coex *coex = &rtwdev->coex;1688 struct rtw_coex_stat *coex_stat = &coex->stat;1689 struct rtw_coex_dm *coex_dm = &coex->dm;1690 struct rtw_efuse *efuse = &rtwdev->efuse;1691 struct rtw_coex_rfe *coex_rfe = &coex->rfe;1692 u8 table_case = 0xff, tdma_case = 0xff;1693 1694 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1695 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1696 1697 if (coex_rfe->ant_switch_with_bt &&1698 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {1699 if (efuse->share_ant &&1700 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&1701 coex_stat->wl_gl_busy) {1702 table_case = 0;1703 tdma_case = 0;1704 } else if (!efuse->share_ant) {1705 table_case = 100;1706 tdma_case = 100;1707 }1708 }1709 1710 if (table_case != 0xff && tdma_case != 0xff) {1711 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);1712 goto exit;1713 }1714 1715 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1716 1717 if (efuse->share_ant) {1718 /* Shared-Ant */1719 if (!coex_stat->wl_gl_busy) {1720 table_case = 10;1721 tdma_case = 3;1722 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {1723 table_case = 11;1724 1725 if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250)1726 tdma_case = 17;1727 else1728 tdma_case = 7;1729 } else {1730 table_case = 12;1731 tdma_case = 7;1732 }1733 } else {1734 /* Non-Shared-Ant */1735 if (!coex_stat->wl_gl_busy) {1736 table_case = 112;1737 tdma_case = 104;1738 } else if ((coex_stat->bt_ble_scan_type & 0x2) &&1739 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {1740 table_case = 114;1741 tdma_case = 103;1742 } else {1743 table_case = 112;1744 tdma_case = 103;1745 }1746 }1747 1748exit:1749 rtw_coex_table(rtwdev, false, table_case);1750 rtw_coex_tdma(rtwdev, false, tdma_case);1751}1752 1753static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)1754{1755 const struct rtw_chip_info *chip = rtwdev->chip;1756 struct rtw_coex *coex = &rtwdev->coex;1757 struct rtw_coex_stat *coex_stat = &coex->stat;1758 struct rtw_efuse *efuse = &rtwdev->efuse;1759 bool wl_hi_pri = false;1760 u8 table_case, tdma_case;1761 u32 slot_type = 0;1762 1763 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1764 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1765 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1766 1767 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||1768 coex_stat->wl_hi_pri_task2)1769 wl_hi_pri = true;1770 1771 if (efuse->share_ant) {1772 /* Shared-Ant */1773 if (wl_hi_pri) {1774 rtw_dbg(rtwdev, RTW_DBG_COEX,1775 "[BTCoex], bt inq/page + wifi hi-pri task\n");1776 table_case = 15;1777 1778 if (coex_stat->bt_profile_num > 0)1779 tdma_case = 10;1780 else if (coex_stat->wl_hi_pri_task1)1781 tdma_case = 6;1782 else if (!coex_stat->bt_page)1783 tdma_case = 8;1784 else1785 tdma_case = 9;1786 } else if (coex_stat->wl_gl_busy) {1787 rtw_dbg(rtwdev, RTW_DBG_COEX,1788 "[BTCoex], bt inq/page + wifi busy\n");1789 if (coex_stat->bt_profile_num == 0) {1790 table_case = 12;1791 tdma_case = 18;1792 } else if (coex_stat->bt_profile_num == 1 &&1793 !coex_stat->bt_a2dp_exist) {1794 slot_type = TDMA_4SLOT;1795 table_case = 12;1796 tdma_case = 20;1797 } else {1798 slot_type = TDMA_4SLOT;1799 table_case = 12;1800 tdma_case = 26;1801 }1802 } else if (coex_stat->wl_connected) {1803 rtw_dbg(rtwdev, RTW_DBG_COEX,1804 "[BTCoex], bt inq/page + wifi connected\n");1805 table_case = 9;1806 tdma_case = 27;1807 } else {1808 rtw_dbg(rtwdev, RTW_DBG_COEX,1809 "[BTCoex], bt inq/page + wifi not-connected\n");1810 table_case = 1;1811 tdma_case = 0;1812 }1813 } else {1814 /* Non_Shared-Ant */1815 if (wl_hi_pri) {1816 rtw_dbg(rtwdev, RTW_DBG_COEX,1817 "[BTCoex], bt inq/page + wifi hi-pri task\n");1818 table_case = 114;1819 1820 if (coex_stat->bt_profile_num > 0)1821 tdma_case = 110;1822 else if (coex_stat->wl_hi_pri_task1)1823 tdma_case = 106;1824 else if (!coex_stat->bt_page)1825 tdma_case = 108;1826 else1827 tdma_case = 109;1828 } else if (coex_stat->wl_gl_busy) {1829 rtw_dbg(rtwdev, RTW_DBG_COEX,1830 "[BTCoex], bt inq/page + wifi busy\n");1831 table_case = 114;1832 tdma_case = 121;1833 } else if (coex_stat->wl_connected) {1834 rtw_dbg(rtwdev, RTW_DBG_COEX,1835 "[BTCoex], bt inq/page + wifi connected\n");1836 table_case = 101;1837 tdma_case = 100;1838 } else {1839 rtw_dbg(rtwdev, RTW_DBG_COEX,1840 "[BTCoex], bt inq/page + wifi not-connected\n");1841 table_case = 101;1842 tdma_case = 100;1843 }1844 }1845 1846 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n",1847 wl_hi_pri, coex_stat->bt_page);1848 1849 rtw_coex_table(rtwdev, false, table_case);1850 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);1851}1852 1853static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev)1854{1855 const struct rtw_chip_info *chip = rtwdev->chip;1856 struct rtw_coex *coex = &rtwdev->coex;1857 struct rtw_coex_stat *coex_stat = &coex->stat;1858 struct rtw_efuse *efuse = &rtwdev->efuse;1859 struct rtw_coex_dm *coex_dm = &coex->dm;1860 u8 table_case, tdma_case;1861 1862 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1863 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1864 1865 if (efuse->share_ant) {1866 coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;1867 if (coex_stat->bt_whck_test)1868 table_case = 2;1869 else if (coex_stat->wl_linkscan_proc || coex_stat->bt_hid_exist)1870 table_case = 33;1871 else if (coex_stat->bt_setup_link || coex_stat->bt_inq_page)1872 table_case = 0;1873 else if (coex_stat->bt_a2dp_exist)1874 table_case = 34;1875 else1876 table_case = 33;1877 1878 tdma_case = 0;1879 } else {1880 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))1881 tdma_case = 112;1882 else1883 tdma_case = 113;1884 1885 table_case = 121;1886 }1887 1888 if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {1889 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)1890 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);1891 else1892 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);1893 } else {1894 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1895 }1896 1897 rtw_coex_table(rtwdev, false, table_case);1898 rtw_coex_tdma(rtwdev, false, tdma_case);1899}1900 1901static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)1902{1903 const struct rtw_chip_info *chip = rtwdev->chip;1904 struct rtw_coex *coex = &rtwdev->coex;1905 struct rtw_coex_stat *coex_stat = &coex->stat;1906 struct rtw_efuse *efuse = &rtwdev->efuse;1907 u8 table_case, tdma_case;1908 1909 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1910 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1911 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1912 1913 if (efuse->share_ant) {1914 /* Shared-Ant */1915 table_case = 10;1916 tdma_case = 5;1917 } else {1918 /* Non-Shared-Ant */1919 if (coex_stat->bt_multi_link) {1920 table_case = 112;1921 tdma_case = 117;1922 } else {1923 table_case = 105;1924 tdma_case = 100;1925 }1926 }1927 1928 rtw_coex_table(rtwdev, false, table_case);1929 rtw_coex_tdma(rtwdev, false, tdma_case);1930}1931 1932static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)1933{1934 const struct rtw_chip_info *chip = rtwdev->chip;1935 struct rtw_coex *coex = &rtwdev->coex;1936 struct rtw_coex_stat *coex_stat = &coex->stat;1937 struct rtw_efuse *efuse = &rtwdev->efuse;1938 u8 table_case, tdma_case;1939 u32 slot_type = 0;1940 bool bt_multi_link_remain = false, is_toggle_table = false;1941 1942 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);1943 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);1944 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);1945 1946 if (efuse->share_ant) {1947 /* Shared-Ant */1948 if (coex_stat->bt_ble_exist) {1949 /* RCU */1950 if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {1951 table_case = 26;1952 tdma_case = 2;1953 } else {1954 table_case = 27;1955 tdma_case = 9;1956 }1957 } else {1958 /* Legacy HID */1959 if (coex_stat->bt_profile_num == 1 &&1960 (coex_stat->bt_multi_link ||1961 (coex_stat->lo_pri_rx +1962 coex_stat->lo_pri_tx > 360) ||1963 coex_stat->bt_slave ||1964 bt_multi_link_remain)) {1965 slot_type = TDMA_4SLOT;1966 table_case = 12;1967 tdma_case = 20;1968 } else if (coex_stat->bt_a2dp_active) {1969 table_case = 9;1970 tdma_case = 18;1971 } else if (coex_stat->bt_418_hid_exist &&1972 coex_stat->wl_gl_busy) {1973 is_toggle_table = true;1974 slot_type = TDMA_4SLOT;1975 table_case = 9;1976 tdma_case = 24;1977 } else if (coex_stat->bt_ble_hid_exist &&1978 coex_stat->wl_gl_busy) {1979 table_case = 32;1980 tdma_case = 9;1981 } else {1982 table_case = 9;1983 tdma_case = 9;1984 }1985 }1986 } else {1987 /* Non-Shared-Ant */1988 if (coex_stat->bt_ble_exist) {1989 /* BLE */1990 if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {1991 table_case = 121;1992 tdma_case = 102;1993 } else {1994 table_case = 122;1995 tdma_case = 109;1996 }1997 } else if (coex_stat->bt_a2dp_active) {1998 table_case = 113;1999 tdma_case = 118;2000 } else {2001 table_case = 113;2002 tdma_case = 104;2003 }2004 }2005 2006 rtw_coex_table(rtwdev, false, table_case);2007 if (is_toggle_table) {2008 rtw_btc_wltoggle_table_a(rtwdev, true, table_case);2009 rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE);2010 }2011 2012 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);2013}2014 2015static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)2016{2017 const struct rtw_chip_info *chip = rtwdev->chip;2018 struct rtw_coex *coex = &rtwdev->coex;2019 struct rtw_coex_stat *coex_stat = &coex->stat;2020 struct rtw_coex_dm *coex_dm = &coex->dm;2021 struct rtw_efuse *efuse = &rtwdev->efuse;2022 u8 table_case, tdma_case;2023 u32 slot_type = 0;2024 2025 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2026 2027 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2028 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2029 2030 slot_type = TDMA_4SLOT;2031 2032 if (efuse->share_ant) {2033 /* Shared-Ant */2034 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)2035 table_case = 12;2036 else2037 table_case = 9;2038 2039 if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy)2040 tdma_case = 14;2041 else2042 tdma_case = 13;2043 } else {2044 /* Non-Shared-Ant */2045 table_case = 112;2046 2047 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))2048 tdma_case = 112;2049 else2050 tdma_case = 113;2051 }2052 2053 rtw_coex_table(rtwdev, false, table_case);2054 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);2055}2056 2057static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)2058{2059 const struct rtw_chip_info *chip = rtwdev->chip;2060 struct rtw_coex *coex = &rtwdev->coex;2061 struct rtw_coex_stat *coex_stat = &coex->stat;2062 struct rtw_efuse *efuse = &rtwdev->efuse;2063 u8 table_case, tdma_case;2064 bool ap_enable = false;2065 2066 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2067 2068 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2069 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2070 2071 if (efuse->share_ant) { /* Shared-Ant */2072 if (ap_enable) {2073 table_case = 2;2074 tdma_case = 0;2075 } else if (coex_stat->wl_gl_busy) {2076 table_case = 28;2077 tdma_case = 20;2078 } else {2079 table_case = 28;2080 tdma_case = 26;2081 }2082 } else { /* Non-Shared-Ant */2083 if (ap_enable) {2084 table_case = 100;2085 tdma_case = 100;2086 } else {2087 table_case = 119;2088 tdma_case = 120;2089 }2090 }2091 2092 rtw_coex_table(rtwdev, false, table_case);2093 rtw_coex_tdma(rtwdev, false, tdma_case);2094}2095 2096static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)2097{2098 const struct rtw_chip_info *chip = rtwdev->chip;2099 struct rtw_coex *coex = &rtwdev->coex;2100 struct rtw_coex_stat *coex_stat = &coex->stat;2101 struct rtw_efuse *efuse = &rtwdev->efuse;2102 u8 table_case, tdma_case;2103 2104 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2105 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2106 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2107 2108 if (efuse->share_ant) {2109 /* Shared-Ant */2110 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)2111 table_case = 14;2112 else2113 table_case = 10;2114 2115 if (coex_stat->wl_gl_busy)2116 tdma_case = 17;2117 else2118 tdma_case = 20;2119 } else {2120 /* Non-Shared-Ant */2121 table_case = 112;2122 2123 if (coex_stat->wl_gl_busy)2124 tdma_case = 117;2125 else2126 tdma_case = 119;2127 }2128 2129 rtw_coex_table(rtwdev, false, table_case);2130 rtw_coex_tdma(rtwdev, false, tdma_case);2131}2132 2133static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)2134{2135 const struct rtw_chip_info *chip = rtwdev->chip;2136 struct rtw_coex *coex = &rtwdev->coex;2137 struct rtw_coex_stat *coex_stat = &coex->stat;2138 struct rtw_coex_dm *coex_dm = &coex->dm;2139 struct rtw_efuse *efuse = &rtwdev->efuse;2140 u8 table_case, tdma_case, interval = 0;2141 u32 slot_type = 0;2142 bool is_toggle_table = false;2143 2144 slot_type = TDMA_4SLOT;2145 2146 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2147 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2148 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2149 2150 if (efuse->share_ant) {2151 /* Shared-Ant */2152 if (coex_stat->bt_ble_exist) {2153 table_case = 26; /* for RCU */2154 } else if (coex_stat->bt_418_hid_exist) {2155 table_case = 9;2156 interval = 1;2157 } else {2158 table_case = 9;2159 }2160 2161 if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) {2162 tdma_case = 14;2163 } else if (coex_stat->bt_418_hid_exist) {2164 is_toggle_table = true;2165 tdma_case = 23;2166 } else {2167 tdma_case = 13;2168 }2169 } else {2170 /* Non-Shared-Ant */2171 if (coex_stat->bt_ble_exist)2172 table_case = 121;2173 else2174 table_case = 113;2175 2176 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))2177 tdma_case = 112;2178 else2179 tdma_case = 113;2180 }2181 2182 rtw_coex_table(rtwdev, false, table_case);2183 if (is_toggle_table) {2184 rtw_btc_wltoggle_table_a(rtwdev, true, table_case);2185 rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE);2186 }2187 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);2188}2189 2190static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)2191{2192 const struct rtw_chip_info *chip = rtwdev->chip;2193 struct rtw_coex *coex = &rtwdev->coex;2194 struct rtw_coex_stat *coex_stat = &coex->stat;2195 struct rtw_efuse *efuse = &rtwdev->efuse;2196 u8 table_case, tdma_case;2197 2198 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2199 2200 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2201 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2202 if (efuse->share_ant) {2203 /* Shared-Ant */2204 if (coex_stat->wl_gl_busy &&2205 coex_stat->wl_noisy_level == 0)2206 table_case = 14;2207 else2208 table_case = 10;2209 2210 if (coex_stat->wl_gl_busy)2211 tdma_case = 15;2212 else2213 tdma_case = 20;2214 } else {2215 /* Non-Shared-Ant */2216 table_case = 112;2217 2218 if (coex_stat->wl_gl_busy)2219 tdma_case = 115;2220 else2221 tdma_case = 120;2222 }2223 2224 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2225 rtw_coex_table(rtwdev, false, table_case);2226 rtw_coex_tdma(rtwdev, false, tdma_case);2227}2228 2229static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)2230{2231 const struct rtw_chip_info *chip = rtwdev->chip;2232 struct rtw_coex *coex = &rtwdev->coex;2233 struct rtw_coex_stat *coex_stat = &coex->stat;2234 struct rtw_efuse *efuse = &rtwdev->efuse;2235 u8 table_case, tdma_case;2236 2237 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2238 2239 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2240 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2241 2242 if (efuse->share_ant) {2243 /* Shared-Ant */2244 table_case = 9;2245 2246 if (coex_stat->wl_gl_busy)2247 tdma_case = 18;2248 else2249 tdma_case = 19;2250 } else {2251 /* Non-Shared-Ant */2252 table_case = 113;2253 2254 if (coex_stat->wl_gl_busy)2255 tdma_case = 117;2256 else2257 tdma_case = 119;2258 }2259 2260 rtw_coex_table(rtwdev, false, table_case);2261 rtw_coex_tdma(rtwdev, false, tdma_case);2262}2263 2264static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)2265{2266 const struct rtw_chip_info *chip = rtwdev->chip;2267 struct rtw_coex *coex = &rtwdev->coex;2268 struct rtw_coex_stat *coex_stat = &coex->stat;2269 struct rtw_efuse *efuse = &rtwdev->efuse;2270 u8 table_case, tdma_case;2271 2272 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2273 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2274 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2275 2276 if (efuse->share_ant) {2277 /* Shared-Ant */2278 table_case = 10;2279 2280 if (coex_stat->wl_gl_busy)2281 tdma_case = 15;2282 else2283 tdma_case = 20;2284 } else {2285 /* Non-Shared-Ant */2286 table_case = 113;2287 2288 if (coex_stat->wl_gl_busy)2289 tdma_case = 115;2290 else2291 tdma_case = 120;2292 }2293 2294 rtw_coex_table(rtwdev, false, table_case);2295 rtw_coex_tdma(rtwdev, false, tdma_case);2296}2297 2298static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)2299{2300 const struct rtw_chip_info *chip = rtwdev->chip;2301 struct rtw_coex *coex = &rtwdev->coex;2302 struct rtw_efuse *efuse = &rtwdev->efuse;2303 struct rtw_coex_stat *coex_stat = &coex->stat;2304 u8 table_case, tdma_case;2305 2306 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2307 2308 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);2309 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2310 2311 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);2312 2313 if (coex_stat->bt_game_hid_exist && coex_stat->wl_linkscan_proc)2314 coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;2315 2316 if (efuse->share_ant) {2317 /* Shared-Ant */2318 table_case = 0;2319 tdma_case = 0;2320 } else {2321 /* Non-Shared-Ant */2322 table_case = 100;2323 tdma_case = 100;2324 }2325 2326 rtw_coex_table(rtwdev, false, table_case);2327 rtw_coex_tdma(rtwdev, false, tdma_case);2328}2329 2330static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)2331{2332 const struct rtw_chip_info *chip = rtwdev->chip;2333 struct rtw_efuse *efuse = &rtwdev->efuse;2334 u8 table_case, tdma_case;2335 2336 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2337 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2338 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2339 2340 if (efuse->share_ant) {2341 /* Shared-Ant */2342 table_case = 2;2343 tdma_case = 0;2344 } else {2345 /* Non-Shared-Ant */2346 table_case = 100;2347 tdma_case = 100;2348 }2349 2350 rtw_coex_table(rtwdev, false, table_case);2351 rtw_coex_tdma(rtwdev, false, tdma_case);2352}2353 2354static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)2355{2356 const struct rtw_chip_info *chip = rtwdev->chip;2357 struct rtw_coex *coex = &rtwdev->coex;2358 struct rtw_efuse *efuse = &rtwdev->efuse;2359 struct rtw_coex_stat *coex_stat = &coex->stat;2360 u8 table_case, tdma_case;2361 2362 if (coex->under_5g)2363 return;2364 2365 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2366 2367 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2368 2369 if (efuse->share_ant) {2370 /* Shared-Ant */2371 table_case = 28;2372 tdma_case = 0;2373 } else {2374 /* Non-Shared-Ant */2375 table_case = 100;2376 tdma_case = 100;2377 }2378 2379 if (coex_stat->bt_game_hid_exist) {2380 coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;2381 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)2382 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);2383 else2384 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);2385 } else {2386 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2387 }2388 2389 rtw_coex_table(rtwdev, false, table_case);2390 rtw_coex_tdma(rtwdev, false, tdma_case);2391}2392 2393static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)2394{2395 const struct rtw_chip_info *chip = rtwdev->chip;2396 struct rtw_coex *coex = &rtwdev->coex;2397 struct rtw_coex_stat *coex_stat = &coex->stat;2398 struct rtw_efuse *efuse = &rtwdev->efuse;2399 u8 table_case, tdma_case;2400 u32 slot_type = 0;2401 2402 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2403 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2404 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2405 2406 if (efuse->share_ant) { /* Shared-Ant */2407 if (coex_stat->bt_a2dp_exist) {2408 slot_type = TDMA_4SLOT;2409 tdma_case = 11;2410 if (coex_stat->wl_gl_busy)2411 table_case = 26;2412 else2413 table_case = 9;2414 } else {2415 table_case = 9;2416 tdma_case = 7;2417 }2418 } else { /* Non-Shared-Ant */2419 if (coex_stat->bt_a2dp_exist) {2420 slot_type = TDMA_4SLOT;2421 table_case = 112;2422 tdma_case = 111;2423 } else {2424 table_case = 112;2425 tdma_case = 107;2426 }2427 }2428 2429 rtw_coex_table(rtwdev, false, table_case);2430 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);2431}2432 2433static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)2434{2435 const struct rtw_chip_info *chip = rtwdev->chip;2436 struct rtw_efuse *efuse = &rtwdev->efuse;2437 u8 table_case, tdma_case;2438 2439 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2440 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);2441 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);2442 2443 if (efuse->share_ant) {2444 /* Shared-Ant */2445 table_case = 1;2446 tdma_case = 0;2447 } else {2448 /* Non-Shared-Ant */2449 table_case = 100;2450 tdma_case = 100;2451 }2452 2453 rtw_coex_table(rtwdev, false, table_case);2454 rtw_coex_tdma(rtwdev, false, tdma_case);2455}2456 2457static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)2458{2459 struct rtw_coex *coex = &rtwdev->coex;2460 struct rtw_coex_stat *coex_stat = &coex->stat;2461 u8 algorithm;2462 2463 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2464 2465 algorithm = rtw_coex_algorithm(rtwdev);2466 2467 switch (algorithm) {2468 case COEX_ALGO_HFP:2469 rtw_coex_action_bt_hfp(rtwdev);2470 break;2471 case COEX_ALGO_HID:2472 if (rtw_coex_freerun_check(rtwdev))2473 rtw_coex_action_freerun(rtwdev);2474 else2475 rtw_coex_action_bt_hid(rtwdev);2476 break;2477 case COEX_ALGO_A2DP:2478 if (rtw_coex_freerun_check(rtwdev))2479 rtw_coex_action_freerun(rtwdev);2480 else if (coex_stat->bt_a2dp_sink)2481 rtw_coex_action_bt_a2dpsink(rtwdev);2482 else2483 rtw_coex_action_bt_a2dp(rtwdev);2484 break;2485 case COEX_ALGO_PAN:2486 rtw_coex_action_bt_pan(rtwdev);2487 break;2488 case COEX_ALGO_A2DP_HID:2489 if (rtw_coex_freerun_check(rtwdev))2490 rtw_coex_action_freerun(rtwdev);2491 else2492 rtw_coex_action_bt_a2dp_hid(rtwdev);2493 break;2494 case COEX_ALGO_A2DP_PAN:2495 rtw_coex_action_bt_a2dp_pan(rtwdev);2496 break;2497 case COEX_ALGO_PAN_HID:2498 rtw_coex_action_bt_pan_hid(rtwdev);2499 break;2500 case COEX_ALGO_A2DP_PAN_HID:2501 rtw_coex_action_bt_a2dp_pan_hid(rtwdev);2502 break;2503 default:2504 case COEX_ALGO_NOPROFILE:2505 rtw_coex_action_bt_idle(rtwdev);2506 break;2507 }2508}2509 2510static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)2511{2512 const struct rtw_chip_info *chip = rtwdev->chip;2513 struct rtw_coex *coex = &rtwdev->coex;2514 struct rtw_coex_dm *coex_dm = &coex->dm;2515 struct rtw_coex_stat *coex_stat = &coex->stat;2516 bool rf4ce_en = false;2517 2518 lockdep_assert_held(&rtwdev->mutex);2519 2520 if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))2521 return;2522 2523 coex_dm->reason = reason;2524 2525 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__,2526 reason);2527 2528 /* update wifi_link_info_ext variable */2529 rtw_coex_update_wl_link_info(rtwdev, reason);2530 2531 rtw_coex_monitor_bt_enable(rtwdev);2532 2533 if (coex->manual_control) {2534 rtw_dbg(rtwdev, RTW_DBG_COEX,2535 "[BTCoex], return for Manual CTRL!!\n");2536 return;2537 }2538 2539 if (coex->stop_dm) {2540 rtw_dbg(rtwdev, RTW_DBG_COEX,2541 "[BTCoex], return for Stop Coex DM!!\n");2542 return;2543 }2544 2545 if (coex_stat->wl_under_ips) {2546 rtw_dbg(rtwdev, RTW_DBG_COEX,2547 "[BTCoex], return for wifi is under IPS!!\n");2548 return;2549 }2550 2551 if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&2552 !coex_stat->bt_setup_link) {2553 rtw_dbg(rtwdev, RTW_DBG_COEX,2554 "[BTCoex], return for coex_freeze!!\n");2555 return;2556 }2557 2558 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;2559 coex->freerun = false;2560 2561 /* Pure-5G Coex Process */2562 if (coex->under_5g) {2563 coex_stat->wl_coex_mode = COEX_WLINK_5G;2564 rtw_coex_action_wl_under5g(rtwdev);2565 goto exit;2566 }2567 2568 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n");2569 coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;2570 2571 if (coex_stat->bt_disabled) {2572 if (coex_stat->wl_connected && rf4ce_en)2573 rtw_coex_action_rf4ce(rtwdev);2574 else if (!coex_stat->wl_connected)2575 rtw_coex_action_wl_not_connected(rtwdev);2576 else2577 rtw_coex_action_wl_only(rtwdev);2578 goto exit;2579 }2580 2581 if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {2582 rtw_coex_action_wl_native_lps(rtwdev);2583 goto exit;2584 }2585 2586 if (coex_stat->bt_game_hid_exist && coex_stat->wl_connected) {2587 rtw_coex_action_bt_game_hid(rtwdev);2588 goto exit;2589 }2590 2591 if (coex_stat->bt_whck_test) {2592 rtw_coex_action_bt_whql_test(rtwdev);2593 goto exit;2594 }2595 2596 if (coex_stat->bt_setup_link) {2597 rtw_coex_action_bt_relink(rtwdev);2598 goto exit;2599 }2600 2601 if (coex_stat->bt_inq_page) {2602 rtw_coex_action_bt_inquiry(rtwdev);2603 goto exit;2604 }2605 2606 if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||2607 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&2608 coex_stat->wl_connected) {2609 rtw_coex_action_bt_idle(rtwdev);2610 goto exit;2611 }2612 2613 if (coex_stat->wl_linkscan_proc && !coex->freerun) {2614 rtw_coex_action_wl_linkscan(rtwdev);2615 goto exit;2616 }2617 2618 if (coex_stat->wl_connected) {2619 rtw_coex_action_wl_connected(rtwdev);2620 goto exit;2621 } else {2622 rtw_coex_action_wl_not_connected(rtwdev);2623 goto exit;2624 }2625 2626exit:2627 2628 if (chip->wl_mimo_ps_support) {2629 if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {2630 if (coex_dm->reason == COEX_RSN_2GMEDIA)2631 rtw_coex_mimo_ps(rtwdev, true, true);2632 else2633 rtw_coex_mimo_ps(rtwdev, false, true);2634 } else {2635 rtw_coex_mimo_ps(rtwdev, false, false);2636 }2637 }2638 2639 rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);2640 rtw_coex_limited_wl(rtwdev);2641}2642 2643static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)2644{2645 struct rtw_coex *coex = &rtwdev->coex;2646 struct rtw_coex_stat *coex_stat = &coex->stat;2647 struct rtw_coex_dm *coex_dm = &coex->dm;2648 u8 i;2649 2650 memset(coex_dm, 0, sizeof(*coex_dm));2651 memset(coex_stat, 0, sizeof(*coex_stat));2652 2653 for (i = 0; i < COEX_CNT_WL_MAX; i++)2654 coex_stat->cnt_wl[i] = 0;2655 2656 for (i = 0; i < COEX_CNT_BT_MAX; i++)2657 coex_stat->cnt_bt[i] = 0;2658 2659 for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)2660 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;2661 2662 for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)2663 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;2664 2665 coex_stat->wl_coex_mode = COEX_WLINK_MAX;2666 coex_stat->wl_rx_rate = DESC_RATE5_5M;2667 coex_stat->wl_rts_rx_rate = DESC_RATE5_5M;2668}2669 2670static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)2671{2672 struct rtw_coex *coex = &rtwdev->coex;2673 struct rtw_coex_stat *coex_stat = &coex->stat;2674 2675 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2676 2677 rtw_coex_init_coex_var(rtwdev);2678 2679 coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4));2680 2681 rtw_coex_monitor_bt_enable(rtwdev);2682 rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend);2683 2684 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);2685 2686 rtw_coex_set_rfe_type(rtwdev);2687 rtw_coex_set_init(rtwdev);2688 2689 /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */2690 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);2691 2692 /* set Tx beacon = Hi-Pri */2693 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);2694 2695 /* set Tx beacon queue = Hi-Pri */2696 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);2697 2698 /* antenna config */2699 if (coex->wl_rf_off) {2700 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);2701 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);2702 coex->stop_dm = true;2703 2704 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n",2705 __func__);2706 } else if (wifi_only) {2707 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);2708 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,2709 true);2710 coex->stop_dm = true;2711 } else {2712 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);2713 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,2714 true);2715 coex->stop_dm = false;2716 coex->freeze = true;2717 }2718 2719 /* PTA parameter */2720 rtw_coex_table(rtwdev, true, 1);2721 rtw_coex_tdma(rtwdev, true, 0);2722 rtw_coex_query_bt_info(rtwdev);2723}2724 2725void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)2726{2727 struct rtw_coex *coex = &rtwdev->coex;2728 u8 table_case = 1;2729 2730 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);2731 2732 coex->stop_dm = true;2733 coex->wl_rf_off = false;2734 2735 /* enable BB, we can write 0x948 */2736 rtw_write8_set(rtwdev, REG_SYS_FUNC_EN,2737 BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);2738 2739 rtw_coex_monitor_bt_enable(rtwdev);2740 rtw_coex_set_rfe_type(rtwdev);2741 2742 /* set antenna path to BT */2743 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);2744 2745 rtw_coex_table(rtwdev, true, table_case);2746 /* red x issue */2747 rtw_write8(rtwdev, 0xff1a, 0x0);2748 rtw_coex_set_gnt_debug(rtwdev);2749}2750 2751void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)2752{2753 rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);2754}2755 2756void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)2757{2758 __rtw_coex_init_hw_config(rtwdev, wifi_only);2759}2760 2761void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)2762{2763 struct rtw_coex *coex = &rtwdev->coex;2764 struct rtw_coex_stat *coex_stat = &coex->stat;2765 2766 if (coex->manual_control || coex->stop_dm)2767 return;2768 2769 if (type == COEX_IPS_ENTER) {2770 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n");2771 2772 coex_stat->wl_under_ips = true;2773 2774 /* for lps off */2775 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);2776 2777 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);2778 rtw_coex_action_coex_all_off(rtwdev);2779 } else if (type == COEX_IPS_LEAVE) {2780 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n");2781 2782 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);2783 /* run init hw config (exclude wifi only) */2784 __rtw_coex_init_hw_config(rtwdev, false);2785 2786 coex_stat->wl_under_ips = false;2787 }2788}2789 2790void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)2791{2792 struct rtw_coex *coex = &rtwdev->coex;2793 struct rtw_coex_stat *coex_stat = &coex->stat;2794 2795 if (coex->manual_control || coex->stop_dm)2796 return;2797 2798 if (type == COEX_LPS_ENABLE) {2799 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n");2800 2801 coex_stat->wl_under_lps = true;2802 2803 if (coex_stat->wl_force_lps_ctrl) {2804 /* for ps-tdma */2805 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);2806 } else {2807 /* for native ps */2808 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);2809 rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false);2810 2811 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);2812 }2813 } else if (type == COEX_LPS_DISABLE) {2814 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n");2815 2816 coex_stat->wl_under_lps = false;2817 2818 /* for lps off */2819 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);2820 2821 if (!coex_stat->wl_force_lps_ctrl)2822 rtw_coex_query_bt_info(rtwdev);2823 2824 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);2825 }2826}2827 2828void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)2829{2830 struct rtw_coex *coex = &rtwdev->coex;2831 struct rtw_coex_stat *coex_stat = &coex->stat;2832 2833 if (coex->manual_control || coex->stop_dm)2834 return;2835 2836 coex->freeze = false;2837 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);2838 2839 if (type == COEX_SCAN_START_5G) {2840 rtw_dbg(rtwdev, RTW_DBG_COEX,2841 "[BTCoex], SCAN START notify (5G)\n");2842 2843 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);2844 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);2845 } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {2846 rtw_dbg(rtwdev, RTW_DBG_COEX,2847 "[BTCoex], SCAN START notify (2G)\n");2848 2849 coex_stat->wl_hi_pri_task2 = true;2850 2851 /* Force antenna setup for no scan result issue */2852 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);2853 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);2854 } else {2855 coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */2856 2857 rtw_dbg(rtwdev, RTW_DBG_COEX,2858 "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",2859 coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]);2860 2861 coex_stat->wl_hi_pri_task2 = false;2862 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);2863 }2864}2865 2866void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)2867{2868 struct rtw_coex *coex = &rtwdev->coex;2869 2870 if (coex->manual_control || coex->stop_dm)2871 return;2872 2873 if (type == COEX_SWITCH_TO_5G) {2874 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n",2875 __func__);2876 } else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) {2877 rtw_dbg(rtwdev, RTW_DBG_COEX,2878 "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__);2879 } else {2880 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n",2881 __func__);2882 }2883 2884 if (type == COEX_SWITCH_TO_5G)2885 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);2886 else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)2887 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);2888 else2889 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);2890}2891 2892void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)2893{2894 struct rtw_coex *coex = &rtwdev->coex;2895 struct rtw_coex_stat *coex_stat = &coex->stat;2896 2897 if (coex->manual_control || coex->stop_dm)2898 return;2899 2900 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);2901 2902 if (type == COEX_ASSOCIATE_5G_START) {2903 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n",2904 __func__);2905 2906 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);2907 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);2908 } else if (type == COEX_ASSOCIATE_5G_FINISH) {2909 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n",2910 __func__);2911 2912 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);2913 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);2914 } else if (type == COEX_ASSOCIATE_START) {2915 coex_stat->wl_hi_pri_task1 = true;2916 coex_stat->wl_connecting = true;2917 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;2918 coex_stat->wl_connecting = true;2919 ieee80211_queue_delayed_work(rtwdev->hw,2920 &coex->wl_connecting_work, 2 * HZ);2921 2922 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n",2923 __func__);2924 /* Force antenna setup for no scan result issue */2925 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);2926 2927 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);2928 2929 /* To keep TDMA case during connect process,2930 * to avoid changed by Btinfo and runcoexmechanism2931 */2932 coex->freeze = true;2933 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,2934 5 * HZ);2935 } else {2936 coex_stat->wl_hi_pri_task1 = false;2937 coex->freeze = false;2938 coex_stat->wl_connecting = false;2939 2940 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n",2941 __func__);2942 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);2943 }2944}2945 2946void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)2947{2948 struct rtw_coex *coex = &rtwdev->coex;2949 struct rtw_coex_stat *coex_stat = &coex->stat;2950 2951 if (coex->manual_control || coex->stop_dm)2952 return;2953 2954 if (type == COEX_MEDIA_CONNECT_5G) {2955 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__);2956 2957 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);2958 2959 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);2960 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);2961 } else if (type == COEX_MEDIA_CONNECT) {2962 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__);2963 2964 coex_stat->wl_connecting = false;2965 2966 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);2967 2968 /* Force antenna setup for no scan result issue */2969 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);2970 2971 /* Set CCK Rx high Pri */2972 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);2973 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);2974 } else {2975 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n",2976 __func__);2977 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);2978 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);2979 }2980 2981 rtw_coex_update_wl_ch_info(rtwdev, type);2982}2983 2984void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)2985{2986 const struct rtw_chip_info *chip = rtwdev->chip;2987 struct rtw_coex *coex = &rtwdev->coex;2988 struct rtw_coex_stat *coex_stat = &coex->stat;2989 struct rtw_coex_dm *coex_dm = &coex->dm;2990 u32 bt_relink_time;2991 u8 i, rsp_source = 0, type;2992 bool inq_page = false;2993 2994 rsp_source = buf[0] & 0xf;2995 if (rsp_source >= COEX_BTINFO_SRC_MAX)2996 return;2997 coex_stat->cnt_bt_info_c2h[rsp_source]++;2998 2999 if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {3000 coex_stat->bt_iqk_state = buf[1];3001 if (coex_stat->bt_iqk_state == 0)3002 coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;3003 else if (coex_stat->bt_iqk_state == 2)3004 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;3005 3006 rtw_dbg(rtwdev, RTW_DBG_COEX,3007 "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",3008 buf[1]);3009 3010 return;3011 }3012 3013 if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {3014 rtw_dbg(rtwdev, RTW_DBG_COEX,3015 "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",3016 buf[1], buf[2]);3017 3018 rtw_coex_monitor_bt_enable(rtwdev);3019 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {3020 coex_stat->bt_disabled_pre = coex_stat->bt_disabled;3021 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);3022 }3023 return;3024 }3025 3026 if (rsp_source == COEX_BTINFO_SRC_H2C60) {3027 rtw_dbg(rtwdev, RTW_DBG_COEX,3028 "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",3029 buf[1], buf[2], buf[3], buf[4], buf[5]);3030 3031 for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++)3032 coex_dm->fw_tdma_para[i - 1] = buf[i];3033 return;3034 }3035 3036 if (rsp_source == COEX_BTINFO_SRC_WL_FW) {3037 rtw_dbg(rtwdev, RTW_DBG_COEX,3038 "[BTCoex], bt_info reply by WL FW\n");3039 3040 rtw_coex_update_bt_link_info(rtwdev);3041 return;3042 }3043 3044 if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||3045 rsp_source == COEX_BTINFO_SRC_BT_ACT) {3046 if (coex_stat->bt_disabled) {3047 coex_stat->bt_disabled = false;3048 coex_stat->bt_reenable = true;3049 ieee80211_queue_delayed_work(rtwdev->hw,3050 &coex->bt_reenable_work,3051 15 * HZ);3052 rtw_dbg(rtwdev, RTW_DBG_COEX,3053 "[BTCoex], BT enable detected by bt_info\n");3054 }3055 }3056 3057 if (length != COEX_BTINFO_LENGTH) {3058 rtw_dbg(rtwdev, RTW_DBG_COEX,3059 "[BTCoex], Bt_info length = %d invalid!!\n", length);3060 3061 return;3062 }3063 3064 rtw_dbg(rtwdev, RTW_DBG_COEX,3065 "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",3066 buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);3067 3068 for (i = 0; i < COEX_BTINFO_LENGTH; i++)3069 coex_stat->bt_info_c2h[rsp_source][i] = buf[i];3070 3071 /* get the same info from bt, skip it */3072 if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&3073 coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&3074 coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&3075 coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&3076 coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&3077 coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) {3078 rtw_dbg(rtwdev, RTW_DBG_COEX,3079 "[BTCoex], Return because Btinfo duplicate!!\n");3080 return;3081 }3082 3083 coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];3084 coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];3085 coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];3086 coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];3087 coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];3088 coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];3089 3090 /* 0xff means BT is under WHCK test */3091 coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);3092 3093 inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));3094 3095 if (inq_page != coex_stat->bt_inq_page) {3096 cancel_delayed_work_sync(&coex->bt_remain_work);3097 coex_stat->bt_inq_page = inq_page;3098 3099 if (inq_page)3100 coex_stat->bt_inq_remain = true;3101 else3102 ieee80211_queue_delayed_work(rtwdev->hw,3103 &coex->bt_remain_work,3104 4 * HZ);3105 }3106 coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));3107 if (chip->ble_hid_profile_support) {3108 if (coex_stat->bt_info_lb2 & BIT(5)) {3109 if (coex_stat->bt_info_hb1 & BIT(0)) {3110 /*BLE HID*/3111 coex_stat->bt_ble_hid_exist = true;3112 } else {3113 coex_stat->bt_ble_hid_exist = false;3114 }3115 coex_stat->bt_ble_exist = false;3116 } else if (coex_stat->bt_info_hb1 & BIT(0)) {3117 /*RCU*/3118 coex_stat->bt_ble_hid_exist = false;3119 coex_stat->bt_ble_exist = true;3120 } else {3121 coex_stat->bt_ble_hid_exist = false;3122 coex_stat->bt_ble_exist = false;3123 }3124 } else {3125 if (coex_stat->bt_info_hb1 & BIT(0)) {3126 if (coex_stat->bt_hid_slot == 1 &&3127 coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx &&3128 coex_stat->hi_pri_rx < 100) {3129 coex_stat->bt_ble_hid_exist = true;3130 coex_stat->bt_ble_exist = false;3131 } else {3132 coex_stat->bt_ble_hid_exist = false;3133 coex_stat->bt_ble_exist = true;3134 }3135 } else {3136 coex_stat->bt_ble_hid_exist = false;3137 coex_stat->bt_ble_exist = false;3138 }3139 }3140 3141 coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;3142 if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)3143 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;3144 3145 coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));3146 coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));3147 if (coex_stat->bt_inq)3148 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;3149 3150 coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));3151 if (coex_stat->bt_page)3152 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;3153 3154 /* unit: % (value-100 to translate to unit: dBm in coex info) */3155 if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {3156 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;3157 } else {3158 if (coex_stat->bt_info_hb0 <= 127)3159 coex_stat->bt_rssi = 100;3160 else if (256 - coex_stat->bt_info_hb0 <= 100)3161 coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);3162 else3163 coex_stat->bt_rssi = 0;3164 }3165 3166 if (coex_stat->bt_info_hb1 & BIT(1))3167 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;3168 3169 if (coex_stat->bt_info_hb1 & BIT(2)) {3170 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;3171 coex_stat->bt_setup_link = true;3172 if (coex_stat->bt_reenable)3173 bt_relink_time = 6 * HZ;3174 else3175 bt_relink_time = 1 * HZ;3176 3177 ieee80211_queue_delayed_work(rtwdev->hw,3178 &coex->bt_relink_work,3179 bt_relink_time);3180 3181 rtw_dbg(rtwdev, RTW_DBG_COEX,3182 "[BTCoex], Re-Link start in BT info!!\n");3183 }3184 3185 if (coex_stat->bt_info_hb1 & BIT(3))3186 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;3187 3188 coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));3189 coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));3190 if (coex_stat->bt_info_hb1 & BIT(6))3191 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;3192 3193 coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));3194 /* for multi_link = 0 but bt pkt remain exist */3195 /* Use PS-TDMA to protect WL RX */3196 if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) {3197 coex_stat->bt_multi_link_remain = true;3198 ieee80211_queue_delayed_work(rtwdev->hw,3199 &coex->bt_multi_link_remain_work,3200 3 * HZ);3201 }3202 coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link;3203 3204 /* resend wifi info to bt, it is reset and lost the info */3205 if (coex_stat->bt_info_hb1 & BIT(1)) {3206 rtw_dbg(rtwdev, RTW_DBG_COEX,3207 "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");3208 3209 if (coex_stat->wl_connected)3210 type = COEX_MEDIA_CONNECT;3211 else3212 type = COEX_MEDIA_DISCONNECT;3213 rtw_coex_update_wl_ch_info(rtwdev, type);3214 }3215 3216 /* if ignore_wlan_act && not set_up_link */3217 if ((coex_stat->bt_info_hb1 & BIT(3)) &&3218 (!(coex_stat->bt_info_hb1 & BIT(2)))) {3219 rtw_dbg(rtwdev, RTW_DBG_COEX,3220 "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");3221 rtw_coex_ignore_wlan_act(rtwdev, false);3222 }3223 3224 coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));3225 if (coex_stat->bt_info_hb2 & BIT(1))3226 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;3227 3228 coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);3229 coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));3230 coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;3231 coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;3232 if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)3233 coex_stat->bt_418_hid_exist = true;3234 else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1)3235 coex_stat->bt_418_hid_exist = false;3236 3237 if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)3238 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);3239 else3240 coex_stat->bt_a2dp_bitpool = 0;3241 3242 coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));3243 3244 rtw_coex_update_bt_link_info(rtwdev);3245 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);3246}3247 3248#define COEX_BT_HIDINFO_MTK 0x463249static const u8 coex_bt_hidinfo_ps[] = {0x57, 0x69, 0x72};3250static const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f};3251 3252void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)3253{3254 const struct rtw_chip_info *chip = rtwdev->chip;3255 struct rtw_coex *coex = &rtwdev->coex;3256 struct rtw_coex_stat *coex_stat = &coex->stat;3257 struct rtw_coex_hid *hidinfo;3258 struct rtw_coex_hid_info_a *hida;3259 struct rtw_coex_hid_handle_list *hl, *bhl;3260 u8 sub_id = buf[2], gamehid_cnt = 0, handle, i;3261 bool cur_game_hid_exist, complete;3262 3263 if (!chip->wl_mimo_ps_support &&3264 (sub_id == COEX_BT_HIDINFO_LIST || sub_id == COEX_BT_HIDINFO_A))3265 return;3266 3267 rtw_dbg(rtwdev, RTW_DBG_COEX,3268 "[BTCoex], HID info notify, sub_id = 0x%x\n", sub_id);3269 3270 switch (sub_id) {3271 case COEX_BT_HIDINFO_LIST:3272 hl = &coex_stat->hid_handle_list;3273 bhl = (struct rtw_coex_hid_handle_list *)buf;3274 if (!memcmp(hl, bhl, sizeof(*hl)))3275 return;3276 coex_stat->hid_handle_list = *bhl;3277 memset(&coex_stat->hid_info, 0, sizeof(coex_stat->hid_info));3278 for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {3279 hidinfo = &coex_stat->hid_info[i];3280 if (hl->handle[i] != COEX_BT_HIDINFO_NOTCON &&3281 hl->handle[i] != 0)3282 hidinfo->hid_handle = hl->handle[i];3283 }3284 break;3285 case COEX_BT_HIDINFO_A:3286 hida = (struct rtw_coex_hid_info_a *)buf;3287 handle = hida->handle;3288 for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {3289 hidinfo = &coex_stat->hid_info[i];3290 if (hidinfo->hid_handle == handle) {3291 hidinfo->hid_vendor = hida->vendor;3292 memcpy(hidinfo->hid_name, hida->name,3293 sizeof(hidinfo->hid_name));3294 hidinfo->hid_info_completed = true;3295 break;3296 }3297 }3298 break;3299 }3300 for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {3301 hidinfo = &coex_stat->hid_info[i];3302 complete = hidinfo->hid_info_completed;3303 handle = hidinfo->hid_handle;3304 if (!complete || handle == COEX_BT_HIDINFO_NOTCON ||3305 handle == 0 || handle >= COEX_BT_BLE_HANDLE_THRS) {3306 hidinfo->is_game_hid = false;3307 continue;3308 }3309 3310 if (hidinfo->hid_vendor == COEX_BT_HIDINFO_MTK) {3311 if ((memcmp(hidinfo->hid_name,3312 coex_bt_hidinfo_ps,3313 COEX_BT_HIDINFO_NAME)) == 0)3314 hidinfo->is_game_hid = true;3315 else if ((memcmp(hidinfo->hid_name,3316 coex_bt_hidinfo_xb,3317 COEX_BT_HIDINFO_NAME)) == 0)3318 hidinfo->is_game_hid = true;3319 else3320 hidinfo->is_game_hid = false;3321 } else {3322 hidinfo->is_game_hid = false;3323 }3324 if (hidinfo->is_game_hid)3325 gamehid_cnt++;3326 }3327 3328 if (gamehid_cnt > 0)3329 cur_game_hid_exist = true;3330 else3331 cur_game_hid_exist = false;3332 3333 if (cur_game_hid_exist != coex_stat->bt_game_hid_exist) {3334 coex_stat->bt_game_hid_exist = cur_game_hid_exist;3335 rtw_dbg(rtwdev, RTW_DBG_COEX,3336 "[BTCoex], HID info changed!bt_game_hid_exist = %d!\n",3337 coex_stat->bt_game_hid_exist);3338 rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);3339 }3340}3341 3342void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev)3343{3344 const struct rtw_chip_info *chip = rtwdev->chip;3345 struct rtw_coex *coex = &rtwdev->coex;3346 struct rtw_coex_stat *coex_stat = &coex->stat;3347 struct rtw_coex_hid *hidinfo;3348 u8 i, handle;3349 bool complete;3350 3351 if (!chip->wl_mimo_ps_support || coex_stat->wl_under_ips ||3352 (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl))3353 return;3354 3355 if (!coex_stat->bt_hid_exist &&3356 !((coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION) &&3357 (coex_stat->hi_pri_tx + coex_stat->hi_pri_rx >3358 COEX_BT_GAMEHID_CNT)))3359 return;3360 3361 rtw_fw_coex_query_hid_info(rtwdev, COEX_BT_HIDINFO_LIST, 0);3362 3363 for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {3364 hidinfo = &coex_stat->hid_info[i];3365 complete = hidinfo->hid_info_completed;3366 handle = hidinfo->hid_handle;3367 if (handle == 0 || handle == COEX_BT_HIDINFO_NOTCON ||3368 handle >= COEX_BT_BLE_HANDLE_THRS || complete)3369 continue;3370 3371 rtw_fw_coex_query_hid_info(rtwdev,3372 COEX_BT_HIDINFO_A,3373 handle);3374 }3375}3376 3377void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)3378{3379 struct rtw_coex *coex = &rtwdev->coex;3380 struct rtw_coex_stat *coex_stat = &coex->stat;3381 u8 val;3382 int i;3383 3384 rtw_dbg(rtwdev, RTW_DBG_COEX,3385 "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",3386 buf, length);3387 if (WARN(length < 8, "invalid wl info c2h length\n"))3388 return;3389 3390 if (buf[0] != 0x08)3391 return;3392 3393 for (i = 1; i < 8; i++) {3394 val = coex_stat->wl_fw_dbg_info_pre[i];3395 if (buf[i] >= val)3396 coex_stat->wl_fw_dbg_info[i] = buf[i] - val;3397 else3398 coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i];3399 3400 coex_stat->wl_fw_dbg_info_pre[i] = buf[i];3401 }3402 3403 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;3404 rtw_coex_wl_ccklock_action(rtwdev);3405 rtw_coex_wl_ccklock_detect(rtwdev);3406}3407 3408void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)3409{3410 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);3411}3412 3413void rtw_coex_wl_status_check(struct rtw_dev *rtwdev)3414{3415 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3416 3417 if ((coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) ||3418 coex_stat->wl_under_ips)3419 return;3420 3421 rtw_coex_monitor_bt_ctr(rtwdev);3422}3423 3424void rtw_coex_bt_relink_work(struct work_struct *work)3425{3426 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3427 coex.bt_relink_work.work);3428 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3429 3430 mutex_lock(&rtwdev->mutex);3431 coex_stat->bt_setup_link = false;3432 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);3433 mutex_unlock(&rtwdev->mutex);3434}3435 3436void rtw_coex_bt_reenable_work(struct work_struct *work)3437{3438 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3439 coex.bt_reenable_work.work);3440 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3441 3442 mutex_lock(&rtwdev->mutex);3443 coex_stat->bt_reenable = false;3444 mutex_unlock(&rtwdev->mutex);3445}3446 3447void rtw_coex_defreeze_work(struct work_struct *work)3448{3449 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3450 coex.defreeze_work.work);3451 struct rtw_coex *coex = &rtwdev->coex;3452 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3453 3454 mutex_lock(&rtwdev->mutex);3455 coex->freeze = false;3456 coex_stat->wl_hi_pri_task1 = false;3457 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);3458 mutex_unlock(&rtwdev->mutex);3459}3460 3461void rtw_coex_wl_remain_work(struct work_struct *work)3462{3463 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3464 coex.wl_remain_work.work);3465 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3466 3467 mutex_lock(&rtwdev->mutex);3468 coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);3469 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);3470 mutex_unlock(&rtwdev->mutex);3471}3472 3473void rtw_coex_bt_remain_work(struct work_struct *work)3474{3475 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3476 coex.bt_remain_work.work);3477 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3478 3479 mutex_lock(&rtwdev->mutex);3480 coex_stat->bt_inq_remain = coex_stat->bt_inq_page;3481 rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);3482 mutex_unlock(&rtwdev->mutex);3483}3484 3485void rtw_coex_wl_connecting_work(struct work_struct *work)3486{3487 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3488 coex.wl_connecting_work.work);3489 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3490 3491 mutex_lock(&rtwdev->mutex);3492 coex_stat->wl_connecting = false;3493 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n");3494 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);3495 mutex_unlock(&rtwdev->mutex);3496}3497 3498void rtw_coex_bt_multi_link_remain_work(struct work_struct *work)3499{3500 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3501 coex.bt_multi_link_remain_work.work);3502 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3503 3504 mutex_lock(&rtwdev->mutex);3505 coex_stat->bt_multi_link_remain = false;3506 mutex_unlock(&rtwdev->mutex);3507}3508 3509void rtw_coex_wl_ccklock_work(struct work_struct *work)3510{3511 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,3512 coex.wl_ccklock_work.work);3513 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;3514 3515 mutex_lock(&rtwdev->mutex);3516 coex_stat->wl_cck_lock = false;3517 mutex_unlock(&rtwdev->mutex);3518}3519 3520#ifdef CONFIG_RTW88_DEBUGFS3521#define INFO_SIZE 803522 3523#define case_BTINFO(src) \3524 case COEX_BTINFO_SRC_##src: return #src3525 3526static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)3527{3528 switch (bt_info_src) {3529 case_BTINFO(WL_FW);3530 case_BTINFO(BT_RSP);3531 case_BTINFO(BT_ACT);3532 default:3533 return "Unknown";3534 }3535}3536 3537#define case_RSN(src) \3538 case COEX_RSN_##src: return #src3539 3540static const char *rtw_coex_get_reason_string(u8 reason)3541{3542 switch (reason) {3543 case_RSN(2GSCANSTART);3544 case_RSN(5GSCANSTART);3545 case_RSN(SCANFINISH);3546 case_RSN(2GSWITCHBAND);3547 case_RSN(5GSWITCHBAND);3548 case_RSN(2GCONSTART);3549 case_RSN(5GCONSTART);3550 case_RSN(2GCONFINISH);3551 case_RSN(5GCONFINISH);3552 case_RSN(2GMEDIA);3553 case_RSN(5GMEDIA);3554 case_RSN(MEDIADISCON);3555 case_RSN(BTINFO);3556 case_RSN(LPS);3557 case_RSN(WLSTATUS);3558 default:3559 return "Unknown";3560 }3561}3562 3563static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,3564 u32 wl_reg_6c4)3565{3566 const struct rtw_chip_info *chip = rtwdev->chip;3567 struct rtw_efuse *efuse = &rtwdev->efuse;3568 u8 ans = 0xFF;3569 u8 n, i;3570 u32 load_bt_val;3571 u32 load_wl_val;3572 bool share_ant = efuse->share_ant;3573 3574 if (share_ant)3575 n = chip->table_sant_num;3576 else3577 n = chip->table_nsant_num;3578 3579 for (i = 0; i < n; i++) {3580 if (share_ant) {3581 load_bt_val = chip->table_sant[i].bt;3582 load_wl_val = chip->table_sant[i].wl;3583 } else {3584 load_bt_val = chip->table_nsant[i].bt;3585 load_wl_val = chip->table_nsant[i].wl;3586 }3587 3588 if (wl_reg_6c0 == load_bt_val &&3589 wl_reg_6c4 == load_wl_val) {3590 ans = i;3591 if (!share_ant)3592 ans += 100;3593 break;3594 }3595 }3596 3597 return ans;3598}3599 3600static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)3601{3602 const struct rtw_chip_info *chip = rtwdev->chip;3603 struct rtw_efuse *efuse = &rtwdev->efuse;3604 u8 ans = 0xFF;3605 u8 n, i, j;3606 u8 load_cur_tab_val;3607 bool valid = false;3608 bool share_ant = efuse->share_ant;3609 3610 if (share_ant)3611 n = chip->tdma_sant_num;3612 else3613 n = chip->tdma_nsant_num;3614 3615 for (i = 0; i < n; i++) {3616 valid = false;3617 for (j = 0; j < 5; j++) {3618 if (share_ant)3619 load_cur_tab_val = chip->tdma_sant[i].para[j];3620 else3621 load_cur_tab_val = chip->tdma_nsant[i].para[j];3622 3623 if (*(tdma_para + j) != load_cur_tab_val)3624 break;3625 3626 if (j == 4)3627 valid = true;3628 }3629 if (valid) {3630 ans = i;3631 break;3632 }3633 }3634 3635 return ans;3636}3637 3638static int rtw_coex_addr_info(struct rtw_dev *rtwdev,3639 const struct rtw_reg_domain *reg,3640 char addr_info[], int n)3641{3642 const char *rf_prefix = "";3643 const char *sep = n == 0 ? "" : "/ ";3644 int ffs, fls;3645 int max_fls;3646 3647 if (INFO_SIZE - n <= 0)3648 return 0;3649 3650 switch (reg->domain) {3651 case RTW_REG_DOMAIN_MAC32:3652 max_fls = 31;3653 break;3654 case RTW_REG_DOMAIN_MAC16:3655 max_fls = 15;3656 break;3657 case RTW_REG_DOMAIN_MAC8:3658 max_fls = 7;3659 break;3660 case RTW_REG_DOMAIN_RF_A:3661 case RTW_REG_DOMAIN_RF_B:3662 rf_prefix = "RF_";3663 max_fls = 19;3664 break;3665 default:3666 return 0;3667 }3668 3669 ffs = __ffs(reg->mask);3670 fls = __fls(reg->mask);3671 3672 if (ffs == 0 && fls == max_fls)3673 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",3674 sep, rf_prefix, reg->addr);3675 else if (ffs == fls)3676 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",3677 sep, rf_prefix, reg->addr, ffs);3678 else3679 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",3680 sep, rf_prefix, reg->addr, fls, ffs);3681}3682 3683static int rtw_coex_val_info(struct rtw_dev *rtwdev,3684 const struct rtw_reg_domain *reg,3685 char val_info[], int n)3686{3687 const char *sep = n == 0 ? "" : "/ ";3688 u8 rf_path;3689 3690 if (INFO_SIZE - n <= 0)3691 return 0;3692 3693 switch (reg->domain) {3694 case RTW_REG_DOMAIN_MAC32:3695 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,3696 rtw_read32_mask(rtwdev, reg->addr, reg->mask));3697 case RTW_REG_DOMAIN_MAC16:3698 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,3699 rtw_read16_mask(rtwdev, reg->addr, reg->mask));3700 case RTW_REG_DOMAIN_MAC8:3701 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,3702 rtw_read8_mask(rtwdev, reg->addr, reg->mask));3703 case RTW_REG_DOMAIN_RF_A:3704 rf_path = RF_PATH_A;3705 break;3706 case RTW_REG_DOMAIN_RF_B:3707 rf_path = RF_PATH_B;3708 break;3709 default:3710 return 0;3711 }3712 3713 /* only RF go through here */3714 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,3715 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));3716}3717 3718static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)3719{3720 const struct rtw_chip_info *chip = rtwdev->chip;3721 const struct rtw_reg_domain *reg;3722 char addr_info[INFO_SIZE];3723 int n_addr = 0;3724 char val_info[INFO_SIZE];3725 int n_val = 0;3726 int i;3727 3728 for (i = 0; i < chip->coex_info_hw_regs_num; i++) {3729 reg = &chip->coex_info_hw_regs[i];3730 3731 n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);3732 n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);3733 3734 if (reg->domain == RTW_REG_DOMAIN_NL) {3735 seq_printf(m, "%-40s = %s\n", addr_info, val_info);3736 n_addr = 0;3737 n_val = 0;3738 }3739 }3740 3741 if (n_addr != 0 && n_val != 0)3742 seq_printf(m, "%-40s = %s\n", addr_info, val_info);3743}3744 3745static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,3746 u8 type, u16 addr, u16 *val)3747{3748 struct rtw_coex_info_req req = {0};3749 struct sk_buff *skb;3750 __le16 le_addr;3751 u8 *payload;3752 3753 le_addr = cpu_to_le16(addr);3754 req.op_code = BT_MP_INFO_OP_READ_REG;3755 req.para1 = type;3756 req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));3757 req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));3758 skb = rtw_coex_info_request(rtwdev, &req);3759 if (!skb) {3760 *val = 0xeaea;3761 return false;3762 }3763 3764 payload = get_payload_from_coex_resp(skb);3765 *val = GET_COEX_RESP_BT_REG_VAL(payload);3766 dev_kfree_skb_any(skb);3767 3768 return true;3769}3770 3771static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,3772 u32 *patch_version)3773{3774 struct rtw_coex_info_req req = {0};3775 struct sk_buff *skb;3776 u8 *payload;3777 3778 req.op_code = BT_MP_INFO_OP_PATCH_VER;3779 skb = rtw_coex_info_request(rtwdev, &req);3780 if (!skb)3781 return false;3782 3783 payload = get_payload_from_coex_resp(skb);3784 *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);3785 dev_kfree_skb_any(skb);3786 3787 return true;3788}3789 3790static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,3791 u32 *supported_version)3792{3793 struct rtw_coex_info_req req = {0};3794 struct sk_buff *skb;3795 u8 *payload;3796 3797 req.op_code = BT_MP_INFO_OP_SUPP_VER;3798 skb = rtw_coex_info_request(rtwdev, &req);3799 if (!skb)3800 return false;3801 3802 payload = get_payload_from_coex_resp(skb);3803 *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);3804 dev_kfree_skb_any(skb);3805 3806 return true;3807}3808 3809static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,3810 u32 *supported_feature)3811{3812 struct rtw_coex_info_req req = {0};3813 struct sk_buff *skb;3814 u8 *payload;3815 3816 req.op_code = BT_MP_INFO_OP_SUPP_FEAT;3817 skb = rtw_coex_info_request(rtwdev, &req);3818 if (!skb)3819 return false;3820 3821 payload = get_payload_from_coex_resp(skb);3822 *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);3823 dev_kfree_skb_any(skb);3824 3825 return true;3826}3827 3828struct rtw_coex_sta_stat_iter_data {3829 struct rtw_vif *rtwvif;3830 struct seq_file *file;3831};3832 3833static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)3834{3835 struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;3836 struct rtw_vif *rtwvif = sta_iter_data->rtwvif;3837 struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;3838 struct seq_file *m = sta_iter_data->file;3839 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);3840 u8 rssi;3841 3842 if (si->vif != vif)3843 return;3844 3845 rssi = ewma_rssi_read(&si->avg_rssi);3846 seq_printf(m, "\tPeer %3d\n", si->mac_id);3847 seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);3848 seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);3849}3850 3851struct rtw_coex_vif_stat_iter_data {3852 struct rtw_dev *rtwdev;3853 struct seq_file *file;3854};3855 3856static void rtw_coex_vif_stat_iter(void *data, u8 *mac,3857 struct ieee80211_vif *vif)3858{3859 struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;3860 struct rtw_coex_sta_stat_iter_data sta_iter_data;3861 struct rtw_dev *rtwdev = vif_iter_data->rtwdev;3862 struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;3863 struct seq_file *m = vif_iter_data->file;3864 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;3865 3866 seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);3867 seq_printf(m, "\t%-32s = %d\n",3868 "Beacon interval", bss_conf->beacon_int);3869 seq_printf(m, "\t%-32s = %d\n",3870 "Network Type", rtwvif->net_type);3871 3872 sta_iter_data.rtwvif = rtwvif;3873 sta_iter_data.file = m;3874 rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,3875 &sta_iter_data);3876}3877 3878#define case_WLINK(src) \3879 case COEX_WLINK_##src: return #src3880 3881static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)3882{3883 switch (coex_wl_link_mode) {3884 case_WLINK(2G1PORT);3885 case_WLINK(5G);3886 case_WLINK(2GFREE);3887 default:3888 return "Unknown";3889 }3890}3891 3892void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)3893{3894 const struct rtw_chip_info *chip = rtwdev->chip;3895 struct rtw_dm_info *dm_info = &rtwdev->dm_info;3896 struct rtw_coex *coex = &rtwdev->coex;3897 struct rtw_coex_stat *coex_stat = &coex->stat;3898 struct rtw_coex_dm *coex_dm = &coex->dm;3899 struct rtw_hal *hal = &rtwdev->hal;3900 struct rtw_efuse *efuse = &rtwdev->efuse;3901 struct rtw_fw_state *fw = &rtwdev->fw;3902 struct rtw_coex_vif_stat_iter_data vif_iter_data;3903 u8 reason = coex_dm->reason;3904 u8 sys_lte;3905 u16 score_board_WB, score_board_BW;3906 u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;3907 u32 lte_coex, bt_coex;3908 int i;3909 3910 score_board_BW = rtw_coex_read_scbd(rtwdev);3911 score_board_WB = coex_stat->score_board;3912 wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0);3913 wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1);3914 wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE);3915 wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);3916 wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);3917 3918 sys_lte = rtw_read8(rtwdev, 0x73);3919 lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);3920 bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);3921 3922 if (!coex_stat->wl_under_ips &&3923 (!coex_stat->wl_under_lps || coex_stat->wl_force_lps_ctrl) &&3924 !coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {3925 rtw_coex_get_bt_supported_version(rtwdev,3926 &coex_stat->bt_supported_version);3927 rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);3928 rtw_coex_get_bt_supported_feature(rtwdev,3929 &coex_stat->bt_supported_feature);3930 rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);3931 rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);3932 3933 if (coex_stat->patch_ver != 0)3934 coex_stat->bt_mailbox_reply = true;3935 }3936 3937 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);3938 seq_printf(m, "**********************************************\n");3939 seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);3940 seq_printf(m, "**********************************************\n");3941 3942 if (coex->manual_control) {3943 seq_puts(m, "============[Under Manual Control]============\n");3944 seq_puts(m, "==========================================\n");3945 3946 } else if (coex->stop_dm) {3947 seq_puts(m, "============[Coex is STOPPED]============\n");3948 seq_puts(m, "==========================================\n");3949 3950 } else if (coex->freeze) {3951 seq_puts(m, "============[coex_freeze]============\n");3952 seq_puts(m, "==========================================\n");3953 }3954 3955 seq_printf(m, "%-40s = %s/ %d\n",3956 "Mech/ RFE",3957 efuse->share_ant ? "Shared" : "Non-Shared",3958 efuse->rfe_option);3959 seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",3960 "Coex Ver/ BT Dez/ BT Rpt",3961 chip->coex_para_ver, chip->bt_desired_ver,3962 coex_stat->bt_supported_version,3963 coex_stat->bt_disabled ? "(BT disabled)" :3964 coex_stat->bt_supported_version >= chip->bt_desired_ver ?3965 "(Match)" : "(Mismatch)");3966 seq_printf(m, "%-40s = %s/ %u/ %d\n",3967 "Role/ RoleSwCnt/ IgnWL/ Feature",3968 coex_stat->bt_slave ? "Slave" : "Master",3969 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],3970 coex_dm->ignore_wl_act);3971 seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",3972 "WL FW/ BT FW/ BT FW Desired/ KT",3973 fw->version, fw->sub_version,3974 coex_stat->patch_ver,3975 chip->wl_fw_desired_ver, coex_stat->kt_ver + 65);3976 seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",3977 "AFH Map",3978 coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],3979 coex_dm->wl_ch_info[2], hal->current_channel);3980 3981 rtw_debugfs_get_simple_phy_info(m);3982 seq_printf(m, "**********************************************\n");3983 seq_printf(m, "\t\tBT Status\n");3984 seq_printf(m, "**********************************************\n");3985 seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",3986 "BT status/ rssi/ retry/ pop",3987 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :3988 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",3989 coex_stat->bt_rssi - 100,3990 coex_stat->cnt_bt[COEX_CNT_BT_RETRY],3991 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);3992 seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",3993 "Profiles",3994 coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?3995 "A2DP sink," : "A2DP,") : "",3996 coex_stat->bt_hfp_exist ? "HFP," : "",3997 coex_stat->bt_hid_exist ?3998 (coex_stat->bt_ble_exist ? "HID(RCU)," :3999 coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :4000 coex_stat->bt_ble_hid_exist ? "HID(BLE)" :4001 "HID(2/18),") : "",4002 coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?4003 "OPP," : "PAN," : "",4004 coex_stat->bt_ble_voice ? "Voice," : "",4005 coex_stat->bt_multi_link);4006 seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",4007 "Reinit/ Relink/ IgnWl/ Feature",4008 coex_stat->cnt_bt[COEX_CNT_BT_REINIT],4009 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],4010 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],4011 coex_stat->bt_supported_feature);4012 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",4013 "Page/ Inq/ iqk/ iqk fail",4014 coex_stat->cnt_bt[COEX_CNT_BT_PAGE],4015 coex_stat->cnt_bt[COEX_CNT_BT_INQ],4016 coex_stat->cnt_bt[COEX_CNT_BT_IQK],4017 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);4018 seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",4019 "0xae/ 0xac/ score board (W->B)/ (B->W)",4020 coex_stat->bt_reg_vendor_ae,4021 coex_stat->bt_reg_vendor_ac,4022 score_board_WB, score_board_BW);4023 seq_printf(m, "%-40s = %u/%u, %u/%u\n",4024 "Hi-Pri TX/RX, Lo-Pri TX/RX",4025 coex_stat->hi_pri_tx, coex_stat->hi_pri_rx,4026 coex_stat->lo_pri_tx, coex_stat->lo_pri_rx);4027 for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)4028 seq_printf(m, "%-40s = %7ph\n",4029 rtw_coex_get_bt_info_src_string(i),4030 coex_stat->bt_info_c2h[i]);4031 4032 seq_printf(m, "**********************************************\n");4033 seq_printf(m, "\t\tWiFi Status\n");4034 seq_printf(m, "**********************************************\n");4035 seq_printf(m, "%-40s = %d\n",4036 "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));4037 seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",4038 "G_busy/ TX/ RX",4039 coex_stat->wl_gl_busy,4040 rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);4041 seq_printf(m, "%-40s = %u/ %u/ %u\n",4042 "IPS/ Low Power/ PS mode",4043 !test_bit(RTW_FLAG_POWERON, rtwdev->flags),4044 test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),4045 rtwdev->lps_conf.mode);4046 4047 vif_iter_data.rtwdev = rtwdev;4048 vif_iter_data.file = m;4049 rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);4050 4051 if (coex->manual_control) {4052 seq_printf(m, "**********************************************\n");4053 seq_printf(m, "\t\tMechanism (Under Manual)\n");4054 seq_printf(m, "**********************************************\n");4055 seq_printf(m, "%-40s = %5ph (%d)\n",4056 "TDMA Now",4057 coex_dm->fw_tdma_para,4058 rtw_coex_get_tdma_index(rtwdev,4059 &coex_dm->fw_tdma_para[0]));4060 } else {4061 seq_printf(m, "**********************************************\n");4062 seq_printf(m, "\t\tMechanism\n");4063 seq_printf(m, "**********************************************\n");4064 seq_printf(m, "%-40s = %5ph (case-%d)\n",4065 "TDMA",4066 coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);4067 }4068 seq_printf(m, "%-40s = %s/ %s/ %d\n",4069 "Coex Mode/Free Run/Timer base",4070 rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode),4071 coex->freerun ? "Yes" : "No",4072 coex_stat->tdma_timer_base);4073 seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",4074 "Table/ 0x6c0/ 0x6c4/ 0x6c8",4075 coex_dm->cur_table,4076 rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4),4077 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);4078 seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",4079 "0x778/ 0x6cc/ Run Count/ Reason",4080 wl_reg_778, wl_reg_6cc,4081 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN],4082 rtw_coex_get_reason_string(reason));4083 seq_printf(m, "%-40s = %3ph\n",4084 "AFH Map to BT",4085 coex_dm->wl_ch_info);4086 seq_printf(m, "%-40s = %s/ %d\n",4087 "AntDiv/ BtCtrlLPS/ g_busy",4088 coex_stat->wl_force_lps_ctrl ? "On" : "Off",4089 coex_stat->wl_gl_busy);4090 seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",4091 "Null All/ Retry/ Ack/ BT Empty/ BT Late",4092 coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],4093 coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],4094 coex_stat->wl_fw_dbg_info[5]);4095 seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",4096 "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",4097 coex_stat->wl_fw_dbg_info[6],4098 coex_stat->wl_fw_dbg_info[7],4099 coex_stat->wl_slot_extend ? "Yes" : "No",4100 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);4101 seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n",4102 "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",4103 coex_dm->cur_wl_pwr_lvl,4104 coex_dm->cur_bt_pwr_lvl,4105 coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off",4106 coex_dm->cur_bt_lna_lvl);4107 4108 seq_printf(m, "**********************************************\n");4109 seq_printf(m, "\t\tHW setting\n");4110 seq_printf(m, "**********************************************\n");4111 seq_printf(m, "%-40s = %s/ %s\n",4112 "LTE Coex/ Path Owner",4113 lte_coex & BIT(7) ? "ON" : "OFF",4114 sys_lte & BIT(2) ? "WL" : "BT");4115 seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",4116 "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",4117 lte_coex & BIT(12) ? "SW" : "HW",4118 lte_coex & BIT(8) ? "SW" : "HW",4119 lte_coex & BIT(14) ? "SW" : "HW",4120 lte_coex & BIT(10) ? "SW" : "HW",4121 sys_lte & BIT(3) ? "On" : "Off");4122 seq_printf(m, "%-40s = %lu/ %lu\n",4123 "GNT_WL/ GNT_BT",4124 (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);4125 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",4126 "CRC OK CCK/ OFDM/ HT/ VHT",4127 dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,4128 dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);4129 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",4130 "CRC ERR CCK/ OFDM/ HT/ VHT",4131 dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,4132 dm_info->ht_err_cnt, dm_info->vht_err_cnt);4133 seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",4134 "HiPr/ Locking/ Locked/ Noisy",4135 coex_stat->wl_hi_pri_task1 ? "Y" : "N",4136 coex_stat->wl_cck_lock ? "Y" : "N",4137 coex_stat->wl_cck_lock_ever ? "Y" : "N",4138 coex_stat->wl_noisy_level);4139 4140 rtw_coex_set_coexinfo_hw(rtwdev, m);4141 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",4142 "EVM A/ EVM B/ SNR A/ SNR B",4143 -dm_info->rx_evm_dbm[RF_PATH_A],4144 -dm_info->rx_evm_dbm[RF_PATH_B],4145 -dm_info->rx_snr[RF_PATH_A],4146 -dm_info->rx_snr[RF_PATH_B]);4147 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",4148 "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",4149 dm_info->cck_cca_cnt, dm_info->cck_fa_cnt,4150 dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt);4151 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",4152 dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,4153 dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);4154 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",4155 dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,4156 dm_info->ht_err_cnt, dm_info->vht_err_cnt);4157 4158}4159#endif /* CONFIG_RTW88_DEBUGFS */4160