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