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