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