The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/rtw88/coex.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 70d79e485d94216ea05f9c74e1bb2d06


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.