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