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