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