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