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 12 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state, 13 u8 rssi, u8 rssi_thresh) 14 { 15 struct rtw_chip_info *chip = rtwdev->chip; 16 u8 tol = chip->rssi_tolerance; 17 u8 next_state; 18 19 if (pre_state == COEX_RSSI_STATE_LOW || 20 pre_state == COEX_RSSI_STATE_STAY_LOW) { 21 if (rssi >= (rssi_thresh + tol)) 22 next_state = COEX_RSSI_STATE_HIGH; 23 else 24 next_state = COEX_RSSI_STATE_STAY_LOW; 25 } else { 26 if (rssi < rssi_thresh) 27 next_state = COEX_RSSI_STATE_LOW; 28 else 29 next_state = COEX_RSSI_STATE_STAY_HIGH; 30 } 31 32 return next_state; 33 } 34 35 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev, 36 bool tx_limit_en, bool ampdu_limit_en) 37 { 38 struct rtw_chip_info *chip = rtwdev->chip; 39 struct rtw_coex *coex = &rtwdev->coex; 40 struct rtw_coex_stat *coex_stat = &coex->stat; 41 bool wifi_under_b_mode = false; 42 43 if (!chip->scbd_support) 44 return; 45 46 /* force max tx retry limit = 8 */ 47 if (coex_stat->wl_tx_limit_en == tx_limit_en && 48 coex_stat->wl_ampdu_limit_en == ampdu_limit_en) 49 return; 50 51 if (!coex_stat->wl_tx_limit_en) { 52 coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC); 53 coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH); 54 coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT); 55 } 56 57 if (!coex_stat->wl_ampdu_limit_en) 58 coex_stat->ampdu_max_time = 59 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1); 60 61 coex_stat->wl_tx_limit_en = tx_limit_en; 62 coex_stat->wl_ampdu_limit_en = ampdu_limit_en; 63 64 if (tx_limit_en) { 65 /* set BT polluted packet on for tx rate adaptive, 66 * not including tx retry broken by PTA 67 */ 68 rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); 69 70 /* set queue life time to avoid can't reach tx retry limit 71 * if tx is always broken by GNT_BT 72 */ 73 rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf); 74 rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808); 75 76 /* auto rate fallback step within 8 retries */ 77 if (wifi_under_b_mode) { 78 rtw_write32(rtwdev, REG_DARFRC, 0x1000000); 79 rtw_write32(rtwdev, REG_DARFRCH, 0x1010101); 80 } else { 81 rtw_write32(rtwdev, REG_DARFRC, 0x1000000); 82 rtw_write32(rtwdev, REG_DARFRCH, 0x4030201); 83 } 84 } else { 85 rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); 86 rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf); 87 88 rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit); 89 rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc); 90 rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch); 91 } 92 93 if (ampdu_limit_en) 94 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20); 95 else 96 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 97 coex_stat->ampdu_max_time); 98 } 99 100 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev) 101 { 102 struct rtw_coex *coex = &rtwdev->coex; 103 struct rtw_coex_dm *coex_dm = &coex->dm; 104 struct rtw_coex_stat *coex_stat = &coex->stat; 105 bool tx_limit = false; 106 bool tx_agg_ctrl = false; 107 108 if (coex->under_5g || 109 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 110 /* no need to limit tx */ 111 } else { 112 tx_limit = true; 113 if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist || 114 coex_stat->bt_hid_pair_num > 0) 115 tx_agg_ctrl = true; 116 } 117 118 rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl); 119 } 120 121 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) 122 { 123 struct rtw_coex *coex = &rtwdev->coex; 124 struct rtw_coex_stat *coex_stat = &coex->stat; 125 u8 para[6] = {0}; 126 127 if (coex->stop_dm) 128 return; 129 130 para[0] = COEX_H2C69_WL_LEAKAP; 131 132 if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) { 133 para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */ 134 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 135 coex_stat->wl_slot_extend = false; 136 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 137 return; 138 } 139 140 if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl && 141 !coex_stat->wl_cck_lock_ever) { 142 if (coex_stat->wl_fw_dbg_info[7] <= 5) 143 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++; 144 else 145 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 146 147 if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) { 148 para[1] = 0x1; /* disable 5ms extend */ 149 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 150 coex_stat->wl_slot_extend = false; 151 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 152 } 153 } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) { 154 para[1] = 0x0; /* enable 5ms extend */ 155 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 156 coex_stat->wl_slot_extend = true; 157 } 158 } 159 160 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev) 161 { 162 struct rtw_coex *coex = &rtwdev->coex; 163 struct rtw_coex_stat *coex_stat = &coex->stat; 164 165 /* TODO: wait for rx_rate_change_notify implement */ 166 coex_stat->wl_cck_lock = false; 167 coex_stat->wl_cck_lock_pre = false; 168 coex_stat->wl_cck_lock_ever = false; 169 } 170 171 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) 172 { 173 struct rtw_coex *coex = &rtwdev->coex; 174 struct rtw_coex_stat *coex_stat = &coex->stat; 175 struct rtw_dm_info *dm_info = &rtwdev->dm_info; 176 u32 cnt_cck; 177 178 /* wifi noisy environment identification */ 179 cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt; 180 181 if (!coex_stat->wl_gl_busy) { 182 if (cnt_cck > 250) { 183 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5) 184 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++; 185 186 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) { 187 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; 188 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; 189 } 190 } else if (cnt_cck < 100) { 191 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5) 192 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++; 193 194 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) { 195 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; 196 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; 197 } 198 } else { 199 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5) 200 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++; 201 202 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) { 203 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; 204 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; 205 } 206 } 207 208 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) 209 coex_stat->wl_noisy_level = 2; 210 else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) 211 coex_stat->wl_noisy_level = 1; 212 else 213 coex_stat->wl_noisy_level = 0; 214 } 215 } 216 217 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) 218 { 219 struct rtw_coex *coex = &rtwdev->coex; 220 struct rtw_coex_stat *coex_stat = &coex->stat; 221 u8 para[2] = {0}; 222 223 if (coex_stat->tdma_timer_base == type) 224 return; 225 226 coex_stat->tdma_timer_base = type; 227 228 para[0] = COEX_H2C69_TDMA_SLOT; 229 230 if (type == 3) /* 4-slot */ 231 para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */ 232 else /* 2-slot */ 233 para[1] = PARA1_H2C69_TDMA_2SLOT; 234 235 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 236 237 /* no 5ms_wl_slot_extend for 4-slot mode */ 238 if (coex_stat->tdma_timer_base == 3) 239 rtw_coex_wl_ccklock_action(rtwdev); 240 } 241 242 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap, 243 u8 data) 244 { 245 u32 addr; 246 247 addr = REG_BT_COEX_TABLE_H + (bitmap / 8); 248 bitmap = bitmap % 8; 249 250 rtw_write8_mask(rtwdev, addr, BIT(bitmap), data); 251 } 252 253 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set) 254 { 255 struct rtw_chip_info *chip = rtwdev->chip; 256 struct rtw_coex *coex = &rtwdev->coex; 257 struct rtw_coex_stat *coex_stat = &coex->stat; 258 u16 val = 0x2; 259 260 if (!chip->scbd_support) 261 return; 262 263 val |= coex_stat->score_board; 264 265 /* for 8822b, scbd[10] is CQDDR on 266 * for 8822c, scbd[10] is no fix 2M 267 */ 268 if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) { 269 if (set) 270 val &= ~COEX_SCBD_FIX2M; 271 else 272 val |= COEX_SCBD_FIX2M; 273 } else { 274 if (set) 275 val |= bitpos; 276 else 277 val &= ~bitpos; 278 } 279 280 if (val != coex_stat->score_board) { 281 coex_stat->score_board = val; 282 val |= BIT_BT_INT_EN; 283 rtw_write16(rtwdev, REG_WIFI_BT_INFO, val); 284 } 285 } 286 287 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev) 288 { 289 struct rtw_chip_info *chip = rtwdev->chip; 290 291 if (!chip->scbd_support) 292 return 0; 293 294 return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN); 295 } 296 297 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) 298 { 299 struct rtw_chip_info *chip = rtwdev->chip; 300 struct rtw_coex *coex = &rtwdev->coex; 301 struct rtw_coex_stat *coex_stat = &coex->stat; 302 struct rtw_coex_rfe *coex_rfe = &coex->rfe; 303 u8 cnt = 0; 304 u32 wait_cnt; 305 bool btk, wlk; 306 307 if (coex_rfe->wlg_at_btg && chip->scbd_support && 308 coex_stat->bt_iqk_state != 0xff) { 309 wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY; 310 do { 311 /* BT RFK */ 312 btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK); 313 314 /* WL RFK */ 315 wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK); 316 317 if (!btk && !wlk) 318 break; 319 320 mdelay(COEX_MIN_DELAY); 321 } while (++cnt < wait_cnt); 322 323 if (cnt >= wait_cnt) 324 coex_stat->bt_iqk_state = 0xff; 325 } 326 } 327 328 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) 329 { 330 struct rtw_coex *coex = &rtwdev->coex; 331 struct rtw_coex_stat *coex_stat = &coex->stat; 332 333 if (coex_stat->bt_disabled) 334 return; 335 336 rtw_fw_query_bt_info(rtwdev); 337 } 338 339 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) 340 { 341 struct rtw_chip_info *chip = rtwdev->chip; 342 struct rtw_coex *coex = &rtwdev->coex; 343 struct rtw_coex_stat *coex_stat = &coex->stat; 344 struct rtw_coex_dm *coex_dm = &coex->dm; 345 bool bt_disabled = false; 346 u16 score_board; 347 348 if (chip->scbd_support) { 349 score_board = rtw_coex_read_scbd(rtwdev); 350 bt_disabled = !(score_board & COEX_SCBD_ONOFF); 351 } 352 353 if (coex_stat->bt_disabled != bt_disabled) { 354 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n", 355 coex_stat->bt_disabled, bt_disabled); 356 357 coex_stat->bt_disabled = bt_disabled; 358 coex_stat->bt_ble_scan_type = 0; 359 coex_dm->cur_bt_lna_lvl = 0; 360 } 361 362 if (!coex_stat->bt_disabled) { 363 coex_stat->bt_reenable = true; 364 ieee80211_queue_delayed_work(rtwdev->hw, 365 &coex->bt_reenable_work, 15 * HZ); 366 } else { 367 coex_stat->bt_mailbox_reply = false; 368 coex_stat->bt_reenable = false; 369 } 370 } 371 372 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason) 373 { 374 struct rtw_coex *coex = &rtwdev->coex; 375 struct rtw_coex_stat *coex_stat = &coex->stat; 376 struct rtw_coex_dm *coex_dm = &coex->dm; 377 struct rtw_chip_info *chip = rtwdev->chip; 378 struct rtw_traffic_stats *stats = &rtwdev->stats; 379 bool is_5G = false; 380 bool scan = false, link = false; 381 int i; 382 u8 rssi_state; 383 u8 rssi_step; 384 u8 rssi; 385 386 scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags); 387 coex_stat->wl_connected = !!rtwdev->sta_cnt; 388 coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 389 390 if (stats->tx_throughput > stats->rx_throughput) 391 coex_stat->wl_tput_dir = COEX_WL_TPUT_TX; 392 else 393 coex_stat->wl_tput_dir = COEX_WL_TPUT_RX; 394 395 if (scan || link || reason == COEX_RSN_2GCONSTART || 396 reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND) 397 coex_stat->wl_linkscan_proc = true; 398 else 399 coex_stat->wl_linkscan_proc = false; 400 401 rtw_coex_wl_noisy_detect(rtwdev); 402 403 for (i = 0; i < 4; i++) { 404 rssi_state = coex_dm->wl_rssi_state[i]; 405 rssi_step = chip->wl_rssi_step[i]; 406 rssi = rtwdev->dm_info.min_rssi; 407 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 408 rssi, rssi_step); 409 coex_dm->wl_rssi_state[i] = rssi_state; 410 } 411 412 switch (reason) { 413 case COEX_RSN_5GSCANSTART: 414 case COEX_RSN_5GSWITCHBAND: 415 case COEX_RSN_5GCONSTART: 416 417 is_5G = true; 418 break; 419 case COEX_RSN_2GSCANSTART: 420 case COEX_RSN_2GSWITCHBAND: 421 case COEX_RSN_2GCONSTART: 422 423 is_5G = false; 424 break; 425 default: 426 if (rtwdev->hal.current_band_type == RTW_BAND_5G) 427 is_5G = true; 428 else 429 is_5G = false; 430 break; 431 } 432 433 coex->under_5g = is_5G; 434 } 435 436 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp) 437 { 438 struct rtw_c2h_cmd *c2h; 439 u32 pkt_offset; 440 441 pkt_offset = *((u32 *)resp->cb); 442 c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset); 443 444 return c2h->payload; 445 } 446 447 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb) 448 { 449 struct rtw_coex *coex = &rtwdev->coex; 450 u8 *payload = get_payload_from_coex_resp(skb); 451 452 if (payload[0] != COEX_RESP_ACK_BY_WL_FW) 453 return; 454 455 skb_queue_tail(&coex->queue, skb); 456 wake_up(&coex->wait); 457 } 458 459 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, 460 struct rtw_coex_info_req *req) 461 { 462 struct rtw_coex *coex = &rtwdev->coex; 463 struct sk_buff *skb_resp = NULL; 464 465 mutex_lock(&coex->mutex); 466 467 rtw_fw_query_bt_mp_info(rtwdev, req); 468 469 if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue), 470 COEX_REQUEST_TIMEOUT)) { 471 rtw_err(rtwdev, "coex request time out\n"); 472 goto out; 473 } 474 475 skb_resp = skb_dequeue(&coex->queue); 476 if (!skb_resp) { 477 rtw_err(rtwdev, "failed to get coex info response\n"); 478 goto out; 479 } 480 481 out: 482 mutex_unlock(&coex->mutex); 483 return skb_resp; 484 } 485 486 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type) 487 { 488 struct rtw_coex_info_req req = {0}; 489 struct sk_buff *skb; 490 u8 *payload; 491 bool ret = false; 492 493 req.op_code = BT_MP_INFO_OP_SCAN_TYPE; 494 skb = rtw_coex_info_request(rtwdev, &req); 495 if (!skb) 496 goto out; 497 498 payload = get_payload_from_coex_resp(skb); 499 *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload); 500 dev_kfree_skb_any(skb); 501 ret = true; 502 503 out: 504 return ret; 505 } 506 507 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev, 508 u8 lna_constrain_level) 509 { 510 struct rtw_coex_info_req req = {0}; 511 struct sk_buff *skb; 512 bool ret = false; 513 514 req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT; 515 req.para1 = lna_constrain_level; 516 skb = rtw_coex_info_request(rtwdev, &req); 517 if (!skb) 518 goto out; 519 520 dev_kfree_skb_any(skb); 521 ret = true; 522 523 out: 524 return ret; 525 } 526 527 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) 528 { 529 struct rtw_coex *coex = &rtwdev->coex; 530 struct rtw_coex_stat *coex_stat = &coex->stat; 531 struct rtw_coex_dm *coex_dm = &coex->dm; 532 struct rtw_chip_info *chip = rtwdev->chip; 533 u8 i; 534 u8 rssi_state; 535 u8 rssi_step; 536 u8 rssi; 537 538 /* update wl/bt rssi by btinfo */ 539 for (i = 0; i < COEX_RSSI_STEP; i++) { 540 rssi_state = coex_dm->bt_rssi_state[i]; 541 rssi_step = chip->bt_rssi_step[i]; 542 rssi = coex_stat->bt_rssi; 543 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 544 rssi, rssi_step); 545 coex_dm->bt_rssi_state[i] = rssi_state; 546 } 547 548 for (i = 0; i < COEX_RSSI_STEP; i++) { 549 rssi_state = coex_dm->wl_rssi_state[i]; 550 rssi_step = chip->wl_rssi_step[i]; 551 rssi = rtwdev->dm_info.min_rssi; 552 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 553 rssi, rssi_step); 554 coex_dm->wl_rssi_state[i] = rssi_state; 555 } 556 557 if (coex_stat->bt_ble_scan_en && 558 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) { 559 u8 scan_type; 560 561 if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) { 562 coex_stat->bt_ble_scan_type = scan_type; 563 if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1) 564 coex_stat->bt_init_scan = true; 565 else 566 coex_stat->bt_init_scan = false; 567 } 568 } 569 570 coex_stat->bt_profile_num = 0; 571 572 /* set link exist status */ 573 if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { 574 coex_stat->bt_link_exist = false; 575 coex_stat->bt_pan_exist = false; 576 coex_stat->bt_a2dp_exist = false; 577 coex_stat->bt_hid_exist = false; 578 coex_stat->bt_hfp_exist = false; 579 } else { 580 /* connection exists */ 581 coex_stat->bt_link_exist = true; 582 if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) { 583 coex_stat->bt_pan_exist = true; 584 coex_stat->bt_profile_num++; 585 } else { 586 coex_stat->bt_pan_exist = false; 587 } 588 589 if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) { 590 coex_stat->bt_a2dp_exist = true; 591 coex_stat->bt_profile_num++; 592 } else { 593 coex_stat->bt_a2dp_exist = false; 594 } 595 596 if (coex_stat->bt_info_lb2 & COEX_INFO_HID) { 597 coex_stat->bt_hid_exist = true; 598 coex_stat->bt_profile_num++; 599 } else { 600 coex_stat->bt_hid_exist = false; 601 } 602 603 if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) { 604 coex_stat->bt_hfp_exist = true; 605 coex_stat->bt_profile_num++; 606 } else { 607 coex_stat->bt_hfp_exist = false; 608 } 609 } 610 611 if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) { 612 coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE; 613 } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { 614 coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE; 615 } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) { 616 coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE; 617 } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) || 618 (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) { 619 if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) 620 coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY; 621 else 622 coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY; 623 } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) { 624 coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY; 625 } else { 626 coex_dm->bt_status = COEX_BTSTATUS_MAX; 627 } 628 629 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++; 630 631 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status); 632 } 633 634 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) 635 { 636 struct rtw_chip_info *chip = rtwdev->chip; 637 struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm; 638 struct rtw_efuse *efuse = &rtwdev->efuse; 639 u8 link = 0; 640 u8 center_chan = 0; 641 u8 bw; 642 int i; 643 644 bw = rtwdev->hal.current_band_width; 645 646 if (type != COEX_MEDIA_DISCONNECT) 647 center_chan = rtwdev->hal.current_channel; 648 649 if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) { 650 link = 0; 651 } else if (center_chan <= 14) { 652 link = 0x1; 653 654 if (bw == RTW_CHANNEL_WIDTH_40) 655 bw = chip->bt_afh_span_bw40; 656 else 657 bw = chip->bt_afh_span_bw20; 658 } else if (chip->afh_5g_num > 1) { 659 for (i = 0; i < chip->afh_5g_num; i++) { 660 if (center_chan == chip->afh_5g[i].wl_5g_ch) { 661 link = 0x3; 662 center_chan = chip->afh_5g[i].bt_skip_ch; 663 bw = chip->afh_5g[i].bt_skip_span; 664 break; 665 } 666 } 667 } 668 669 coex_dm->wl_ch_info[0] = link; 670 coex_dm->wl_ch_info[1] = center_chan; 671 coex_dm->wl_ch_info[2] = bw; 672 673 rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw); 674 } 675 676 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl) 677 { 678 struct rtw_coex *coex = &rtwdev->coex; 679 struct rtw_coex_dm *coex_dm = &coex->dm; 680 681 if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl) 682 return; 683 684 coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl; 685 686 rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl); 687 } 688 689 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl) 690 { 691 struct rtw_coex *coex = &rtwdev->coex; 692 struct rtw_coex_dm *coex_dm = &coex->dm; 693 694 if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl) 695 return; 696 697 coex_dm->cur_bt_lna_lvl = bt_lna_lvl; 698 699 /* notify BT rx gain table changed */ 700 if (bt_lna_lvl < 7) { 701 rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl); 702 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true); 703 } else { 704 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false); 705 } 706 } 707 708 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev, 709 struct coex_rf_para para) 710 { 711 struct rtw_coex *coex = &rtwdev->coex; 712 struct rtw_coex_stat *coex_stat = &coex->stat; 713 u8 offset = 0; 714 715 if (coex->freerun && coex_stat->wl_noisy_level <= 1) 716 offset = 3; 717 718 rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl); 719 rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset); 720 rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en); 721 rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl); 722 } 723 724 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr) 725 { 726 u32 val; 727 728 if (!ltecoex_read_reg(rtwdev, addr, &val)) { 729 rtw_err(rtwdev, "failed to read indirect register\n"); 730 return 0; 731 } 732 733 return val; 734 } 735 736 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr, 737 u32 mask, u32 val) 738 { 739 u32 shift = __ffs(mask); 740 u32 tmp; 741 742 tmp = rtw_coex_read_indirect_reg(rtwdev, addr); 743 tmp = (tmp & (~mask)) | ((val << shift) & mask); 744 745 if (!ltecoex_reg_write(rtwdev, addr, tmp)) 746 rtw_err(rtwdev, "failed to write indirect register\n"); 747 } 748 749 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) 750 { 751 if (wifi_control) 752 rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); 753 else 754 rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); 755 } 756 757 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) 758 { 759 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state); 760 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state); 761 } 762 763 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state) 764 { 765 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state); 766 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state); 767 } 768 769 static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1) 770 { 771 #define DEF_BRK_TABLE_VAL 0xf0ffffff 772 rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0); 773 rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1); 774 rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL); 775 } 776 777 static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type) 778 { 779 struct rtw_coex *coex = &rtwdev->coex; 780 struct rtw_coex_dm *coex_dm = &coex->dm; 781 struct rtw_chip_info *chip = rtwdev->chip; 782 struct rtw_efuse *efuse = &rtwdev->efuse; 783 784 coex_dm->cur_table = type; 785 786 if (efuse->share_ant) { 787 if (type < chip->table_sant_num) 788 rtw_coex_set_table(rtwdev, 789 chip->table_sant[type].bt, 790 chip->table_sant[type].wl); 791 } else { 792 type = type - 100; 793 if (type < chip->table_nsant_num) 794 rtw_coex_set_table(rtwdev, 795 chip->table_nsant[type].bt, 796 chip->table_nsant[type].wl); 797 } 798 } 799 800 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable) 801 { 802 struct rtw_coex *coex = &rtwdev->coex; 803 804 if (coex->stop_dm) 805 return; 806 807 rtw_fw_bt_ignore_wlan_action(rtwdev, enable); 808 } 809 810 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type, 811 u8 lps_val, u8 rpwm_val) 812 { 813 struct rtw_coex *coex = &rtwdev->coex; 814 struct rtw_coex_stat *coex_stat = &coex->stat; 815 u8 lps_mode = 0x0; 816 817 lps_mode = rtwdev->lps_conf.mode; 818 819 switch (ps_type) { 820 case COEX_PS_WIFI_NATIVE: 821 /* recover to original 32k low power setting */ 822 coex_stat->wl_force_lps_ctrl = false; 823 824 rtw_leave_lps(rtwdev); 825 break; 826 case COEX_PS_LPS_OFF: 827 coex_stat->wl_force_lps_ctrl = true; 828 if (lps_mode) 829 rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0); 830 831 rtw_leave_lps(rtwdev); 832 break; 833 default: 834 break; 835 } 836 } 837 838 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, 839 u8 byte3, u8 byte4, u8 byte5) 840 { 841 struct rtw_coex *coex = &rtwdev->coex; 842 struct rtw_coex_dm *coex_dm = &coex->dm; 843 struct rtw_chip_info *chip = rtwdev->chip; 844 u8 ps_type = COEX_PS_WIFI_NATIVE; 845 bool ap_enable = false; 846 847 if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) { 848 byte1 &= ~BIT(4); 849 byte1 |= BIT(5); 850 851 byte5 |= BIT(5); 852 byte5 &= ~BIT(6); 853 854 ps_type = COEX_PS_WIFI_NATIVE; 855 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 856 } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) { 857 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF) 858 ps_type = COEX_PS_LPS_OFF; 859 else 860 ps_type = COEX_PS_LPS_ON; 861 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4); 862 } else { 863 ps_type = COEX_PS_WIFI_NATIVE; 864 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 865 } 866 867 coex_dm->ps_tdma_para[0] = byte1; 868 coex_dm->ps_tdma_para[1] = byte2; 869 coex_dm->ps_tdma_para[2] = byte3; 870 coex_dm->ps_tdma_para[3] = byte4; 871 coex_dm->ps_tdma_para[4] = byte5; 872 873 rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5); 874 } 875 876 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) 877 { 878 struct rtw_coex *coex = &rtwdev->coex; 879 struct rtw_coex_dm *coex_dm = &coex->dm; 880 struct rtw_chip_info *chip = rtwdev->chip; 881 struct rtw_efuse *efuse = &rtwdev->efuse; 882 u8 n, type; 883 bool turn_on; 884 885 if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */ 886 rtw_coex_tdma_timer_base(rtwdev, 3); 887 else 888 rtw_coex_tdma_timer_base(rtwdev, 0); 889 890 type = (u8)(tcase & 0xff); 891 892 turn_on = (type == 0 || type == 100) ? false : true; 893 894 if (!force) { 895 if (turn_on == coex_dm->cur_ps_tdma_on && 896 type == coex_dm->cur_ps_tdma) { 897 return; 898 } 899 } 900 901 if (turn_on) { 902 /* enable TBTT interrupt */ 903 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); 904 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true); 905 } else { 906 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false); 907 } 908 909 if (efuse->share_ant) { 910 if (type < chip->tdma_sant_num) 911 rtw_coex_set_tdma(rtwdev, 912 chip->tdma_sant[type].para[0], 913 chip->tdma_sant[type].para[1], 914 chip->tdma_sant[type].para[2], 915 chip->tdma_sant[type].para[3], 916 chip->tdma_sant[type].para[4]); 917 } else { 918 n = type - 100; 919 if (n < chip->tdma_nsant_num) 920 rtw_coex_set_tdma(rtwdev, 921 chip->tdma_nsant[n].para[0], 922 chip->tdma_nsant[n].para[1], 923 chip->tdma_nsant[n].para[2], 924 chip->tdma_nsant[n].para[3], 925 chip->tdma_nsant[n].para[4]); 926 } 927 928 /* update pre state */ 929 coex_dm->cur_ps_tdma_on = turn_on; 930 coex_dm->cur_ps_tdma = type; 931 932 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type); 933 } 934 935 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) 936 { 937 struct rtw_coex *coex = &rtwdev->coex; 938 struct rtw_coex_stat *coex_stat = &coex->stat; 939 struct rtw_coex_dm *coex_dm = &coex->dm; 940 u8 ctrl_type = COEX_SWITCH_CTRL_MAX; 941 u8 pos_type = COEX_SWITCH_TO_MAX; 942 943 if (!force && coex_dm->cur_ant_pos_type == phase) 944 return; 945 946 coex_dm->cur_ant_pos_type = phase; 947 948 /* avoid switch coex_ctrl_owner during BT IQK */ 949 rtw_coex_check_rfk(rtwdev); 950 951 switch (phase) { 952 case COEX_SET_ANT_POWERON: 953 /* set path control owner to BT at power-on */ 954 if (coex_stat->bt_disabled) 955 rtw_coex_coex_ctrl_owner(rtwdev, true); 956 else 957 rtw_coex_coex_ctrl_owner(rtwdev, false); 958 959 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 960 pos_type = COEX_SWITCH_TO_BT; 961 break; 962 case COEX_SET_ANT_INIT: 963 if (coex_stat->bt_disabled) { 964 /* set GNT_BT to SW low */ 965 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 966 967 /* set GNT_WL to SW high */ 968 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 969 } else { 970 /* set GNT_BT to SW high */ 971 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 972 973 /* set GNT_WL to SW low */ 974 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW); 975 } 976 977 /* set path control owner to wl at initial step */ 978 rtw_coex_coex_ctrl_owner(rtwdev, true); 979 980 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 981 pos_type = COEX_SWITCH_TO_BT; 982 break; 983 case COEX_SET_ANT_WONLY: 984 /* set GNT_BT to SW Low */ 985 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 986 987 /* Set GNT_WL to SW high */ 988 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 989 990 /* set path control owner to wl at initial step */ 991 rtw_coex_coex_ctrl_owner(rtwdev, true); 992 993 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 994 pos_type = COEX_SWITCH_TO_WLG; 995 break; 996 case COEX_SET_ANT_WOFF: 997 /* set path control owner to BT */ 998 rtw_coex_coex_ctrl_owner(rtwdev, false); 999 1000 ctrl_type = COEX_SWITCH_CTRL_BY_BT; 1001 pos_type = COEX_SWITCH_TO_NOCARE; 1002 break; 1003 case COEX_SET_ANT_2G: 1004 /* set GNT_BT to PTA */ 1005 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 1006 1007 /* set GNT_WL to PTA */ 1008 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 1009 1010 /* set path control owner to wl at runtime step */ 1011 rtw_coex_coex_ctrl_owner(rtwdev, true); 1012 1013 ctrl_type = COEX_SWITCH_CTRL_BY_PTA; 1014 pos_type = COEX_SWITCH_TO_NOCARE; 1015 break; 1016 case COEX_SET_ANT_5G: 1017 /* set GNT_BT to PTA */ 1018 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 1019 1020 /* set GNT_WL to SW high */ 1021 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 1022 1023 /* set path control owner to wl at runtime step */ 1024 rtw_coex_coex_ctrl_owner(rtwdev, true); 1025 1026 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1027 pos_type = COEX_SWITCH_TO_WLA; 1028 break; 1029 case COEX_SET_ANT_2G_FREERUN: 1030 /* set GNT_BT to SW high */ 1031 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 1032 1033 /* Set GNT_WL to SW high */ 1034 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 1035 1036 /* set path control owner to wl at runtime step */ 1037 rtw_coex_coex_ctrl_owner(rtwdev, true); 1038 1039 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1040 pos_type = COEX_SWITCH_TO_WLG_BT; 1041 break; 1042 case COEX_SET_ANT_2G_WLBT: 1043 /* set GNT_BT to SW high */ 1044 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 1045 1046 /* Set GNT_WL to SW high */ 1047 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 1048 1049 /* set path control owner to wl at runtime step */ 1050 rtw_coex_coex_ctrl_owner(rtwdev, true); 1051 1052 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1053 pos_type = COEX_SWITCH_TO_WLG_BT; 1054 break; 1055 default: 1056 WARN(1, "unknown phase when setting antenna path\n"); 1057 return; 1058 } 1059 1060 if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX) 1061 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type); 1062 } 1063 1064 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) 1065 { 1066 struct rtw_coex *coex = &rtwdev->coex; 1067 struct rtw_coex_stat *coex_stat = &coex->stat; 1068 u8 algorithm = COEX_ALGO_NOPROFILE; 1069 u8 profile_map = 0; 1070 1071 if (coex_stat->bt_hfp_exist) 1072 profile_map |= BPM_HFP; 1073 if (coex_stat->bt_hid_exist) 1074 profile_map |= BPM_HID; 1075 if (coex_stat->bt_a2dp_exist) 1076 profile_map |= BPM_A2DP; 1077 if (coex_stat->bt_pan_exist) 1078 profile_map |= BPM_PAN; 1079 1080 switch (profile_map) { 1081 case BPM_HFP: 1082 algorithm = COEX_ALGO_HFP; 1083 break; 1084 case BPM_HID: 1085 case BPM_HFP + BPM_HID: 1086 algorithm = COEX_ALGO_HID; 1087 break; 1088 case BPM_HFP + BPM_A2DP: 1089 case BPM_HID + BPM_A2DP: 1090 case BPM_HFP + BPM_HID + BPM_A2DP: 1091 algorithm = COEX_ALGO_A2DP_HID; 1092 break; 1093 case BPM_HFP + BPM_PAN: 1094 case BPM_HID + BPM_PAN: 1095 case BPM_HFP + BPM_HID + BPM_PAN: 1096 algorithm = COEX_ALGO_PAN_HID; 1097 break; 1098 case BPM_HFP + BPM_A2DP + BPM_PAN: 1099 case BPM_HID + BPM_A2DP + BPM_PAN: 1100 case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN: 1101 algorithm = COEX_ALGO_A2DP_PAN_HID; 1102 break; 1103 case BPM_PAN: 1104 algorithm = COEX_ALGO_PAN; 1105 break; 1106 case BPM_A2DP + BPM_PAN: 1107 algorithm = COEX_ALGO_A2DP_PAN; 1108 break; 1109 case BPM_A2DP: 1110 if (coex_stat->bt_multi_link) { 1111 if (coex_stat->bt_hid_pair_num > 0) 1112 algorithm = COEX_ALGO_A2DP_HID; 1113 else 1114 algorithm = COEX_ALGO_A2DP_PAN; 1115 } else { 1116 algorithm = COEX_ALGO_A2DP; 1117 } 1118 break; 1119 default: 1120 algorithm = COEX_ALGO_NOPROFILE; 1121 break; 1122 } 1123 1124 return algorithm; 1125 } 1126 1127 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) 1128 { 1129 struct rtw_efuse *efuse = &rtwdev->efuse; 1130 struct rtw_chip_info *chip = rtwdev->chip; 1131 u8 table_case, tdma_case; 1132 1133 if (efuse->share_ant) { 1134 /* Shared-Ant */ 1135 table_case = 2; 1136 tdma_case = 0; 1137 } else { 1138 /* Non-Shared-Ant */ 1139 table_case = 100; 1140 tdma_case = 100; 1141 } 1142 1143 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1144 rtw_coex_table(rtwdev, table_case); 1145 rtw_coex_tdma(rtwdev, false, tdma_case); 1146 } 1147 1148 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev) 1149 { 1150 struct rtw_coex *coex = &rtwdev->coex; 1151 struct rtw_coex_stat *coex_stat = &coex->stat; 1152 struct rtw_coex_dm *coex_dm = &coex->dm; 1153 struct rtw_efuse *efuse = &rtwdev->efuse; 1154 struct rtw_chip_info *chip = rtwdev->chip; 1155 u8 level = 0; 1156 1157 if (efuse->share_ant) 1158 return; 1159 1160 coex->freerun = true; 1161 1162 if (coex_stat->wl_connected) 1163 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT); 1164 1165 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 1166 1167 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1168 1169 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0])) 1170 level = 2; 1171 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1172 level = 3; 1173 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2])) 1174 level = 4; 1175 else 1176 level = 5; 1177 1178 if (level > chip->wl_rf_para_num - 1) 1179 level = chip->wl_rf_para_num - 1; 1180 1181 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 1182 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]); 1183 else 1184 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]); 1185 1186 rtw_coex_table(rtwdev, 100); 1187 rtw_coex_tdma(rtwdev, false, 100); 1188 } 1189 1190 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) 1191 { 1192 struct rtw_efuse *efuse = &rtwdev->efuse; 1193 struct rtw_chip_info *chip = rtwdev->chip; 1194 u8 table_case, tdma_case; 1195 1196 if (efuse->share_ant) { 1197 /* Shared-Ant */ 1198 table_case = 2; 1199 tdma_case = 0; 1200 } else { 1201 /* Non-Shared-Ant */ 1202 table_case = 100; 1203 tdma_case = 100; 1204 } 1205 1206 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1207 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1208 rtw_coex_table(rtwdev, table_case); 1209 rtw_coex_tdma(rtwdev, false, tdma_case); 1210 } 1211 1212 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) 1213 { 1214 struct rtw_efuse *efuse = &rtwdev->efuse; 1215 struct rtw_chip_info *chip = rtwdev->chip; 1216 u8 table_case, tdma_case; 1217 1218 if (efuse->share_ant) { 1219 /* Shared-Ant */ 1220 table_case = 1; 1221 tdma_case = 0; 1222 } else { 1223 /* Non-Shared-Ant */ 1224 table_case = 100; 1225 tdma_case = 100; 1226 } 1227 1228 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1229 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1230 rtw_coex_table(rtwdev, table_case); 1231 rtw_coex_tdma(rtwdev, false, tdma_case); 1232 } 1233 1234 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) 1235 { 1236 struct rtw_coex *coex = &rtwdev->coex; 1237 struct rtw_coex_stat *coex_stat = &coex->stat; 1238 struct rtw_coex_dm *coex_dm = &coex->dm; 1239 struct rtw_efuse *efuse = &rtwdev->efuse; 1240 struct rtw_chip_info *chip = rtwdev->chip; 1241 struct rtw_coex_rfe *coex_rfe = &coex->rfe; 1242 u8 table_case = 0xff, tdma_case = 0xff; 1243 1244 if (coex_rfe->ant_switch_with_bt && 1245 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1246 if (efuse->share_ant && 1247 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) { 1248 table_case = 0; 1249 tdma_case = 0; 1250 } else if (!efuse->share_ant) { 1251 table_case = 100; 1252 tdma_case = 100; 1253 } 1254 } 1255 1256 if (table_case != 0xff && tdma_case != 0xff) { 1257 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 1258 rtw_coex_table(rtwdev, table_case); 1259 rtw_coex_tdma(rtwdev, false, tdma_case); 1260 return; 1261 } 1262 1263 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1264 1265 if (efuse->share_ant) { 1266 /* Shared-Ant */ 1267 if (!coex_stat->wl_gl_busy) { 1268 table_case = 10; 1269 tdma_case = 3; 1270 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1271 table_case = 6; 1272 tdma_case = 7; 1273 } else { 1274 table_case = 12; 1275 tdma_case = 7; 1276 } 1277 } else { 1278 /* Non-Shared-Ant */ 1279 if (!coex_stat->wl_gl_busy) { 1280 table_case = 112; 1281 tdma_case = 104; 1282 } else if ((coex_stat->bt_ble_scan_type & 0x2) && 1283 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1284 table_case = 114; 1285 tdma_case = 103; 1286 } else { 1287 table_case = 112; 1288 tdma_case = 103; 1289 } 1290 } 1291 1292 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1293 rtw_coex_table(rtwdev, table_case); 1294 rtw_coex_tdma(rtwdev, false, tdma_case); 1295 } 1296 1297 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) 1298 { 1299 struct rtw_coex *coex = &rtwdev->coex; 1300 struct rtw_coex_stat *coex_stat = &coex->stat; 1301 struct rtw_efuse *efuse = &rtwdev->efuse; 1302 struct rtw_chip_info *chip = rtwdev->chip; 1303 bool wl_hi_pri = false; 1304 u8 table_case, tdma_case; 1305 u32 slot_type = 0; 1306 1307 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || 1308 coex_stat->wl_hi_pri_task2) 1309 wl_hi_pri = true; 1310 1311 if (efuse->share_ant) { 1312 /* Shared-Ant */ 1313 if (wl_hi_pri) { 1314 table_case = 15; 1315 if (coex_stat->bt_a2dp_exist && 1316 !coex_stat->bt_pan_exist) { 1317 slot_type = TDMA_4SLOT; 1318 tdma_case = 11; 1319 } else if (coex_stat->wl_hi_pri_task1) { 1320 tdma_case = 6; 1321 } else if (!coex_stat->bt_page) { 1322 tdma_case = 8; 1323 } else { 1324 tdma_case = 9; 1325 } 1326 } else if (coex_stat->wl_connected) { 1327 table_case = 10; 1328 tdma_case = 10; 1329 } else { 1330 table_case = 1; 1331 tdma_case = 0; 1332 } 1333 } else { 1334 /* Non_Shared-Ant */ 1335 if (wl_hi_pri) { 1336 table_case = 113; 1337 if (coex_stat->bt_a2dp_exist && 1338 !coex_stat->bt_pan_exist) 1339 tdma_case = 111; 1340 else if (coex_stat->wl_hi_pri_task1) 1341 tdma_case = 106; 1342 else if (!coex_stat->bt_page) 1343 tdma_case = 108; 1344 else 1345 tdma_case = 109; 1346 } else if (coex_stat->wl_connected) { 1347 table_case = 101; 1348 tdma_case = 110; 1349 } else { 1350 table_case = 100; 1351 tdma_case = 100; 1352 } 1353 } 1354 1355 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n", 1356 wl_hi_pri, coex_stat->bt_page); 1357 1358 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1359 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1360 rtw_coex_table(rtwdev, table_case); 1361 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1362 } 1363 1364 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) 1365 { 1366 struct rtw_coex *coex = &rtwdev->coex; 1367 struct rtw_coex_stat *coex_stat = &coex->stat; 1368 struct rtw_efuse *efuse = &rtwdev->efuse; 1369 struct rtw_chip_info *chip = rtwdev->chip; 1370 u8 table_case, tdma_case; 1371 1372 if (efuse->share_ant) { 1373 /* Shared-Ant */ 1374 if (coex_stat->bt_multi_link) { 1375 table_case = 10; 1376 tdma_case = 17; 1377 } else { 1378 table_case = 10; 1379 tdma_case = 5; 1380 } 1381 } else { 1382 /* Non-Shared-Ant */ 1383 if (coex_stat->bt_multi_link) { 1384 table_case = 112; 1385 tdma_case = 117; 1386 } else { 1387 table_case = 105; 1388 tdma_case = 100; 1389 } 1390 } 1391 1392 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1393 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1394 rtw_coex_table(rtwdev, table_case); 1395 rtw_coex_tdma(rtwdev, false, tdma_case); 1396 } 1397 1398 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev) 1399 { 1400 struct rtw_coex *coex = &rtwdev->coex; 1401 struct rtw_coex_stat *coex_stat = &coex->stat; 1402 struct rtw_efuse *efuse = &rtwdev->efuse; 1403 struct rtw_chip_info *chip = rtwdev->chip; 1404 u8 table_case, tdma_case; 1405 u32 wl_bw; 1406 1407 wl_bw = rtwdev->hal.current_band_width; 1408 1409 if (efuse->share_ant) { 1410 /* Shared-Ant */ 1411 if (coex_stat->bt_ble_exist) { 1412 /* RCU */ 1413 if (!coex_stat->wl_gl_busy) 1414 table_case = 14; 1415 else 1416 table_case = 15; 1417 1418 if (coex_stat->bt_a2dp_active || wl_bw == 0) 1419 tdma_case = 18; 1420 else if (coex_stat->wl_gl_busy) 1421 tdma_case = 8; 1422 else 1423 tdma_case = 4; 1424 } else { 1425 if (coex_stat->bt_a2dp_active || wl_bw == 0) { 1426 table_case = 8; 1427 tdma_case = 4; 1428 } else { 1429 /* for 4/18 HID */ 1430 if (coex_stat->bt_418_hid_exist && 1431 coex_stat->wl_gl_busy) 1432 table_case = 12; 1433 else 1434 table_case = 10; 1435 tdma_case = 4; 1436 } 1437 } 1438 } else { 1439 /* Non-Shared-Ant */ 1440 if (coex_stat->bt_a2dp_active) { 1441 table_case = 113; 1442 tdma_case = 118; 1443 } else if (coex_stat->bt_ble_exist) { 1444 /* BLE */ 1445 table_case = 113; 1446 1447 if (coex_stat->wl_gl_busy) 1448 tdma_case = 106; 1449 else 1450 tdma_case = 104; 1451 } else { 1452 table_case = 113; 1453 tdma_case = 104; 1454 } 1455 } 1456 1457 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1458 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1459 rtw_coex_table(rtwdev, table_case); 1460 rtw_coex_tdma(rtwdev, false, tdma_case); 1461 } 1462 1463 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) 1464 { 1465 struct rtw_coex *coex = &rtwdev->coex; 1466 struct rtw_coex_stat *coex_stat = &coex->stat; 1467 struct rtw_coex_dm *coex_dm = &coex->dm; 1468 struct rtw_efuse *efuse = &rtwdev->efuse; 1469 struct rtw_chip_info *chip = rtwdev->chip; 1470 u8 table_case, tdma_case; 1471 u32 slot_type = 0; 1472 1473 if (efuse->share_ant) { 1474 /* Shared-Ant */ 1475 slot_type = TDMA_4SLOT; 1476 1477 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 1478 table_case = 10; 1479 else 1480 table_case = 9; 1481 1482 if (coex_stat->wl_gl_busy) 1483 tdma_case = 13; 1484 else 1485 tdma_case = 14; 1486 } else { 1487 /* Non-Shared-Ant */ 1488 table_case = 112; 1489 1490 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1491 tdma_case = 112; 1492 else 1493 tdma_case = 113; 1494 } 1495 1496 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1497 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1498 rtw_coex_table(rtwdev, table_case); 1499 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1500 } 1501 1502 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) 1503 { 1504 struct rtw_coex *coex = &rtwdev->coex; 1505 struct rtw_coex_stat *coex_stat = &coex->stat; 1506 struct rtw_efuse *efuse = &rtwdev->efuse; 1507 struct rtw_chip_info *chip = rtwdev->chip; 1508 u8 table_case, tdma_case; 1509 bool ap_enable = false; 1510 1511 if (efuse->share_ant) { /* Shared-Ant */ 1512 if (ap_enable) { 1513 table_case = 2; 1514 tdma_case = 0; 1515 } else if (coex_stat->wl_gl_busy) { 1516 table_case = 28; 1517 tdma_case = 20; 1518 } else { 1519 table_case = 28; 1520 tdma_case = 26; 1521 } 1522 } else { /* Non-Shared-Ant */ 1523 if (ap_enable) { 1524 table_case = 100; 1525 tdma_case = 100; 1526 } else { 1527 table_case = 119; 1528 tdma_case = 120; 1529 } 1530 } 1531 1532 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1533 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1534 rtw_coex_table(rtwdev, table_case); 1535 rtw_coex_tdma(rtwdev, false, tdma_case); 1536 } 1537 1538 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) 1539 { 1540 struct rtw_coex *coex = &rtwdev->coex; 1541 struct rtw_coex_stat *coex_stat = &coex->stat; 1542 struct rtw_efuse *efuse = &rtwdev->efuse; 1543 struct rtw_chip_info *chip = rtwdev->chip; 1544 u8 table_case, tdma_case; 1545 1546 if (efuse->share_ant) { 1547 /* Shared-Ant */ 1548 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 1549 table_case = 14; 1550 else 1551 table_case = 10; 1552 1553 if (coex_stat->wl_gl_busy) 1554 tdma_case = 17; 1555 else 1556 tdma_case = 19; 1557 } else { 1558 /* Non-Shared-Ant */ 1559 table_case = 112; 1560 1561 if (coex_stat->wl_gl_busy) 1562 tdma_case = 117; 1563 else 1564 tdma_case = 119; 1565 } 1566 1567 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1568 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1569 rtw_coex_table(rtwdev, table_case); 1570 rtw_coex_tdma(rtwdev, false, tdma_case); 1571 } 1572 1573 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) 1574 { 1575 struct rtw_coex *coex = &rtwdev->coex; 1576 struct rtw_coex_stat *coex_stat = &coex->stat; 1577 struct rtw_coex_dm *coex_dm = &coex->dm; 1578 struct rtw_efuse *efuse = &rtwdev->efuse; 1579 struct rtw_chip_info *chip = rtwdev->chip; 1580 u8 table_case, tdma_case; 1581 u32 slot_type = 0; 1582 1583 if (efuse->share_ant) { 1584 /* Shared-Ant */ 1585 slot_type = TDMA_4SLOT; 1586 1587 if (coex_stat->bt_ble_exist) 1588 table_case = 26; 1589 else 1590 table_case = 9; 1591 1592 if (coex_stat->wl_gl_busy) { 1593 tdma_case = 13; 1594 } else { 1595 tdma_case = 14; 1596 } 1597 } else { 1598 /* Non-Shared-Ant */ 1599 if (coex_stat->bt_ble_exist) 1600 table_case = 121; 1601 else 1602 table_case = 113; 1603 1604 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1605 tdma_case = 112; 1606 else 1607 tdma_case = 113; 1608 } 1609 1610 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1611 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1612 rtw_coex_table(rtwdev, table_case); 1613 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1614 } 1615 1616 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) 1617 { 1618 struct rtw_coex *coex = &rtwdev->coex; 1619 struct rtw_coex_stat *coex_stat = &coex->stat; 1620 struct rtw_efuse *efuse = &rtwdev->efuse; 1621 struct rtw_chip_info *chip = rtwdev->chip; 1622 u8 table_case, tdma_case; 1623 1624 if (efuse->share_ant) { 1625 /* Shared-Ant */ 1626 if (coex_stat->wl_gl_busy && 1627 coex_stat->wl_noisy_level == 0) 1628 table_case = 14; 1629 else 1630 table_case = 10; 1631 1632 if (coex_stat->wl_gl_busy) 1633 tdma_case = 15; 1634 else 1635 tdma_case = 20; 1636 } else { 1637 /* Non-Shared-Ant */ 1638 table_case = 112; 1639 1640 if (coex_stat->wl_gl_busy) 1641 tdma_case = 115; 1642 else 1643 tdma_case = 120; 1644 } 1645 1646 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1647 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1648 rtw_coex_table(rtwdev, table_case); 1649 rtw_coex_tdma(rtwdev, false, tdma_case); 1650 } 1651 1652 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) 1653 { 1654 struct rtw_coex *coex = &rtwdev->coex; 1655 struct rtw_coex_stat *coex_stat = &coex->stat; 1656 struct rtw_efuse *efuse = &rtwdev->efuse; 1657 struct rtw_chip_info *chip = rtwdev->chip; 1658 u8 table_case, tdma_case; 1659 1660 if (efuse->share_ant) { 1661 /* Shared-Ant */ 1662 table_case = 9; 1663 1664 if (coex_stat->wl_gl_busy) 1665 tdma_case = 18; 1666 else 1667 tdma_case = 19; 1668 } else { 1669 /* Non-Shared-Ant */ 1670 table_case = 113; 1671 1672 if (coex_stat->wl_gl_busy) 1673 tdma_case = 117; 1674 else 1675 tdma_case = 119; 1676 } 1677 1678 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1679 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1680 rtw_coex_table(rtwdev, table_case); 1681 rtw_coex_tdma(rtwdev, false, tdma_case); 1682 } 1683 1684 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) 1685 { 1686 struct rtw_coex *coex = &rtwdev->coex; 1687 struct rtw_coex_stat *coex_stat = &coex->stat; 1688 struct rtw_efuse *efuse = &rtwdev->efuse; 1689 struct rtw_chip_info *chip = rtwdev->chip; 1690 u8 table_case, tdma_case; 1691 1692 if (efuse->share_ant) { 1693 /* Shared-Ant */ 1694 table_case = 10; 1695 1696 if (coex_stat->wl_gl_busy) 1697 tdma_case = 15; 1698 else 1699 tdma_case = 20; 1700 } else { 1701 /* Non-Shared-Ant */ 1702 table_case = 113; 1703 1704 if (coex_stat->wl_gl_busy) 1705 tdma_case = 115; 1706 else 1707 tdma_case = 120; 1708 } 1709 1710 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1711 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1712 rtw_coex_table(rtwdev, table_case); 1713 rtw_coex_tdma(rtwdev, false, tdma_case); 1714 } 1715 1716 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) 1717 { 1718 struct rtw_efuse *efuse = &rtwdev->efuse; 1719 struct rtw_chip_info *chip = rtwdev->chip; 1720 u8 table_case, tdma_case; 1721 1722 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1723 1724 if (efuse->share_ant) { 1725 /* Shared-Ant */ 1726 table_case = 0; 1727 tdma_case = 0; 1728 } else { 1729 /* Non-Shared-Ant */ 1730 table_case = 100; 1731 tdma_case = 100; 1732 } 1733 1734 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 1735 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1736 rtw_coex_table(rtwdev, table_case); 1737 rtw_coex_tdma(rtwdev, false, tdma_case); 1738 } 1739 1740 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) 1741 { 1742 struct rtw_efuse *efuse = &rtwdev->efuse; 1743 struct rtw_chip_info *chip = rtwdev->chip; 1744 u8 table_case, tdma_case; 1745 1746 if (efuse->share_ant) { 1747 /* Shared-Ant */ 1748 table_case = 2; 1749 tdma_case = 0; 1750 } else { 1751 /* Non-Shared-Ant */ 1752 table_case = 100; 1753 tdma_case = 100; 1754 } 1755 1756 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1757 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1758 rtw_coex_table(rtwdev, table_case); 1759 rtw_coex_tdma(rtwdev, false, tdma_case); 1760 } 1761 1762 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) 1763 { 1764 struct rtw_coex *coex = &rtwdev->coex; 1765 struct rtw_efuse *efuse = &rtwdev->efuse; 1766 struct rtw_chip_info *chip = rtwdev->chip; 1767 u8 table_case, tdma_case; 1768 1769 if (coex->under_5g) 1770 return; 1771 1772 if (efuse->share_ant) { 1773 /* Shared-Ant */ 1774 table_case = 28; 1775 tdma_case = 0; 1776 } else { 1777 /* Non-Shared-Ant */ 1778 table_case = 100; 1779 tdma_case = 100; 1780 } 1781 1782 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1783 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1784 rtw_coex_table(rtwdev, table_case); 1785 rtw_coex_tdma(rtwdev, false, tdma_case); 1786 } 1787 1788 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) 1789 { 1790 struct rtw_coex *coex = &rtwdev->coex; 1791 struct rtw_coex_stat *coex_stat = &coex->stat; 1792 struct rtw_efuse *efuse = &rtwdev->efuse; 1793 struct rtw_chip_info *chip = rtwdev->chip; 1794 u8 table_case, tdma_case; 1795 u32 slot_type = 0; 1796 1797 if (efuse->share_ant) { 1798 /* Shared-Ant */ 1799 if (coex_stat->bt_a2dp_exist) { 1800 slot_type = TDMA_4SLOT; 1801 table_case = 9; 1802 tdma_case = 11; 1803 } else { 1804 table_case = 9; 1805 tdma_case = 7; 1806 } 1807 } else { 1808 /* Non-Shared-Ant */ 1809 if (coex_stat->bt_a2dp_exist) { 1810 table_case = 112; 1811 tdma_case = 111; 1812 } else { 1813 table_case = 112; 1814 tdma_case = 107; 1815 } 1816 } 1817 1818 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1819 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1820 rtw_coex_table(rtwdev, table_case); 1821 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1822 } 1823 1824 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev) 1825 { 1826 struct rtw_efuse *efuse = &rtwdev->efuse; 1827 struct rtw_chip_info *chip = rtwdev->chip; 1828 u8 table_case, tdma_case; 1829 1830 if (efuse->share_ant) { 1831 /* Shared-Ant */ 1832 table_case = 1; 1833 tdma_case = 0; 1834 } else { 1835 /* Non-Shared-Ant */ 1836 table_case = 100; 1837 tdma_case = 100; 1838 } 1839 1840 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1841 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1842 rtw_coex_table(rtwdev, table_case); 1843 rtw_coex_tdma(rtwdev, false, tdma_case); 1844 } 1845 1846 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) 1847 { 1848 struct rtw_coex *coex = &rtwdev->coex; 1849 struct rtw_coex_stat *coex_stat = &coex->stat; 1850 struct rtw_coex_dm *coex_dm = &coex->dm; 1851 struct rtw_efuse *efuse = &rtwdev->efuse; 1852 u8 algorithm; 1853 1854 /* Non-Shared-Ant */ 1855 if (!efuse->share_ant && coex_stat->wl_gl_busy && 1856 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && 1857 COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) { 1858 rtw_coex_action_freerun(rtwdev); 1859 return; 1860 } 1861 1862 algorithm = rtw_coex_algorithm(rtwdev); 1863 1864 switch (algorithm) { 1865 case COEX_ALGO_HFP: 1866 rtw_coex_action_bt_hfp(rtwdev); 1867 break; 1868 case COEX_ALGO_HID: 1869 rtw_coex_action_bt_hid(rtwdev); 1870 break; 1871 case COEX_ALGO_A2DP: 1872 if (coex_stat->bt_a2dp_sink) 1873 rtw_coex_action_bt_a2dpsink(rtwdev); 1874 else 1875 rtw_coex_action_bt_a2dp(rtwdev); 1876 break; 1877 case COEX_ALGO_PAN: 1878 rtw_coex_action_bt_pan(rtwdev); 1879 break; 1880 case COEX_ALGO_A2DP_HID: 1881 rtw_coex_action_bt_a2dp_hid(rtwdev); 1882 break; 1883 case COEX_ALGO_A2DP_PAN: 1884 rtw_coex_action_bt_a2dp_pan(rtwdev); 1885 break; 1886 case COEX_ALGO_PAN_HID: 1887 rtw_coex_action_bt_pan_hid(rtwdev); 1888 break; 1889 case COEX_ALGO_A2DP_PAN_HID: 1890 rtw_coex_action_bt_a2dp_pan_hid(rtwdev); 1891 break; 1892 default: 1893 case COEX_ALGO_NOPROFILE: 1894 rtw_coex_action_bt_idle(rtwdev); 1895 break; 1896 } 1897 } 1898 1899 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) 1900 { 1901 struct rtw_coex *coex = &rtwdev->coex; 1902 struct rtw_coex_dm *coex_dm = &coex->dm; 1903 struct rtw_coex_stat *coex_stat = &coex->stat; 1904 1905 lockdep_assert_held(&rtwdev->mutex); 1906 1907 if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) 1908 return; 1909 1910 coex_dm->reason = reason; 1911 1912 /* update wifi_link_info_ext variable */ 1913 rtw_coex_update_wl_link_info(rtwdev, reason); 1914 1915 rtw_coex_monitor_bt_enable(rtwdev); 1916 1917 if (coex->stop_dm) 1918 return; 1919 1920 if (coex_stat->wl_under_ips) 1921 return; 1922 1923 if (coex->freeze && !coex_stat->bt_setup_link) 1924 return; 1925 1926 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++; 1927 coex->freerun = false; 1928 1929 /* Pure-5G Coex Process */ 1930 if (coex->under_5g) { 1931 coex_stat->wl_coex_mode = COEX_WLINK_5G; 1932 rtw_coex_action_wl_under5g(rtwdev); 1933 goto exit; 1934 } 1935 1936 coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT; 1937 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1938 if (coex_stat->bt_disabled) { 1939 rtw_coex_action_wl_only(rtwdev); 1940 goto exit; 1941 } 1942 1943 if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) { 1944 rtw_coex_action_wl_native_lps(rtwdev); 1945 goto exit; 1946 } 1947 1948 if (coex_stat->bt_whck_test) { 1949 rtw_coex_action_bt_whql_test(rtwdev); 1950 goto exit; 1951 } 1952 1953 if (coex_stat->bt_setup_link) { 1954 rtw_coex_action_bt_relink(rtwdev); 1955 goto exit; 1956 } 1957 1958 if (coex_stat->bt_inq_page) { 1959 rtw_coex_action_bt_inquiry(rtwdev); 1960 goto exit; 1961 } 1962 1963 if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE || 1964 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) && 1965 coex_stat->wl_connected) { 1966 rtw_coex_action_bt_idle(rtwdev); 1967 goto exit; 1968 } 1969 1970 if (coex_stat->wl_linkscan_proc) { 1971 rtw_coex_action_wl_linkscan(rtwdev); 1972 goto exit; 1973 } 1974 1975 if (coex_stat->wl_connected) 1976 rtw_coex_action_wl_connected(rtwdev); 1977 else 1978 rtw_coex_action_wl_not_connected(rtwdev); 1979 1980 exit: 1981 rtw_coex_set_gnt_fix(rtwdev); 1982 rtw_coex_limited_wl(rtwdev); 1983 } 1984 1985 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev) 1986 { 1987 struct rtw_coex *coex = &rtwdev->coex; 1988 struct rtw_coex_stat *coex_stat = &coex->stat; 1989 struct rtw_coex_dm *coex_dm = &coex->dm; 1990 u8 i; 1991 1992 memset(coex_dm, 0, sizeof(*coex_dm)); 1993 memset(coex_stat, 0, sizeof(*coex_stat)); 1994 1995 for (i = 0; i < COEX_CNT_WL_MAX; i++) 1996 coex_stat->cnt_wl[i] = 0; 1997 1998 for (i = 0; i < COEX_CNT_BT_MAX; i++) 1999 coex_stat->cnt_bt[i] = 0; 2000 2001 for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++) 2002 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW; 2003 2004 for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++) 2005 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW; 2006 2007 coex_stat->wl_coex_mode = COEX_WLINK_MAX; 2008 } 2009 2010 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) 2011 { 2012 struct rtw_coex *coex = &rtwdev->coex; 2013 2014 rtw_coex_init_coex_var(rtwdev); 2015 rtw_coex_monitor_bt_enable(rtwdev); 2016 rtw_coex_set_rfe_type(rtwdev); 2017 rtw_coex_set_init(rtwdev); 2018 2019 /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */ 2020 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1); 2021 2022 /* set Tx beacon = Hi-Pri */ 2023 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1); 2024 2025 /* set Tx beacon queue = Hi-Pri */ 2026 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1); 2027 2028 /* antenna config */ 2029 if (coex->wl_rf_off) { 2030 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); 2031 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); 2032 coex->stop_dm = true; 2033 } else if (wifi_only) { 2034 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY); 2035 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, 2036 true); 2037 coex->stop_dm = true; 2038 } else { 2039 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT); 2040 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, 2041 true); 2042 coex->stop_dm = false; 2043 coex->freeze = true; 2044 } 2045 2046 /* PTA parameter */ 2047 rtw_coex_table(rtwdev, 0); 2048 rtw_coex_tdma(rtwdev, true, 0); 2049 rtw_coex_query_bt_info(rtwdev); 2050 } 2051 2052 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev) 2053 { 2054 struct rtw_coex *coex = &rtwdev->coex; 2055 2056 coex->stop_dm = true; 2057 coex->wl_rf_off = false; 2058 2059 /* enable BB, we can write 0x948 */ 2060 rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1)); 2061 2062 rtw_coex_monitor_bt_enable(rtwdev); 2063 rtw_coex_set_rfe_type(rtwdev); 2064 2065 /* set antenna path to BT */ 2066 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON); 2067 2068 /* red x issue */ 2069 rtw_write8(rtwdev, 0xff1a, 0x0); 2070 } 2071 2072 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) 2073 { 2074 __rtw_coex_init_hw_config(rtwdev, wifi_only); 2075 } 2076 2077 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) 2078 { 2079 struct rtw_coex *coex = &rtwdev->coex; 2080 struct rtw_coex_stat *coex_stat = &coex->stat; 2081 2082 if (coex->stop_dm) 2083 return; 2084 2085 if (type == COEX_IPS_ENTER) { 2086 coex_stat->wl_under_ips = true; 2087 2088 /* for lps off */ 2089 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); 2090 2091 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); 2092 rtw_coex_action_coex_all_off(rtwdev); 2093 } else if (type == COEX_IPS_LEAVE) { 2094 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); 2095 2096 /* run init hw config (exclude wifi only) */ 2097 __rtw_coex_init_hw_config(rtwdev, false); 2098 /* sw all off */ 2099 2100 coex_stat->wl_under_ips = false; 2101 } 2102 } 2103 2104 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) 2105 { 2106 struct rtw_coex *coex = &rtwdev->coex; 2107 struct rtw_coex_stat *coex_stat = &coex->stat; 2108 2109 if (coex->stop_dm) 2110 return; 2111 2112 if (type == COEX_LPS_ENABLE) { 2113 coex_stat->wl_under_lps = true; 2114 2115 if (coex_stat->wl_force_lps_ctrl) { 2116 /* for ps-tdma */ 2117 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2118 } else { 2119 /* for native ps */ 2120 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); 2121 2122 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); 2123 } 2124 } else if (type == COEX_LPS_DISABLE) { 2125 coex_stat->wl_under_lps = false; 2126 2127 /* for lps off */ 2128 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2129 2130 if (!coex_stat->wl_force_lps_ctrl) 2131 rtw_coex_query_bt_info(rtwdev); 2132 } 2133 } 2134 2135 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type) 2136 { 2137 struct rtw_coex *coex = &rtwdev->coex; 2138 struct rtw_coex_stat *coex_stat = &coex->stat; 2139 2140 if (coex->stop_dm) 2141 return; 2142 2143 coex->freeze = false; 2144 2145 if (type != COEX_SCAN_FINISH) 2146 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | 2147 COEX_SCBD_ONOFF, true); 2148 2149 if (type == COEX_SCAN_START_5G) { 2150 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2151 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART); 2152 } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) { 2153 coex_stat->wl_hi_pri_task2 = true; 2154 2155 /* Force antenna setup for no scan result issue */ 2156 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 2157 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART); 2158 } else { 2159 coex_stat->wl_hi_pri_task2 = false; 2160 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH); 2161 } 2162 } 2163 2164 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type) 2165 { 2166 struct rtw_coex *coex = &rtwdev->coex; 2167 2168 if (coex->stop_dm) 2169 return; 2170 2171 if (type == COEX_SWITCH_TO_5G) 2172 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND); 2173 else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) 2174 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND); 2175 else 2176 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G); 2177 } 2178 2179 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type) 2180 { 2181 struct rtw_coex *coex = &rtwdev->coex; 2182 struct rtw_coex_stat *coex_stat = &coex->stat; 2183 2184 if (coex->stop_dm) 2185 return; 2186 2187 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | 2188 COEX_SCBD_ONOFF, true); 2189 2190 if (type == COEX_ASSOCIATE_5G_START) { 2191 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2192 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART); 2193 } else if (type == COEX_ASSOCIATE_5G_FINISH) { 2194 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2195 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH); 2196 } else if (type == COEX_ASSOCIATE_START) { 2197 coex_stat->wl_hi_pri_task1 = true; 2198 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2; 2199 2200 /* Force antenna setup for no scan result issue */ 2201 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 2202 2203 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART); 2204 2205 /* To keep TDMA case during connect process, 2206 * to avoid changed by Btinfo and runcoexmechanism 2207 */ 2208 coex->freeze = true; 2209 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work, 2210 5 * HZ); 2211 } else { 2212 coex_stat->wl_hi_pri_task1 = false; 2213 coex->freeze = false; 2214 2215 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH); 2216 } 2217 } 2218 2219 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) 2220 { 2221 struct rtw_coex *coex = &rtwdev->coex; 2222 struct rtw_coex_stat *coex_stat = &coex->stat; 2223 u8 para[6] = {0}; 2224 2225 if (coex->stop_dm) 2226 return; 2227 2228 if (type == COEX_MEDIA_CONNECT_5G) { 2229 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2230 2231 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2232 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA); 2233 } else if (type == COEX_MEDIA_CONNECT) { 2234 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2235 2236 /* Force antenna setup for no scan result issue */ 2237 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 2238 2239 /* Set CCK Rx high Pri */ 2240 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1); 2241 2242 /* always enable 5ms extend if connect */ 2243 para[0] = COEX_H2C69_WL_LEAKAP; 2244 para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */ 2245 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 2246 coex_stat->wl_slot_extend = true; 2247 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA); 2248 } else { 2249 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); 2250 2251 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0); 2252 2253 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON); 2254 } 2255 2256 rtw_coex_update_wl_ch_info(rtwdev, type); 2257 } 2258 2259 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 2260 { 2261 struct rtw_coex *coex = &rtwdev->coex; 2262 struct rtw_coex_stat *coex_stat = &coex->stat; 2263 struct rtw_chip_info *chip = rtwdev->chip; 2264 unsigned long bt_relink_time; 2265 u8 i, rsp_source = 0, type; 2266 2267 rsp_source = buf[0] & 0xf; 2268 if (rsp_source >= COEX_BTINFO_SRC_MAX) 2269 rsp_source = COEX_BTINFO_SRC_WL_FW; 2270 2271 if (rsp_source == COEX_BTINFO_SRC_BT_IQK) { 2272 coex_stat->bt_iqk_state = buf[1]; 2273 if (coex_stat->bt_iqk_state == 1) 2274 coex_stat->cnt_bt[COEX_CNT_BT_IQK]++; 2275 else if (coex_stat->bt_iqk_state == 2) 2276 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++; 2277 2278 return; 2279 } 2280 2281 if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) { 2282 rtw_coex_monitor_bt_enable(rtwdev); 2283 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) { 2284 coex_stat->bt_disabled_pre = coex_stat->bt_disabled; 2285 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 2286 } 2287 return; 2288 } 2289 2290 if (rsp_source == COEX_BTINFO_SRC_BT_RSP || 2291 rsp_source == COEX_BTINFO_SRC_BT_ACT) { 2292 if (coex_stat->bt_disabled) { 2293 coex_stat->bt_disabled = false; 2294 coex_stat->bt_reenable = true; 2295 ieee80211_queue_delayed_work(rtwdev->hw, 2296 &coex->bt_reenable_work, 2297 15 * HZ); 2298 } 2299 } 2300 2301 for (i = 0; i < length; i++) { 2302 if (i < COEX_BTINFO_LENGTH_MAX) 2303 coex_stat->bt_info_c2h[rsp_source][i] = buf[i]; 2304 else 2305 break; 2306 } 2307 2308 if (rsp_source == COEX_BTINFO_SRC_WL_FW) { 2309 rtw_coex_update_bt_link_info(rtwdev); 2310 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 2311 return; 2312 } 2313 2314 /* get the same info from bt, skip it */ 2315 if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 && 2316 coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 && 2317 coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 && 2318 coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 && 2319 coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 && 2320 coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) 2321 return; 2322 2323 coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1]; 2324 coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2]; 2325 coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3]; 2326 coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4]; 2327 coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5]; 2328 coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6]; 2329 2330 /* 0xff means BT is under WHCK test */ 2331 coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff); 2332 coex_stat->bt_inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2)); 2333 coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3)); 2334 coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf; 2335 if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1) 2336 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++; 2337 2338 coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4)); 2339 coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5)); 2340 if (coex_stat->bt_inq) 2341 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++; 2342 2343 coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7)); 2344 if (coex_stat->bt_page) { 2345 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++; 2346 if (coex_stat->wl_linkscan_proc || 2347 coex_stat->wl_hi_pri_task1 || 2348 coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy) 2349 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true); 2350 else 2351 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); 2352 } else { 2353 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); 2354 } 2355 2356 /* unit: % (value-100 to translate to unit: dBm in coex info) */ 2357 if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) { 2358 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10; 2359 } else { /* original unit: dbm -> unit: % -> value-100 in coex info */ 2360 if (coex_stat->bt_info_hb0 <= 127) 2361 coex_stat->bt_rssi = 100; 2362 else if (256 - coex_stat->bt_info_hb0 <= 100) 2363 coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0); 2364 else 2365 coex_stat->bt_rssi = 0; 2366 } 2367 2368 coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0)); 2369 if (coex_stat->bt_info_hb1 & BIT(1)) 2370 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++; 2371 2372 if (coex_stat->bt_info_hb1 & BIT(2)) { 2373 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++; 2374 coex_stat->bt_setup_link = true; 2375 if (coex_stat->bt_reenable) 2376 bt_relink_time = 6 * HZ; 2377 else 2378 bt_relink_time = 2 * HZ; 2379 2380 ieee80211_queue_delayed_work(rtwdev->hw, 2381 &coex->bt_relink_work, 2382 bt_relink_time); 2383 } 2384 2385 if (coex_stat->bt_info_hb1 & BIT(3)) 2386 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++; 2387 2388 coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4)); 2389 coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5)); 2390 if (coex_stat->bt_info_hb1 & BIT(6)) 2391 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++; 2392 2393 coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7)); 2394 /* resend wifi info to bt, it is reset and lost the info */ 2395 if ((coex_stat->bt_info_hb1 & BIT(1))) { 2396 if (coex_stat->wl_connected) 2397 type = COEX_MEDIA_CONNECT; 2398 else 2399 type = COEX_MEDIA_DISCONNECT; 2400 rtw_coex_update_wl_ch_info(rtwdev, type); 2401 } 2402 2403 /* if ignore_wlan_act && not set_up_link */ 2404 if ((coex_stat->bt_info_hb1 & BIT(3)) && 2405 (!(coex_stat->bt_info_hb1 & BIT(2)))) 2406 rtw_coex_ignore_wlan_act(rtwdev, false); 2407 2408 coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0)); 2409 if (coex_stat->bt_info_hb2 & BIT(1)) 2410 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++; 2411 2412 coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2); 2413 coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3)); 2414 coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4; 2415 coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6; 2416 if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2) 2417 coex_stat->bt_418_hid_exist = true; 2418 else if (coex_stat->bt_hid_pair_num == 0) 2419 coex_stat->bt_418_hid_exist = false; 2420 2421 if ((coex_stat->bt_info_lb2 & 0x49) == 0x49) 2422 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f); 2423 else 2424 coex_stat->bt_a2dp_bitpool = 0; 2425 2426 coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7)); 2427 2428 rtw_coex_update_bt_link_info(rtwdev); 2429 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 2430 } 2431 2432 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 2433 { 2434 struct rtw_coex *coex = &rtwdev->coex; 2435 struct rtw_coex_stat *coex_stat = &coex->stat; 2436 u8 val; 2437 int i; 2438 2439 if (WARN(length < 8, "invalid wl info c2h length\n")) 2440 return; 2441 2442 if (buf[0] != 0x08) 2443 return; 2444 2445 for (i = 1; i < 8; i++) { 2446 val = coex_stat->wl_fw_dbg_info_pre[i]; 2447 if (buf[i] >= val) 2448 coex_stat->wl_fw_dbg_info[i] = buf[i] - val; 2449 else 2450 coex_stat->wl_fw_dbg_info[i] = val - buf[i]; 2451 2452 coex_stat->wl_fw_dbg_info_pre[i] = buf[i]; 2453 } 2454 2455 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++; 2456 rtw_coex_wl_ccklock_action(rtwdev); 2457 rtw_coex_wl_ccklock_detect(rtwdev); 2458 } 2459 2460 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev) 2461 { 2462 struct rtw_coex *coex = &rtwdev->coex; 2463 2464 if (coex->stop_dm) 2465 return; 2466 2467 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 2468 } 2469 2470 void rtw_coex_bt_relink_work(struct work_struct *work) 2471 { 2472 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 2473 coex.bt_relink_work.work); 2474 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 2475 2476 mutex_lock(&rtwdev->mutex); 2477 coex_stat->bt_setup_link = false; 2478 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 2479 mutex_unlock(&rtwdev->mutex); 2480 } 2481 2482 void rtw_coex_bt_reenable_work(struct work_struct *work) 2483 { 2484 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 2485 coex.bt_reenable_work.work); 2486 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 2487 2488 mutex_lock(&rtwdev->mutex); 2489 coex_stat->bt_reenable = false; 2490 mutex_unlock(&rtwdev->mutex); 2491 } 2492 2493 void rtw_coex_defreeze_work(struct work_struct *work) 2494 { 2495 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 2496 coex.defreeze_work.work); 2497 struct rtw_coex *coex = &rtwdev->coex; 2498 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 2499 2500 mutex_lock(&rtwdev->mutex); 2501 coex->freeze = false; 2502 coex_stat->wl_hi_pri_task1 = false; 2503 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 2504 mutex_unlock(&rtwdev->mutex); 2505 } 2506 2507 #ifdef CONFIG_RTW88_DEBUGFS 2508 #define INFO_SIZE 80 2509 2510 #define case_BTINFO(src) \ 2511 case COEX_BTINFO_SRC_##src: return #src 2512 2513 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src) 2514 { 2515 switch (bt_info_src) { 2516 case_BTINFO(WL_FW); 2517 case_BTINFO(BT_RSP); 2518 case_BTINFO(BT_ACT); 2519 default: 2520 return "Unknown"; 2521 } 2522 } 2523 2524 #define case_RSN(src) \ 2525 case COEX_RSN_##src: return #src 2526 2527 static const char *rtw_coex_get_reason_string(u8 reason) 2528 { 2529 switch (reason) { 2530 case_RSN(2GSCANSTART); 2531 case_RSN(5GSCANSTART); 2532 case_RSN(SCANFINISH); 2533 case_RSN(2GSWITCHBAND); 2534 case_RSN(5GSWITCHBAND); 2535 case_RSN(2GCONSTART); 2536 case_RSN(5GCONSTART); 2537 case_RSN(2GCONFINISH); 2538 case_RSN(5GCONFINISH); 2539 case_RSN(2GMEDIA); 2540 case_RSN(5GMEDIA); 2541 case_RSN(MEDIADISCON); 2542 case_RSN(BTINFO); 2543 case_RSN(LPS); 2544 case_RSN(WLSTATUS); 2545 default: 2546 return "Unknown"; 2547 } 2548 } 2549 2550 static int rtw_coex_addr_info(struct rtw_dev *rtwdev, 2551 const struct rtw_reg_domain *reg, 2552 char addr_info[], int n) 2553 { 2554 const char *rf_prefix = ""; 2555 const char *sep = n == 0 ? "" : "/ "; 2556 int ffs, fls; 2557 int max_fls; 2558 2559 if (INFO_SIZE - n <= 0) 2560 return 0; 2561 2562 switch (reg->domain) { 2563 case RTW_REG_DOMAIN_MAC32: 2564 max_fls = 31; 2565 break; 2566 case RTW_REG_DOMAIN_MAC16: 2567 max_fls = 15; 2568 break; 2569 case RTW_REG_DOMAIN_MAC8: 2570 max_fls = 7; 2571 break; 2572 case RTW_REG_DOMAIN_RF_A: 2573 case RTW_REG_DOMAIN_RF_B: 2574 rf_prefix = "RF_"; 2575 max_fls = 19; 2576 break; 2577 default: 2578 return 0; 2579 } 2580 2581 ffs = __ffs(reg->mask); 2582 fls = __fls(reg->mask); 2583 2584 if (ffs == 0 && fls == max_fls) 2585 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x", 2586 sep, rf_prefix, reg->addr); 2587 else if (ffs == fls) 2588 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]", 2589 sep, rf_prefix, reg->addr, ffs); 2590 else 2591 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]", 2592 sep, rf_prefix, reg->addr, fls, ffs); 2593 } 2594 2595 static int rtw_coex_val_info(struct rtw_dev *rtwdev, 2596 const struct rtw_reg_domain *reg, 2597 char val_info[], int n) 2598 { 2599 const char *sep = n == 0 ? "" : "/ "; 2600 u8 rf_path; 2601 2602 if (INFO_SIZE - n <= 0) 2603 return 0; 2604 2605 switch (reg->domain) { 2606 case RTW_REG_DOMAIN_MAC32: 2607 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 2608 rtw_read32_mask(rtwdev, reg->addr, reg->mask)); 2609 case RTW_REG_DOMAIN_MAC16: 2610 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 2611 rtw_read16_mask(rtwdev, reg->addr, reg->mask)); 2612 case RTW_REG_DOMAIN_MAC8: 2613 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 2614 rtw_read8_mask(rtwdev, reg->addr, reg->mask)); 2615 case RTW_REG_DOMAIN_RF_A: 2616 rf_path = RF_PATH_A; 2617 break; 2618 case RTW_REG_DOMAIN_RF_B: 2619 rf_path = RF_PATH_B; 2620 break; 2621 default: 2622 return 0; 2623 } 2624 2625 /* only RF go through here */ 2626 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 2627 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask)); 2628 } 2629 2630 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m) 2631 { 2632 struct rtw_chip_info *chip = rtwdev->chip; 2633 const struct rtw_reg_domain *reg; 2634 char addr_info[INFO_SIZE]; 2635 int n_addr = 0; 2636 char val_info[INFO_SIZE]; 2637 int n_val = 0; 2638 int i; 2639 2640 for (i = 0; i < chip->coex_info_hw_regs_num; i++) { 2641 reg = &chip->coex_info_hw_regs[i]; 2642 2643 n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr); 2644 n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val); 2645 2646 if (reg->domain == RTW_REG_DOMAIN_NL) { 2647 seq_printf(m, "%-40s = %s\n", addr_info, val_info); 2648 n_addr = 0; 2649 n_val = 0; 2650 } 2651 } 2652 2653 if (n_addr != 0 && n_val != 0) 2654 seq_printf(m, "%-40s = %s\n", addr_info, val_info); 2655 } 2656 2657 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev, 2658 u8 type, u16 addr, u16 *val) 2659 { 2660 struct rtw_coex_info_req req = {0}; 2661 struct sk_buff *skb; 2662 __le16 le_addr; 2663 u8 *payload; 2664 2665 le_addr = cpu_to_le16(addr); 2666 req.op_code = BT_MP_INFO_OP_READ_REG; 2667 req.para1 = type; 2668 req.para2 = le16_get_bits(le_addr, GENMASK(7, 0)); 2669 req.para3 = le16_get_bits(le_addr, GENMASK(15, 8)); 2670 skb = rtw_coex_info_request(rtwdev, &req); 2671 if (!skb) { 2672 *val = 0xeaea; 2673 return false; 2674 } 2675 2676 payload = get_payload_from_coex_resp(skb); 2677 *val = GET_COEX_RESP_BT_REG_VAL(payload); 2678 2679 return true; 2680 } 2681 2682 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev, 2683 u32 *patch_version) 2684 { 2685 struct rtw_coex_info_req req = {0}; 2686 struct sk_buff *skb; 2687 u8 *payload; 2688 bool ret = false; 2689 2690 req.op_code = BT_MP_INFO_OP_PATCH_VER; 2691 skb = rtw_coex_info_request(rtwdev, &req); 2692 if (!skb) 2693 goto out; 2694 2695 payload = get_payload_from_coex_resp(skb); 2696 *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload); 2697 ret = true; 2698 2699 out: 2700 return ret; 2701 } 2702 2703 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev, 2704 u32 *supported_version) 2705 { 2706 struct rtw_coex_info_req req = {0}; 2707 struct sk_buff *skb; 2708 u8 *payload; 2709 bool ret = false; 2710 2711 req.op_code = BT_MP_INFO_OP_SUPP_VER; 2712 skb = rtw_coex_info_request(rtwdev, &req); 2713 if (!skb) 2714 goto out; 2715 2716 payload = get_payload_from_coex_resp(skb); 2717 *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload); 2718 ret = true; 2719 2720 out: 2721 return ret; 2722 } 2723 2724 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev, 2725 u32 *supported_feature) 2726 { 2727 struct rtw_coex_info_req req = {0}; 2728 struct sk_buff *skb; 2729 u8 *payload; 2730 bool ret = false; 2731 2732 req.op_code = BT_MP_INFO_OP_SUPP_FEAT; 2733 skb = rtw_coex_info_request(rtwdev, &req); 2734 if (!skb) 2735 goto out; 2736 2737 payload = get_payload_from_coex_resp(skb); 2738 *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload); 2739 ret = true; 2740 2741 out: 2742 return ret; 2743 } 2744 2745 struct rtw_coex_sta_stat_iter_data { 2746 struct rtw_vif *rtwvif; 2747 struct seq_file *file; 2748 }; 2749 2750 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta) 2751 { 2752 struct rtw_coex_sta_stat_iter_data *sta_iter_data = data; 2753 struct rtw_vif *rtwvif = sta_iter_data->rtwvif; 2754 struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; 2755 struct seq_file *m = sta_iter_data->file; 2756 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 2757 u8 rssi; 2758 2759 if (si->vif != vif) 2760 return; 2761 2762 rssi = ewma_rssi_read(&si->avg_rssi); 2763 seq_printf(m, "\tPeer %3d\n", si->mac_id); 2764 seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi); 2765 seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode); 2766 } 2767 2768 struct rtw_coex_vif_stat_iter_data { 2769 struct rtw_dev *rtwdev; 2770 struct seq_file *file; 2771 }; 2772 2773 static void rtw_coex_vif_stat_iter(void *data, u8 *mac, 2774 struct ieee80211_vif *vif) 2775 { 2776 struct rtw_coex_vif_stat_iter_data *vif_iter_data = data; 2777 struct rtw_coex_sta_stat_iter_data sta_iter_data; 2778 struct rtw_dev *rtwdev = vif_iter_data->rtwdev; 2779 struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 2780 struct seq_file *m = vif_iter_data->file; 2781 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 2782 2783 seq_printf(m, "Iface on Port (%d)\n", rtwvif->port); 2784 seq_printf(m, "\t%-32s = %d\n", 2785 "Beacon interval", bss_conf->beacon_int); 2786 seq_printf(m, "\t%-32s = %d\n", 2787 "Network Type", rtwvif->net_type); 2788 2789 sta_iter_data.rtwvif = rtwvif; 2790 sta_iter_data.file = m; 2791 rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter, 2792 &sta_iter_data); 2793 } 2794 2795 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) 2796 { 2797 struct rtw_chip_info *chip = rtwdev->chip; 2798 struct rtw_dm_info *dm_info = &rtwdev->dm_info; 2799 struct rtw_coex *coex = &rtwdev->coex; 2800 struct rtw_coex_stat *coex_stat = &coex->stat; 2801 struct rtw_coex_dm *coex_dm = &coex->dm; 2802 struct rtw_hal *hal = &rtwdev->hal; 2803 struct rtw_efuse *efuse = &rtwdev->efuse; 2804 struct rtw_fw_state *fw = &rtwdev->fw; 2805 struct rtw_coex_vif_stat_iter_data vif_iter_data; 2806 u8 reason = coex_dm->reason; 2807 u8 sys_lte; 2808 u16 score_board_WB, score_board_BW; 2809 u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc; 2810 u32 lte_coex, bt_coex; 2811 u32 bt_hi_pri, bt_lo_pri; 2812 int i; 2813 2814 score_board_BW = rtw_coex_read_scbd(rtwdev); 2815 score_board_WB = coex_stat->score_board; 2816 wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0); 2817 wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4); 2818 wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8); 2819 wl_reg_6cc = rtw_read32(rtwdev, 0x6cc); 2820 wl_reg_778 = rtw_read32(rtwdev, 0x778); 2821 bt_hi_pri = rtw_read32(rtwdev, 0x770); 2822 bt_lo_pri = rtw_read32(rtwdev, 0x774); 2823 rtw_write8(rtwdev, 0x76e, 0xc); 2824 sys_lte = rtw_read8(rtwdev, 0x73); 2825 lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38); 2826 bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54); 2827 2828 if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) { 2829 rtw_coex_get_bt_supported_version(rtwdev, 2830 &coex_stat->bt_supported_version); 2831 rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver); 2832 rtw_coex_get_bt_supported_feature(rtwdev, 2833 &coex_stat->bt_supported_feature); 2834 rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae); 2835 rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac); 2836 2837 if (coex_stat->patch_ver != 0) 2838 coex_stat->bt_mailbox_reply = true; 2839 } 2840 2841 seq_printf(m, "**********************************************\n"); 2842 seq_printf(m, "\t\tBT Coexist info %x\n", chip->id); 2843 seq_printf(m, "**********************************************\n"); 2844 seq_printf(m, "%-40s = %s/ %d\n", 2845 "Mech/ RFE", 2846 efuse->share_ant ? "Shared" : "Non-Shared", 2847 efuse->rfe_option); 2848 seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n", 2849 "Coex Ver/ BT Dez/ BT Rpt", 2850 chip->coex_para_ver, chip->bt_desired_ver, 2851 coex_stat->bt_supported_version, 2852 coex_stat->bt_disabled ? "(BT disabled)" : 2853 coex_stat->bt_supported_version >= chip->bt_desired_ver ? 2854 "(Match)" : "(Mismatch)"); 2855 seq_printf(m, "%-40s = %s/ %u/ %d\n", 2856 "Role/ RoleSwCnt/ IgnWL/ Feature", 2857 coex_stat->bt_slave ? "Slave" : "Master", 2858 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH], 2859 coex_dm->ignore_wl_act); 2860 seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n", 2861 "WL FW/ BT FW/ KT", 2862 fw->version, fw->sub_version, 2863 coex_stat->patch_ver, coex_stat->kt_ver + 65); 2864 seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n", 2865 "AFH Map", 2866 coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1], 2867 coex_dm->wl_ch_info[2], hal->current_channel); 2868 2869 seq_printf(m, "**********************************************\n"); 2870 seq_printf(m, "\t\tBT Status\n"); 2871 seq_printf(m, "**********************************************\n"); 2872 seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n", 2873 "BT status/ rssi/ retry/ pop", 2874 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" : 2875 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy", 2876 coex_stat->bt_rssi - 100, 2877 coex_stat->cnt_bt[COEX_CNT_BT_RETRY], 2878 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]); 2879 seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n", 2880 "Profiles", 2881 coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ? 2882 "A2DP sink," : "A2DP,") : "", 2883 coex_stat->bt_hfp_exist ? "HFP," : "", 2884 coex_stat->bt_hid_exist ? 2885 (coex_stat->bt_ble_exist ? "HID(RCU)," : 2886 coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" : 2887 "HID(2/18),") : "", 2888 coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ? 2889 "OPP," : "PAN," : "", 2890 coex_stat->bt_ble_voice ? "Voice," : "", 2891 coex_stat->bt_multi_link); 2892 seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n", 2893 "Reinit/ Relink/ IgnWl/ Feature", 2894 coex_stat->cnt_bt[COEX_CNT_BT_REINIT], 2895 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK], 2896 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT], 2897 coex_stat->bt_supported_feature); 2898 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", 2899 "Page/ Inq/ iqk/ iqk fail", 2900 coex_stat->cnt_bt[COEX_CNT_BT_PAGE], 2901 coex_stat->cnt_bt[COEX_CNT_BT_INQ], 2902 coex_stat->cnt_bt[COEX_CNT_BT_IQK], 2903 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]); 2904 seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n", 2905 "0xae/ 0xac/ score board (W->B)/ (B->W)", 2906 coex_stat->bt_reg_vendor_ae, 2907 coex_stat->bt_reg_vendor_ac, 2908 score_board_WB, score_board_BW); 2909 seq_printf(m, "%-40s = %u/%u, %u/%u\n", 2910 "Hi-Pri TX/RX, Lo-Pri TX/RX", 2911 bt_hi_pri & 0xffff, bt_hi_pri >> 16, 2912 bt_lo_pri & 0xffff, bt_lo_pri >> 16); 2913 for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++) 2914 seq_printf(m, "%-40s = %7ph\n", 2915 rtw_coex_get_bt_info_src_string(i), 2916 coex_stat->bt_info_c2h[i]); 2917 2918 seq_printf(m, "**********************************************\n"); 2919 seq_printf(m, "\t\tWiFi Status\n"); 2920 seq_printf(m, "**********************************************\n"); 2921 seq_printf(m, "%-40s = %d\n", 2922 "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags)); 2923 seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n", 2924 "G_busy/ TX/ RX", 2925 coex_stat->wl_gl_busy, 2926 rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput); 2927 seq_printf(m, "%-40s = %u/ %u/ %u\n", 2928 "IPS/ Low Power/ PS mode", 2929 test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags), 2930 test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags), 2931 rtwdev->lps_conf.mode); 2932 2933 vif_iter_data.rtwdev = rtwdev; 2934 vif_iter_data.file = m; 2935 rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data); 2936 2937 seq_printf(m, "**********************************************\n"); 2938 seq_printf(m, "\t\tMechanism\n"); 2939 seq_printf(m, "**********************************************\n"); 2940 seq_printf(m, "%-40s = %5ph (case-%d)\n", 2941 "TDMA", 2942 coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma); 2943 seq_printf(m, "%-40s = %d\n", 2944 "Timer base", coex_stat->tdma_timer_base); 2945 seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n", 2946 "Table/ 0x6c0/ 0x6c4/ 0x6c8", 2947 coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8); 2948 seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n", 2949 "0x778/ 0x6cc/ Reason", 2950 wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason)); 2951 seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n", 2952 "Null All/ Retry/ Ack/ BT Empty/ BT Late", 2953 coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2], 2954 coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4], 2955 coex_stat->wl_fw_dbg_info[5]); 2956 seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n", 2957 "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW", 2958 coex_stat->wl_fw_dbg_info[6], 2959 coex_stat->wl_fw_dbg_info[7], 2960 coex_stat->wl_slot_extend ? "Yes" : "No", 2961 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]); 2962 2963 seq_printf(m, "**********************************************\n"); 2964 seq_printf(m, "\t\tHW setting\n"); 2965 seq_printf(m, "**********************************************\n"); 2966 seq_printf(m, "%-40s = %s/ %s\n", 2967 "LTE Coex/ Path Owner", 2968 lte_coex & BIT(7) ? "ON" : "OFF", 2969 sys_lte & BIT(2) ? "WL" : "BT"); 2970 seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n", 2971 "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg", 2972 lte_coex & BIT(12) ? "SW" : "HW", 2973 lte_coex & BIT(8) ? "SW" : "HW", 2974 lte_coex & BIT(14) ? "SW" : "HW", 2975 lte_coex & BIT(10) ? "SW" : "HW", 2976 sys_lte & BIT(3) ? "On" : "Off"); 2977 seq_printf(m, "%-40s = %lu/ %lu\n", 2978 "GNT_WL/ GNT_BT", 2979 (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3); 2980 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", 2981 "CRC OK CCK/ OFDM/ HT/ VHT", 2982 dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt, 2983 dm_info->ht_ok_cnt, dm_info->vht_ok_cnt); 2984 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", 2985 "CRC ERR CCK/ OFDM/ HT/ VHT", 2986 dm_info->cck_err_cnt, dm_info->ofdm_err_cnt, 2987 dm_info->ht_err_cnt, dm_info->vht_err_cnt); 2988 seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n", 2989 "HiPr/ Locking/ Locked/ Noisy", 2990 coex_stat->wl_hi_pri_task1 ? "Y" : "N", 2991 coex_stat->wl_cck_lock ? "Y" : "N", 2992 coex_stat->wl_cck_lock_ever ? "Y" : "N", 2993 coex_stat->wl_noisy_level); 2994 2995 rtw_coex_set_coexinfo_hw(rtwdev, m); 2996 } 2997 #endif /* CONFIG_RTW88_DEBUGFS */ 2998