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