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/rtw89/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) 2019-2020  Realtek Corporation
    3  */
    4 
    5 #include "coex.h"
    6 #include "debug.h"
    7 #include "fw.h"
    8 #include "mac.h"
    9 #include "ps.h"
   10 #include "reg.h"
   11 
   12 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
   13 
   14 enum btc_fbtc_tdma_template {
   15         CXTD_OFF = 0x0,
   16         CXTD_OFF_B2,
   17         CXTD_OFF_EXT,
   18         CXTD_FIX,
   19         CXTD_PFIX,
   20         CXTD_AUTO,
   21         CXTD_PAUTO,
   22         CXTD_AUTO2,
   23         CXTD_PAUTO2,
   24         CXTD_MAX,
   25 };
   26 
   27 enum btc_fbtc_tdma_type {
   28         CXTDMA_OFF = 0x0,
   29         CXTDMA_FIX = 0x1,
   30         CXTDMA_AUTO = 0x2,
   31         CXTDMA_AUTO2 = 0x3,
   32         CXTDMA_MAX
   33 };
   34 
   35 enum btc_fbtc_tdma_rx_flow_ctrl {
   36         CXFLC_OFF = 0x0,
   37         CXFLC_NULLP = 0x1,
   38         CXFLC_QOSNULL = 0x2,
   39         CXFLC_CTS = 0x3,
   40         CXFLC_MAX
   41 };
   42 
   43 enum btc_fbtc_tdma_wlan_tx_pause {
   44         CXTPS_OFF = 0x0,  /* no wl tx pause*/
   45         CXTPS_ON = 0x1,
   46         CXTPS_MAX
   47 };
   48 
   49 enum btc_mlme_state {
   50         MLME_NO_LINK,
   51         MLME_LINKING,
   52         MLME_LINKED,
   53 };
   54 
   55 #define FCXONESLOT_VER 1
   56 struct btc_fbtc_1slot {
   57         u8 fver;
   58         u8 sid; /* slot id */
   59         struct rtw89_btc_fbtc_slot slot;
   60 } __packed;
   61 
   62 static const struct rtw89_btc_fbtc_tdma t_def[] = {
   63         [CXTD_OFF]      = { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
   64         [CXTD_OFF_B2]   = { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
   65         [CXTD_OFF_EXT]  = { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 3, 0, 0},
   66         [CXTD_FIX]      = { CXTDMA_FIX,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
   67         [CXTD_PFIX]     = { CXTDMA_FIX,  CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
   68         [CXTD_AUTO]     = { CXTDMA_AUTO,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
   69         [CXTD_PAUTO]    = { CXTDMA_AUTO, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
   70         [CXTD_AUTO2]    = {CXTDMA_AUTO2,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
   71         [CXTD_PAUTO2]   = {CXTDMA_AUTO2, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0}
   72 };
   73 
   74 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
   75         { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
   76           .cxtype = cpu_to_le16(__cxtype),}
   77 
   78 static const struct rtw89_btc_fbtc_slot s_def[] = {
   79         [CXST_OFF]      = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
   80         [CXST_B2W]      = __DEF_FBTC_SLOT(5,   0x5a5a5a5a, SLOT_ISO),
   81         [CXST_W1]       = __DEF_FBTC_SLOT(70,  0x5a5a5a5a, SLOT_ISO),
   82         [CXST_W2]       = __DEF_FBTC_SLOT(70,  0x5a5a5aaa, SLOT_ISO),
   83         [CXST_W2B]      = __DEF_FBTC_SLOT(15,  0x5a5a5a5a, SLOT_ISO),
   84         [CXST_B1]       = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
   85         [CXST_B2]       = __DEF_FBTC_SLOT(7,   0x6a5a5a5a, SLOT_MIX),
   86         [CXST_B3]       = __DEF_FBTC_SLOT(5,   0x55555555, SLOT_MIX),
   87         [CXST_B4]       = __DEF_FBTC_SLOT(50,  0x55555555, SLOT_MIX),
   88         [CXST_LK]       = __DEF_FBTC_SLOT(20,  0x5a5a5a5a, SLOT_ISO),
   89         [CXST_BLK]      = __DEF_FBTC_SLOT(250, 0x55555555, SLOT_MIX),
   90         [CXST_E2G]      = __DEF_FBTC_SLOT(20,  0x6a5a5a5a, SLOT_MIX),
   91         [CXST_E5G]      = __DEF_FBTC_SLOT(20,  0xffffffff, SLOT_MIX),
   92         [CXST_EBT]      = __DEF_FBTC_SLOT(20,  0x55555555, SLOT_MIX),
   93         [CXST_ENULL]    = __DEF_FBTC_SLOT(7,   0xaaaaaaaa, SLOT_ISO),
   94         [CXST_WLK]      = __DEF_FBTC_SLOT(250, 0x6a5a6a5a, SLOT_MIX),
   95         [CXST_W1FDD]    = __DEF_FBTC_SLOT(35,  0xfafafafa, SLOT_ISO),
   96         [CXST_B1FDD]    = __DEF_FBTC_SLOT(100, 0xffffffff, SLOT_MIX),
   97 };
   98 
   99 static const u32 cxtbl[] = {
  100         0xffffffff, /* 0 */
  101         0xaaaaaaaa, /* 1 */
  102         0x55555555, /* 2 */
  103         0x66555555, /* 3 */
  104         0x66556655, /* 4 */
  105         0x5a5a5a5a, /* 5 */
  106         0x5a5a5aaa, /* 6 */
  107         0xaa5a5a5a, /* 7 */
  108         0x6a5a5a5a, /* 8 */
  109         0x6a5a5aaa, /* 9 */
  110         0x6a5a6a5a, /* 10 */
  111         0x6a5a6aaa, /* 11 */
  112         0x6afa5afa, /* 12 */
  113         0xaaaa5aaa, /* 13 */
  114         0xaaffffaa, /* 14 */
  115         0xaa5555aa, /* 15 */
  116         0xfafafafa, /* 16 */
  117         0xffffddff, /* 17 */
  118         0xdaffdaff, /* 18 */
  119         0xfafadafa  /* 19 */
  120 };
  121 
  122 struct rtw89_btc_btf_tlv {
  123         u8 type;
  124         u8 len;
  125         u8 val[1];
  126 } __packed;
  127 
  128 enum btc_btf_set_report_en {
  129         RPT_EN_TDMA = BIT(0),
  130         RPT_EN_CYCLE = BIT(1),
  131         RPT_EN_MREG = BIT(2),
  132         RPT_EN_BT_VER_INFO = BIT(3),
  133         RPT_EN_BT_SCAN_INFO = BIT(4),
  134         RPT_EN_BT_AFH_MAP = BIT(5),
  135         RPT_EN_BT_DEVICE_INFO = BIT(6),
  136         RPT_EN_WL_ALL = GENMASK(2, 0),
  137         RPT_EN_BT_ALL = GENMASK(6, 3),
  138         RPT_EN_ALL = GENMASK(6, 0),
  139 };
  140 
  141 #define BTF_SET_REPORT_VER 1
  142 struct rtw89_btc_btf_set_report {
  143         u8 fver;
  144         __le32 enable;
  145         __le32 para;
  146 } __packed;
  147 
  148 #define BTF_SET_SLOT_TABLE_VER 1
  149 struct rtw89_btc_btf_set_slot_table {
  150         u8 fver;
  151         u8 tbl_num;
  152         u8 buf[];
  153 } __packed;
  154 
  155 #define BTF_SET_MON_REG_VER 1
  156 struct rtw89_btc_btf_set_mon_reg {
  157         u8 fver;
  158         u8 reg_num;
  159         u8 buf[];
  160 } __packed;
  161 
  162 enum btc_btf_set_cx_policy {
  163         CXPOLICY_TDMA = 0x0,
  164         CXPOLICY_SLOT = 0x1,
  165         CXPOLICY_TYPE = 0x2,
  166         CXPOLICY_MAX,
  167 };
  168 
  169 enum btc_b2w_scoreboard {
  170         BTC_BSCB_ACT = BIT(0),
  171         BTC_BSCB_ON = BIT(1),
  172         BTC_BSCB_WHQL = BIT(2),
  173         BTC_BSCB_BT_S1 = BIT(3),
  174         BTC_BSCB_A2DP_ACT = BIT(4),
  175         BTC_BSCB_RFK_RUN = BIT(5),
  176         BTC_BSCB_RFK_REQ = BIT(6),
  177         BTC_BSCB_LPS = BIT(7),
  178         BTC_BSCB_WLRFK = BIT(11),
  179         BTC_BSCB_BT_HILNA = BIT(13),
  180         BTC_BSCB_BT_CONNECT = BIT(16),
  181         BTC_BSCB_PATCH_CODE = BIT(30),
  182         BTC_BSCB_ALL = GENMASK(30, 0),
  183 };
  184 
  185 enum btc_phymap {
  186         BTC_PHY_0 = BIT(0),
  187         BTC_PHY_1 = BIT(1),
  188         BTC_PHY_ALL = BIT(0) | BIT(1),
  189 };
  190 
  191 enum btc_cx_state_map {
  192         BTC_WIDLE = 0,
  193         BTC_WBUSY_BNOSCAN,
  194         BTC_WBUSY_BSCAN,
  195         BTC_WSCAN_BNOSCAN,
  196         BTC_WSCAN_BSCAN,
  197         BTC_WLINKING
  198 };
  199 
  200 enum btc_ant_phase {
  201         BTC_ANT_WPOWERON = 0,
  202         BTC_ANT_WINIT,
  203         BTC_ANT_WONLY,
  204         BTC_ANT_WOFF,
  205         BTC_ANT_W2G,
  206         BTC_ANT_W5G,
  207         BTC_ANT_W25G,
  208         BTC_ANT_FREERUN,
  209         BTC_ANT_WRFK,
  210         BTC_ANT_BRFK,
  211         BTC_ANT_MAX
  212 };
  213 
  214 enum btc_plt {
  215         BTC_PLT_NONE = 0,
  216         BTC_PLT_LTE_RX = BIT(0),
  217         BTC_PLT_GNT_BT_TX = BIT(1),
  218         BTC_PLT_GNT_BT_RX = BIT(2),
  219         BTC_PLT_GNT_WL = BIT(3),
  220         BTC_PLT_BT = BIT(1) | BIT(2),
  221         BTC_PLT_ALL = 0xf
  222 };
  223 
  224 enum btc_cx_poicy_main_type {
  225         BTC_CXP_OFF = 0,
  226         BTC_CXP_OFFB,
  227         BTC_CXP_OFFE,
  228         BTC_CXP_FIX,
  229         BTC_CXP_PFIX,
  230         BTC_CXP_AUTO,
  231         BTC_CXP_PAUTO,
  232         BTC_CXP_AUTO2,
  233         BTC_CXP_PAUTO2,
  234         BTC_CXP_MANUAL,
  235         BTC_CXP_USERDEF0,
  236         BTC_CXP_MAIN_MAX
  237 };
  238 
  239 enum btc_cx_poicy_type {
  240         /* TDMA off + pri: BT > WL */
  241         BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
  242 
  243         /* TDMA off + pri: WL > BT */
  244         BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
  245 
  246         /* TDMA off + pri: BT = WL */
  247         BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
  248 
  249         /* TDMA off + pri: BT = WL > BT_Lo */
  250         BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
  251 
  252         /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
  253         BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
  254 
  255         /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
  256         BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
  257 
  258         /* TDMA off + pri: BT_Hi > WL > BT_Lo */
  259         BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 6,
  260 
  261         /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
  262         BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 7,
  263 
  264         /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
  265         BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 8,
  266 
  267         /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
  268         BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
  269 
  270         /* TDMA off + Ext-Ctrl + pri: default */
  271         BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
  272 
  273         /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
  274         BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
  275 
  276         /* TDMA off + Ext-Ctrl + pri: default */
  277         BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
  278 
  279         /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
  280         BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
  281 
  282         /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
  283         BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
  284 
  285         /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
  286         BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
  287 
  288         /* TDMA off + Ext-Ctrl + pri: default */
  289         BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
  290 
  291         /* TDMA Fix slot-0: W1:B1 = 30:30 */
  292         BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
  293 
  294         /* TDMA Fix slot-1: W1:B1 = 50:50 */
  295         BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
  296 
  297         /* TDMA Fix slot-2: W1:B1 = 20:30 */
  298         BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
  299 
  300         /* TDMA Fix slot-3: W1:B1 = 40:10 */
  301         BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
  302 
  303         /* TDMA Fix slot-4: W1:B1 = 70:10 */
  304         BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
  305 
  306         /* TDMA Fix slot-5: W1:B1 = 20:60 */
  307         BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
  308 
  309         /* TDMA Fix slot-6: W1:B1 = 30:60 */
  310         BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
  311 
  312         /* TDMA Fix slot-7: W1:B1 = 20:80 */
  313         BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
  314 
  315         /* TDMA Fix slot-8: W1:B1 = user-define */
  316         BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
  317 
  318         /* TDMA Fix slot-9: W1:B1 = 40:20 */
  319         BTC_CXP_FIX_TD4020 = (BTC_CXP_FIX << 8) | 9,
  320 
  321         /* TDMA Fix slot-9: W1:B1 = 40:10 */
  322         BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 10,
  323 
  324         /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
  325         BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
  326 
  327         /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
  328         BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
  329 
  330         /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
  331         BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
  332 
  333         /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
  334         BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
  335 
  336         /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
  337         BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
  338 
  339         /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
  340         BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
  341 
  342         /* PS-TDMA Fix slot-6: W1:B1 = user-define */
  343         BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
  344 
  345         /* TDMA Auto slot-0: W1:B1 = 50:200 */
  346         BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
  347 
  348         /* TDMA Auto slot-1: W1:B1 = 60:200 */
  349         BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
  350 
  351         /* TDMA Auto slot-2: W1:B1 = 20:200 */
  352         BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
  353 
  354         /* TDMA Auto slot-3: W1:B1 = user-define */
  355         BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
  356 
  357         /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
  358         BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
  359 
  360         /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
  361         BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
  362 
  363         /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
  364         BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
  365 
  366         /* PS-TDMA Auto slot-3: W1:B1 = user-define */
  367         BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
  368 
  369         /* TDMA Auto slot2-0: W1:B4 = 30:50 */
  370         BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
  371 
  372         /* TDMA Auto slot2-1: W1:B4 = 30:70 */
  373         BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
  374 
  375         /* TDMA Auto slot2-2: W1:B4 = 50:50 */
  376         BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
  377 
  378         /* TDMA Auto slot2-3: W1:B4 = 60:60 */
  379         BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
  380 
  381         /* TDMA Auto slot2-4: W1:B4 = 20:80 */
  382         BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
  383 
  384         /* TDMA Auto slot2-5: W1:B4 = user-define */
  385         BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
  386 
  387         /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
  388         BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
  389 
  390         /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
  391         BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
  392 
  393         /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
  394         BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
  395 
  396         /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
  397         BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
  398 
  399         /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
  400         BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
  401 
  402         /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
  403         BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
  404 
  405         BTC_CXP_MAX = 0xffff
  406 };
  407 
  408 enum btc_wl_rfk_result {
  409         BTC_WRFK_REJECT = 0,
  410         BTC_WRFK_ALLOW = 1,
  411 };
  412 
  413 enum btc_coex_info_map_en {
  414         BTC_COEX_INFO_CX = BIT(0),
  415         BTC_COEX_INFO_WL = BIT(1),
  416         BTC_COEX_INFO_BT = BIT(2),
  417         BTC_COEX_INFO_DM = BIT(3),
  418         BTC_COEX_INFO_MREG = BIT(4),
  419         BTC_COEX_INFO_SUMMARY = BIT(5),
  420         BTC_COEX_INFO_ALL = GENMASK(7, 0),
  421 };
  422 
  423 #define BTC_CXP_MASK GENMASK(15, 8)
  424 
  425 enum btc_w2b_scoreboard {
  426         BTC_WSCB_ACTIVE = BIT(0),
  427         BTC_WSCB_ON = BIT(1),
  428         BTC_WSCB_SCAN = BIT(2),
  429         BTC_WSCB_UNDERTEST = BIT(3),
  430         BTC_WSCB_RXGAIN = BIT(4),
  431         BTC_WSCB_WLBUSY = BIT(7),
  432         BTC_WSCB_EXTFEM = BIT(8),
  433         BTC_WSCB_TDMA = BIT(9),
  434         BTC_WSCB_FIX2M = BIT(10),
  435         BTC_WSCB_WLRFK = BIT(11),
  436         BTC_WSCB_BTRFK_GNT = BIT(12), /* not used, use mailbox to inform BT */
  437         BTC_WSCB_BT_HILNA = BIT(13),
  438         BTC_WSCB_BTLOG = BIT(14),
  439         BTC_WSCB_ALL = GENMASK(23, 0),
  440 };
  441 
  442 enum btc_wl_link_mode {
  443         BTC_WLINK_NOLINK = 0x0,
  444         BTC_WLINK_2G_STA,
  445         BTC_WLINK_2G_AP,
  446         BTC_WLINK_2G_GO,
  447         BTC_WLINK_2G_GC,
  448         BTC_WLINK_2G_SCC,
  449         BTC_WLINK_2G_MCC,
  450         BTC_WLINK_25G_MCC,
  451         BTC_WLINK_25G_DBCC,
  452         BTC_WLINK_5G,
  453         BTC_WLINK_2G_NAN,
  454         BTC_WLINK_OTHER,
  455         BTC_WLINK_MAX
  456 };
  457 
  458 enum btc_wl_mrole_type {
  459         BTC_WLMROLE_NONE = 0x0,
  460         BTC_WLMROLE_STA_GC,
  461         BTC_WLMROLE_STA_GC_NOA,
  462         BTC_WLMROLE_STA_GO,
  463         BTC_WLMROLE_STA_GO_NOA,
  464         BTC_WLMROLE_STA_STA,
  465         BTC_WLMROLE_MAX
  466 };
  467 
  468 enum btc_bt_hid_type {
  469         BTC_HID_218 = BIT(0),
  470         BTC_HID_418 = BIT(1),
  471         BTC_HID_BLE = BIT(2),
  472         BTC_HID_RCU = BIT(3),
  473         BTC_HID_RCU_VOICE = BIT(4),
  474         BTC_HID_OTHER_LEGACY = BIT(5)
  475 };
  476 
  477 enum btc_reset_module {
  478         BTC_RESET_CX = BIT(0),
  479         BTC_RESET_DM = BIT(1),
  480         BTC_RESET_CTRL = BIT(2),
  481         BTC_RESET_CXDM = BIT(0) | BIT(1),
  482         BTC_RESET_BTINFO = BIT(3),
  483         BTC_RESET_MDINFO = BIT(4),
  484         BTC_RESET_ALL =  GENMASK(7, 0),
  485 };
  486 
  487 enum btc_gnt_state {
  488         BTC_GNT_HW      = 0,
  489         BTC_GNT_SW_LO,
  490         BTC_GNT_SW_HI,
  491         BTC_GNT_MAX
  492 };
  493 
  494 enum btc_wl_max_tx_time {
  495         BTC_MAX_TX_TIME_L1 = 500,
  496         BTC_MAX_TX_TIME_L2 = 1000,
  497         BTC_MAX_TX_TIME_L3 = 2000,
  498         BTC_MAX_TX_TIME_DEF = 5280
  499 };
  500 
  501 enum btc_wl_max_tx_retry {
  502         BTC_MAX_TX_RETRY_L1 = 7,
  503         BTC_MAX_TX_RETRY_L2 = 15,
  504         BTC_MAX_TX_RETRY_DEF = 31,
  505 };
  506 
  507 enum btc_reason_and_action {
  508         BTC_RSN_NONE,
  509         BTC_RSN_NTFY_INIT,
  510         BTC_RSN_NTFY_SWBAND,
  511         BTC_RSN_NTFY_WL_STA,
  512         BTC_RSN_NTFY_RADIO_STATE,
  513         BTC_RSN_UPDATE_BT_SCBD,
  514         BTC_RSN_NTFY_WL_RFK,
  515         BTC_RSN_UPDATE_BT_INFO,
  516         BTC_RSN_NTFY_SCAN_START,
  517         BTC_RSN_NTFY_SCAN_FINISH,
  518         BTC_RSN_NTFY_SPECIFIC_PACKET,
  519         BTC_RSN_NTFY_POWEROFF,
  520         BTC_RSN_NTFY_ROLE_INFO,
  521         BTC_RSN_CMD_SET_COEX,
  522         BTC_RSN_ACT1_WORK,
  523         BTC_RSN_BT_DEVINFO_WORK,
  524         BTC_RSN_RFK_CHK_WORK,
  525         BTC_RSN_NUM,
  526         BTC_ACT_NONE = 100,
  527         BTC_ACT_WL_ONLY,
  528         BTC_ACT_WL_5G,
  529         BTC_ACT_WL_OTHER,
  530         BTC_ACT_WL_IDLE,
  531         BTC_ACT_WL_NC,
  532         BTC_ACT_WL_RFK,
  533         BTC_ACT_WL_INIT,
  534         BTC_ACT_WL_OFF,
  535         BTC_ACT_FREERUN,
  536         BTC_ACT_BT_WHQL,
  537         BTC_ACT_BT_RFK,
  538         BTC_ACT_BT_OFF,
  539         BTC_ACT_BT_IDLE,
  540         BTC_ACT_BT_HFP,
  541         BTC_ACT_BT_HID,
  542         BTC_ACT_BT_A2DP,
  543         BTC_ACT_BT_A2DPSINK,
  544         BTC_ACT_BT_PAN,
  545         BTC_ACT_BT_A2DP_HID,
  546         BTC_ACT_BT_A2DP_PAN,
  547         BTC_ACT_BT_PAN_HID,
  548         BTC_ACT_BT_A2DP_PAN_HID,
  549         BTC_ACT_WL_25G_MCC,
  550         BTC_ACT_WL_2G_MCC,
  551         BTC_ACT_WL_2G_SCC,
  552         BTC_ACT_WL_2G_AP,
  553         BTC_ACT_WL_2G_GO,
  554         BTC_ACT_WL_2G_GC,
  555         BTC_ACT_WL_2G_NAN,
  556         BTC_ACT_LAST,
  557         BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
  558         BTC_ACT_EXT_BIT = BIT(14),
  559         BTC_POLICY_EXT_BIT = BIT(15),
  560 };
  561 
  562 #define BTC_FREERUN_ANTISO_MIN 30
  563 #define BTC_TDMA_BTHID_MAX 2
  564 #define BTC_BLINK_NOCONNECT 0
  565 #define BTC_B1_MAX 250 /* unit ms */
  566 
  567 static void _run_coex(struct rtw89_dev *rtwdev,
  568                       enum btc_reason_and_action reason);
  569 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
  570 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
  571 
  572 static void _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
  573                          void *param, u16 len)
  574 {
  575         struct rtw89_btc *btc = &rtwdev->btc;
  576         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
  577         struct rtw89_btc_cx *cx = &btc->cx;
  578         struct rtw89_btc_wl_info *wl = &cx->wl;
  579         int ret;
  580 
  581         if (!wl->status.map.init_ok) {
  582                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
  583                             "[BTC], %s(): return by btc not init!!\n", __func__);
  584                 pfwinfo->cnt_h2c_fail++;
  585                 return;
  586         } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
  587                     wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
  588                    (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
  589                     wl->status.map.lps == BTC_LPS_RF_OFF)) {
  590                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
  591                             "[BTC], %s(): return by wl off!!\n", __func__);
  592                 pfwinfo->cnt_h2c_fail++;
  593                 return;
  594         }
  595 
  596         pfwinfo->cnt_h2c++;
  597 
  598         ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
  599                                         false, true);
  600         if (ret != 0)
  601                 pfwinfo->cnt_h2c_fail++;
  602 }
  603 
  604 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
  605 {
  606         struct rtw89_btc *btc = &rtwdev->btc;
  607         struct rtw89_btc_cx *cx = &btc->cx;
  608         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
  609         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
  610         struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
  611         struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
  612         u8 i;
  613 
  614         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
  615 
  616         if (type & BTC_RESET_CX)
  617                 memset(cx, 0, sizeof(*cx));
  618         else if (type & BTC_RESET_BTINFO) /* only for BT enable */
  619                 memset(bt, 0, sizeof(*bt));
  620 
  621         if (type & BTC_RESET_CTRL) {
  622                 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
  623                 btc->ctrl.trace_step = FCXDEF_STEP;
  624         }
  625 
  626         /* Init Coex variables that are not zero */
  627         if (type & BTC_RESET_DM) {
  628                 memset(&btc->dm, 0, sizeof(btc->dm));
  629                 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
  630 
  631                 for (i = 0; i < RTW89_PORT_NUM; i++)
  632                         memset(wl_linfo[i].rssi_state, 0,
  633                                sizeof(wl_linfo[i].rssi_state));
  634 
  635                 /* set the slot_now table to original */
  636                 btc->dm.tdma_now = t_def[CXTD_OFF];
  637                 btc->dm.tdma = t_def[CXTD_OFF];
  638                 memcpy(&btc->dm.slot_now, s_def, sizeof(btc->dm.slot_now));
  639                 memcpy(&btc->dm.slot, s_def, sizeof(btc->dm.slot));
  640 
  641                 btc->policy_len = 0;
  642                 btc->bt_req_len = 0;
  643 
  644                 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
  645                 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
  646                 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
  647         }
  648 
  649         if (type & BTC_RESET_MDINFO)
  650                 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
  651 }
  652 
  653 #define BTC_FWINFO_BUF 1024
  654 
  655 #define BTC_RPT_HDR_SIZE 3
  656 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
  657 #define BTC_CHK_HANG_MAX 3
  658 
  659 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
  660 {
  661         struct rtw89_btc *btc = &rtwdev->btc;
  662         struct rtw89_btc_cx *cx = &btc->cx;
  663         struct rtw89_btc_dm *dm = &btc->dm;
  664         struct rtw89_btc_bt_info *bt = &cx->bt;
  665 
  666         rtw89_debug(rtwdev, RTW89_DBG_BTC,
  667                     "[BTC], %s(): type:%d cnt:%d\n",
  668                     __func__, type, cnt);
  669 
  670         switch (type) {
  671         case BTC_DCNT_RPT_FREEZE:
  672                 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
  673                         dm->cnt_dm[BTC_DCNT_RPT_FREEZE]++;
  674                 else
  675                         dm->cnt_dm[BTC_DCNT_RPT_FREEZE] = 0;
  676 
  677                 if (dm->cnt_dm[BTC_DCNT_RPT_FREEZE] >= BTC_CHK_HANG_MAX)
  678                         dm->error.map.wl_fw_hang = true;
  679                 else
  680                         dm->error.map.wl_fw_hang = false;
  681 
  682                 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
  683                 break;
  684         case BTC_DCNT_CYCLE_FREEZE:
  685                 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
  686                     (dm->tdma_now.type != CXTDMA_OFF ||
  687                      dm->tdma_now.ext_ctrl == CXECTL_EXT))
  688                         dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE]++;
  689                 else
  690                         dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] = 0;
  691 
  692                 if (dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] >= BTC_CHK_HANG_MAX)
  693                         dm->error.map.cycle_hang = true;
  694                 else
  695                         dm->error.map.cycle_hang = false;
  696 
  697                 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
  698                 break;
  699         case BTC_DCNT_W1_FREEZE:
  700                 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
  701                     dm->tdma_now.type != CXTDMA_OFF)
  702                         dm->cnt_dm[BTC_DCNT_W1_FREEZE]++;
  703                 else
  704                         dm->cnt_dm[BTC_DCNT_W1_FREEZE] = 0;
  705 
  706                 if (dm->cnt_dm[BTC_DCNT_W1_FREEZE] >= BTC_CHK_HANG_MAX)
  707                         dm->error.map.w1_hang = true;
  708                 else
  709                         dm->error.map.w1_hang = false;
  710 
  711                 dm->cnt_dm[BTC_DCNT_W1] = cnt;
  712                 break;
  713         case BTC_DCNT_B1_FREEZE:
  714                 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
  715                     dm->tdma_now.type != CXTDMA_OFF)
  716                         dm->cnt_dm[BTC_DCNT_B1_FREEZE]++;
  717                 else
  718                         dm->cnt_dm[BTC_DCNT_B1_FREEZE] = 0;
  719 
  720                 if (dm->cnt_dm[BTC_DCNT_B1_FREEZE] >= BTC_CHK_HANG_MAX)
  721                         dm->error.map.b1_hang = true;
  722                 else
  723                         dm->error.map.b1_hang = false;
  724 
  725                 dm->cnt_dm[BTC_DCNT_B1] = cnt;
  726                 break;
  727         case BTC_DCNT_TDMA_NONSYNC:
  728                 if (cnt != 0) /* if tdma not sync between drv/fw  */
  729                         dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
  730                 else
  731                         dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
  732 
  733                 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
  734                         dm->error.map.tdma_no_sync = true;
  735                 else
  736                         dm->error.map.tdma_no_sync = false;
  737                 break;
  738         case BTC_DCNT_SLOT_NONSYNC:
  739                 if (cnt != 0) /* if slot not sync between drv/fw  */
  740                         dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
  741                 else
  742                         dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
  743 
  744                 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
  745                         dm->error.map.tdma_no_sync = true;
  746                 else
  747                         dm->error.map.tdma_no_sync = false;
  748                 break;
  749         case BTC_DCNT_BTCNT_FREEZE:
  750                 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
  751                       cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
  752                       cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
  753                       cx->cnt_bt[BTC_BCNT_LOPRI_TX];
  754 
  755                 if (cnt == 0)
  756                         dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE]++;
  757                 else
  758                         dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
  759 
  760                 if ((dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX &&
  761                      bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] &&
  762                      !bt->enable.now))
  763                         _update_bt_scbd(rtwdev, false);
  764                 break;
  765         case BTC_DCNT_WL_SLOT_DRIFT:
  766                 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
  767                         dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
  768                 else
  769                         dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
  770 
  771                 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
  772                         dm->error.map.wl_slot_drift = true;
  773                 else
  774                         dm->error.map.wl_slot_drift = false;
  775                 break;
  776         }
  777 }
  778 
  779 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
  780 {
  781         struct rtw89_btc *btc = &rtwdev->btc;
  782         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
  783         struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
  784         struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
  785         struct rtw89_btc_fbtc_btver *pver = NULL;
  786         struct rtw89_btc_fbtc_btscan *pscan = NULL;
  787         struct rtw89_btc_fbtc_btafh *pafh = NULL;
  788         struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
  789 
  790         pver = (struct rtw89_btc_fbtc_btver *)pfinfo;
  791         pscan = (struct rtw89_btc_fbtc_btscan *)pfinfo;
  792         pafh = (struct rtw89_btc_fbtc_btafh *)pfinfo;
  793         pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
  794 
  795         rtw89_debug(rtwdev, RTW89_DBG_BTC,
  796                     "[BTC], %s(): rpt_type:%d\n",
  797                     __func__, rpt_type);
  798 
  799         switch (rpt_type) {
  800         case BTC_RPT_TYPE_BT_VER:
  801                 bt->ver_info.fw = le32_to_cpu(pver->fw_ver);
  802                 bt->ver_info.fw_coex = le32_get_bits(pver->coex_ver, GENMASK(7, 0));
  803                 bt->feature = le32_to_cpu(pver->feature);
  804                 break;
  805         case BTC_RPT_TYPE_BT_SCAN:
  806                 memcpy(bt->scan_info, pscan->scan, BTC_SCAN_MAX1);
  807                 break;
  808         case BTC_RPT_TYPE_BT_AFH:
  809                 memcpy(&bt_linfo->afh_map[0], pafh->afh_l, 4);
  810                 memcpy(&bt_linfo->afh_map[4], pafh->afh_m, 4);
  811                 memcpy(&bt_linfo->afh_map[8], pafh->afh_h, 2);
  812                 break;
  813         case BTC_RPT_TYPE_BT_DEVICE:
  814                 a2dp->device_name = le32_to_cpu(pdev->dev_name);
  815                 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
  816                 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
  817                 break;
  818         default:
  819                 break;
  820         }
  821 }
  822 
  823 struct rtw89_btc_fbtc_cysta_cpu {
  824         u8 fver;
  825         u8 rsvd;
  826         u16 cycles;
  827         u16 cycles_a2dp[CXT_FLCTRL_MAX];
  828         u16 a2dpept;
  829         u16 a2dpeptto;
  830         u16 tavg_cycle[CXT_MAX];
  831         u16 tmax_cycle[CXT_MAX];
  832         u16 tmaxdiff_cycle[CXT_MAX];
  833         u16 tavg_a2dp[CXT_FLCTRL_MAX];
  834         u16 tmax_a2dp[CXT_FLCTRL_MAX];
  835         u16 tavg_a2dpept;
  836         u16 tmax_a2dpept;
  837         u16 tavg_lk;
  838         u16 tmax_lk;
  839         u32 slot_cnt[CXST_MAX];
  840         u32 bcn_cnt[CXBCN_MAX];
  841         u32 leakrx_cnt;
  842         u32 collision_cnt;
  843         u32 skip_cnt;
  844         u32 exception;
  845         u32 except_cnt;
  846         u16 tslot_cycle[BTC_CYCLE_SLOT_MAX];
  847 };
  848 
  849 static void rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta *src,
  850                                         struct rtw89_btc_fbtc_cysta_cpu *dst)
  851 {
  852 #if defined(__linux__)
  853         static_assert(sizeof(*src) == sizeof(*dst));
  854 #elif defined(__FreeBSD__)
  855         rtw89_static_assert(sizeof(*src) == sizeof(*dst));
  856 #endif
  857 
  858 #define __CPY_U8(_x)    ({dst->_x = src->_x; })
  859 #define __CPY_LE16(_x)  ({dst->_x = le16_to_cpu(src->_x); })
  860 #define __CPY_LE16S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
  861                                    dst->_x[_i] = le16_to_cpu(src->_x[_i]); })
  862 #define __CPY_LE32(_x)  ({dst->_x = le32_to_cpu(src->_x); })
  863 #define __CPY_LE32S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
  864                                    dst->_x[_i] = le32_to_cpu(src->_x[_i]); })
  865 
  866         __CPY_U8(fver);
  867         __CPY_U8(rsvd);
  868         __CPY_LE16(cycles);
  869         __CPY_LE16S(cycles_a2dp);
  870         __CPY_LE16(a2dpept);
  871         __CPY_LE16(a2dpeptto);
  872         __CPY_LE16S(tavg_cycle);
  873         __CPY_LE16S(tmax_cycle);
  874         __CPY_LE16S(tmaxdiff_cycle);
  875         __CPY_LE16S(tavg_a2dp);
  876         __CPY_LE16S(tmax_a2dp);
  877         __CPY_LE16(tavg_a2dpept);
  878         __CPY_LE16(tmax_a2dpept);
  879         __CPY_LE16(tavg_lk);
  880         __CPY_LE16(tmax_lk);
  881         __CPY_LE32S(slot_cnt);
  882         __CPY_LE32S(bcn_cnt);
  883         __CPY_LE32(leakrx_cnt);
  884         __CPY_LE32(collision_cnt);
  885         __CPY_LE32(skip_cnt);
  886         __CPY_LE32(exception);
  887         __CPY_LE32(except_cnt);
  888         __CPY_LE16S(tslot_cycle);
  889 
  890 #undef __CPY_U8
  891 #undef __CPY_LE16
  892 #undef __CPY_LE16S
  893 #undef __CPY_LE32
  894 #undef __CPY_LE32S
  895 }
  896 
  897 #define BTC_LEAK_AP_TH 10
  898 #define BTC_CYSTA_CHK_PERIOD 100
  899 
  900 struct rtw89_btc_prpt {
  901         u8 type;
  902         __le16 len;
  903         u8 content[];
  904 } __packed;
  905 
  906 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
  907                            struct rtw89_btc_btf_fwinfo *pfwinfo,
  908                            u8 *prptbuf, u32 index)
  909 {
  910         const struct rtw89_chip_info *chip = rtwdev->chip;
  911         struct rtw89_btc *btc = &rtwdev->btc;
  912         struct rtw89_btc_dm *dm = &btc->dm;
  913         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
  914         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
  915         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
  916         struct rtw89_btc_fbtc_rpt_ctrl *prpt;
  917         struct rtw89_btc_fbtc_rpt_ctrl_v1 *prpt_v1;
  918         struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
  919         struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1 = NULL;
  920         struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
  921         struct rtw89_btc_prpt *btc_prpt = NULL;
  922         struct rtw89_btc_fbtc_slot *rtp_slot = NULL;
  923         u8 rpt_type = 0, *rpt_content = NULL, *pfinfo = NULL;
  924         u16 wl_slot_set = 0, wl_slot_real = 0;
  925         u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t;
  926         u32 cnt_leak_slot = 0, bt_slot_real = 0, cnt_rx_imr = 0;
  927         u8 i;
  928 
  929         rtw89_debug(rtwdev, RTW89_DBG_BTC,
  930                     "[BTC], %s(): index:%d\n",
  931                     __func__, index);
  932 
  933         if (!prptbuf) {
  934                 pfwinfo->err[BTFRE_INVALID_INPUT]++;
  935                 return 0;
  936         }
  937 
  938         btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
  939         rpt_type = btc_prpt->type;
  940         rpt_len = le16_to_cpu(btc_prpt->len);
  941         rpt_content = btc_prpt->content;
  942 
  943         rtw89_debug(rtwdev, RTW89_DBG_BTC,
  944                     "[BTC], %s(): rpt_type:%d\n",
  945                     __func__, rpt_type);
  946 
  947         switch (rpt_type) {
  948         case BTC_RPT_TYPE_CTRL:
  949                 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
  950                 if (chip->chip_id == RTL8852A) {
  951                         pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
  952                         pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
  953                 } else {
  954                         pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo_v1);
  955                         pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo_v1);
  956                 }
  957                 pcinfo->req_fver = chip->fcxbtcrpt_ver;
  958                 pcinfo->rx_len = rpt_len;
  959                 pcinfo->rx_cnt++;
  960                 break;
  961         case BTC_RPT_TYPE_TDMA:
  962                 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
  963                 if (chip->chip_id == RTL8852A) {
  964                         pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo;
  965                         pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
  966                 } else {
  967                         pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo_v1;
  968                         pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo_v1);
  969                 }
  970                 pcinfo->req_fver = chip->fcxtdma_ver;
  971                 pcinfo->rx_len = rpt_len;
  972                 pcinfo->rx_cnt++;
  973                 break;
  974         case BTC_RPT_TYPE_SLOT:
  975                 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
  976                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_slots.finfo);
  977                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
  978                 pcinfo->req_fver = chip->fcxslots_ver;
  979                 pcinfo->rx_len = rpt_len;
  980                 pcinfo->rx_cnt++;
  981                 break;
  982         case BTC_RPT_TYPE_CYSTA:
  983                 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
  984                 if (chip->chip_id == RTL8852A) {
  985                         pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
  986                         pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
  987                         rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
  988                         pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
  989                 } else {
  990                         pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo_v1);
  991                         pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
  992                         pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo_v1);
  993                 }
  994                 pcinfo->req_fver = chip->fcxcysta_ver;
  995                 pcinfo->rx_len = rpt_len;
  996                 pcinfo->rx_cnt++;
  997                 break;
  998         case BTC_RPT_TYPE_STEP:
  999                 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
 1000                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_step.finfo);
 1001                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
 1002                                   trace_step + 8;
 1003                 pcinfo->req_fver = chip->fcxstep_ver;
 1004                 pcinfo->rx_len = rpt_len;
 1005                 pcinfo->rx_cnt++;
 1006                 break;
 1007         case BTC_RPT_TYPE_NULLSTA:
 1008                 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
 1009                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_nullsta.finfo);
 1010                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
 1011                 pcinfo->req_fver = chip->fcxnullsta_ver;
 1012                 pcinfo->rx_len = rpt_len;
 1013                 pcinfo->rx_cnt++;
 1014                 break;
 1015         case BTC_RPT_TYPE_MREG:
 1016                 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
 1017                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_mregval.finfo);
 1018                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo);
 1019                 pcinfo->req_fver = chip->fcxmreg_ver;
 1020                 pcinfo->rx_len = rpt_len;
 1021                 pcinfo->rx_cnt++;
 1022                 break;
 1023         case BTC_RPT_TYPE_GPIO_DBG:
 1024                 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
 1025                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_gpio_dbg.finfo);
 1026                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo);
 1027                 pcinfo->req_fver = chip->fcxgpiodbg_ver;
 1028                 pcinfo->rx_len = rpt_len;
 1029                 pcinfo->rx_cnt++;
 1030                 break;
 1031         case BTC_RPT_TYPE_BT_VER:
 1032                 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
 1033                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btver.finfo);
 1034                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo);
 1035                 pcinfo->req_fver = chip->fcxbtver_ver;
 1036                 pcinfo->rx_len = rpt_len;
 1037                 pcinfo->rx_cnt++;
 1038                 break;
 1039         case BTC_RPT_TYPE_BT_SCAN:
 1040                 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
 1041                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btscan.finfo);
 1042                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo);
 1043                 pcinfo->req_fver = chip->fcxbtscan_ver;
 1044                 pcinfo->rx_len = rpt_len;
 1045                 pcinfo->rx_cnt++;
 1046                 break;
 1047         case BTC_RPT_TYPE_BT_AFH:
 1048                 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
 1049                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btafh.finfo);
 1050                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo);
 1051                 pcinfo->req_fver = chip->fcxbtafh_ver;
 1052                 pcinfo->rx_len = rpt_len;
 1053                 pcinfo->rx_cnt++;
 1054                 break;
 1055         case BTC_RPT_TYPE_BT_DEVICE:
 1056                 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
 1057                 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btdev.finfo);
 1058                 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
 1059                 pcinfo->req_fver = chip->fcxbtdevinfo_ver;
 1060                 pcinfo->rx_len = rpt_len;
 1061                 pcinfo->rx_cnt++;
 1062                 break;
 1063         default:
 1064                 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
 1065                 return 0;
 1066         }
 1067 
 1068         if (rpt_len != pcinfo->req_len) {
 1069                 if (rpt_type < BTC_RPT_TYPE_MAX)
 1070                         pfwinfo->len_mismch |= (0x1 << rpt_type);
 1071                 else
 1072                         pfwinfo->len_mismch |= BIT(31);
 1073                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1074                             "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
 1075                             __func__, rpt_type, rpt_len, pcinfo->req_len);
 1076 
 1077                 pcinfo->valid = 0;
 1078                 return 0;
 1079         } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
 1080                 pfwinfo->err[BTFRE_EXCEPTION]++;
 1081                 pcinfo->valid = 0;
 1082                 return 0;
 1083         }
 1084 
 1085         memcpy(pfinfo, rpt_content, pcinfo->req_len);
 1086         pcinfo->valid = 1;
 1087 
 1088         if (rpt_type == BTC_RPT_TYPE_TDMA && chip->chip_id == RTL8852A) {
 1089                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1090                             "[BTC], %s(): check %d %zu\n", __func__,
 1091                             BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
 1092 
 1093                 if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo,
 1094                            sizeof(dm->tdma_now)) != 0) {
 1095                         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1096                                     "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
 1097                                     __func__, BTC_DCNT_TDMA_NONSYNC,
 1098                                     dm->tdma_now.type, dm->tdma_now.rxflctrl,
 1099                                     dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
 1100                                     dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
 1101                                     dm->tdma_now.rxflctrl_role,
 1102                                     dm->tdma_now.option_ctrl);
 1103 
 1104                         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1105                                     "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
 1106                                     __func__, BTC_DCNT_TDMA_NONSYNC,
 1107                                     pfwinfo->rpt_fbtc_tdma.finfo.type,
 1108                                     pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl,
 1109                                     pfwinfo->rpt_fbtc_tdma.finfo.txpause,
 1110                                     pfwinfo->rpt_fbtc_tdma.finfo.wtgle_n,
 1111                                     pfwinfo->rpt_fbtc_tdma.finfo.leak_n,
 1112                                     pfwinfo->rpt_fbtc_tdma.finfo.ext_ctrl,
 1113                                     pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl_role,
 1114                                     pfwinfo->rpt_fbtc_tdma.finfo.option_ctrl);
 1115                 }
 1116 
 1117                 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
 1118                              memcmp(&dm->tdma_now,
 1119                                     &pfwinfo->rpt_fbtc_tdma.finfo,
 1120                                     sizeof(dm->tdma_now)));
 1121         } else if (rpt_type == BTC_RPT_TYPE_TDMA) {
 1122                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1123                             "[BTC], %s(): check %d %zu\n", __func__,
 1124                             BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
 1125 
 1126                 if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
 1127                            sizeof(dm->tdma_now)) != 0) {
 1128                         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1129                                     "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
 1130                                     __func__, BTC_DCNT_TDMA_NONSYNC,
 1131                                     dm->tdma_now.type, dm->tdma_now.rxflctrl,
 1132                                     dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
 1133                                     dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
 1134                                     dm->tdma_now.rxflctrl_role,
 1135                                     dm->tdma_now.option_ctrl);
 1136                         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1137                                     "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
 1138                                     __func__, BTC_DCNT_TDMA_NONSYNC,
 1139                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.type,
 1140                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl,
 1141                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.txpause,
 1142                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.wtgle_n,
 1143                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.leak_n,
 1144                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.ext_ctrl,
 1145                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl_role,
 1146                                     pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.option_ctrl);
 1147                 }
 1148 
 1149                 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
 1150                              memcmp(&dm->tdma_now,
 1151                                     &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
 1152                                     sizeof(dm->tdma_now)));
 1153         }
 1154 
 1155         if (rpt_type == BTC_RPT_TYPE_SLOT) {
 1156                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1157                             "[BTC], %s(): check %d %zu\n",
 1158                             __func__, BTC_DCNT_SLOT_NONSYNC,
 1159                             sizeof(dm->slot_now));
 1160 
 1161                 if (memcmp(dm->slot_now, pfwinfo->rpt_fbtc_slots.finfo.slot,
 1162                            sizeof(dm->slot_now)) != 0) {
 1163                         for (i = 0; i < CXST_MAX; i++) {
 1164                                 rtp_slot =
 1165                                 &pfwinfo->rpt_fbtc_slots.finfo.slot[i];
 1166                                 if (memcmp(&dm->slot_now[i], rtp_slot,
 1167                                            sizeof(dm->slot_now[i])) != 0) {
 1168                                         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1169                                                     "[BTC], %s(): %d slot_now[%d] dur=0x%04x tbl=%08x type=0x%04x\n",
 1170                                                     __func__,
 1171                                                     BTC_DCNT_SLOT_NONSYNC, i,
 1172                                                     dm->slot_now[i].dur,
 1173                                                     dm->slot_now[i].cxtbl,
 1174                                                     dm->slot_now[i].cxtype);
 1175 
 1176                                         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1177                                                     "[BTC], %s(): %d rpt_fbtc_slots[%d] dur=0x%04x tbl=%08x type=0x%04x\n",
 1178                                                     __func__,
 1179                                                     BTC_DCNT_SLOT_NONSYNC, i,
 1180                                                     rtp_slot->dur,
 1181                                                     rtp_slot->cxtbl,
 1182                                                     rtp_slot->cxtype);
 1183                                 }
 1184                         }
 1185                 }
 1186                 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
 1187                              memcmp(dm->slot_now,
 1188                                     pfwinfo->rpt_fbtc_slots.finfo.slot,
 1189                                     sizeof(dm->slot_now)));
 1190         }
 1191 
 1192         if (rpt_type == BTC_RPT_TYPE_CYSTA && chip->chip_id == RTL8852A &&
 1193             pcysta->cycles >= BTC_CYSTA_CHK_PERIOD) {
 1194                 /* Check Leak-AP */
 1195                 if (pcysta->slot_cnt[CXST_LK] != 0 &&
 1196                     pcysta->leakrx_cnt != 0 && dm->tdma_now.rxflctrl) {
 1197                         if (pcysta->slot_cnt[CXST_LK] <
 1198                             BTC_LEAK_AP_TH * pcysta->leakrx_cnt)
 1199                                 dm->leak_ap = 1;
 1200                 }
 1201 
 1202                 /* Check diff time between WL slot and W1/E2G slot */
 1203                 if (dm->tdma_now.type == CXTDMA_OFF &&
 1204                     dm->tdma_now.ext_ctrl == CXECTL_EXT)
 1205                         wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur);
 1206                 else
 1207                         wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
 1208 
 1209                 if (pcysta->tavg_cycle[CXT_WL] > wl_slot_set) {
 1210                         diff_t = pcysta->tavg_cycle[CXT_WL] - wl_slot_set;
 1211                         _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
 1212                 }
 1213 
 1214                 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_W1]);
 1215                 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_B1]);
 1216                 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE, (u32)pcysta->cycles);
 1217         } else if (rpt_type == BTC_RPT_TYPE_CYSTA && pcysta_v1 &&
 1218                    le16_to_cpu(pcysta_v1->cycles) >= BTC_CYSTA_CHK_PERIOD) {
 1219                 cnt_leak_slot = le32_to_cpu(pcysta_v1->slot_cnt[CXST_LK]);
 1220                 cnt_rx_imr = le32_to_cpu(pcysta_v1->leak_slot.cnt_rximr);
 1221                 /* Check Leak-AP */
 1222                 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
 1223                     dm->tdma_now.rxflctrl) {
 1224                         if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
 1225                                 dm->leak_ap = 1;
 1226                 }
 1227 
 1228                 /* Check diff time between real WL slot and W1 slot */
 1229                 if (dm->tdma_now.type == CXTDMA_OFF) {
 1230                         wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
 1231                         wl_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_WL]);
 1232                         if (wl_slot_real > wl_slot_set) {
 1233                                 diff_t = wl_slot_real - wl_slot_set;
 1234                                 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
 1235                         }
 1236                 }
 1237 
 1238                 /* Check diff time between real BT slot and EBT/E5G slot */
 1239                 if (dm->tdma_now.type == CXTDMA_OFF &&
 1240                     dm->tdma_now.ext_ctrl == CXECTL_EXT &&
 1241                     btc->bt_req_len != 0) {
 1242                         bt_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_BT]);
 1243 
 1244                         if (btc->bt_req_len > bt_slot_real) {
 1245                                 diff_t = btc->bt_req_len - bt_slot_real;
 1246                                 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
 1247                         }
 1248                 }
 1249 
 1250                 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE,
 1251                              le32_to_cpu(pcysta_v1->slot_cnt[CXST_W1]));
 1252                 _chk_btc_err(rtwdev, BTC_DCNT_B1_FREEZE,
 1253                              le32_to_cpu(pcysta_v1->slot_cnt[CXST_B1]));
 1254                 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE,
 1255                              (u32)le16_to_cpu(pcysta_v1->cycles));
 1256         }
 1257 
 1258         if (rpt_type == BTC_RPT_TYPE_CTRL && chip->chip_id == RTL8852A) {
 1259                 prpt = &pfwinfo->rpt_ctrl.finfo;
 1260                 btc->fwinfo.rpt_en_map = prpt->rpt_enable;
 1261                 wl->ver_info.fw_coex = prpt->wl_fw_coex_ver;
 1262                 wl->ver_info.fw = prpt->wl_fw_ver;
 1263                 dm->wl_fw_cx_offload = !!prpt->wl_fw_cx_offload;
 1264 
 1265                 _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
 1266                              pfwinfo->event[BTF_EVNT_RPT]);
 1267 
 1268                 /* To avoid I/O if WL LPS or power-off */
 1269                 if (wl->status.map.lps != BTC_LPS_RF_OFF && !wl->status.map.rf_off) {
 1270                         rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
 1271                         _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
 1272 
 1273                         btc->cx.cnt_bt[BTC_BCNT_POLUT] =
 1274                                 rtw89_mac_get_plt_cnt(rtwdev, RTW89_MAC_0);
 1275                 }
 1276         } else if (rpt_type == BTC_RPT_TYPE_CTRL) {
 1277                 prpt_v1 = &pfwinfo->rpt_ctrl.finfo_v1;
 1278                 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt_v1->rpt_info.en);
 1279                 wl->ver_info.fw_coex = le32_to_cpu(prpt_v1->wl_fw_info.cx_ver);
 1280                 wl->ver_info.fw = le32_to_cpu(prpt_v1->wl_fw_info.fw_ver);
 1281                 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt_v1->wl_fw_info.cx_offload);
 1282 
 1283                 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
 1284                         memcpy(&dm->gnt.band[i], &prpt_v1->gnt_val[i],
 1285                                sizeof(dm->gnt.band[i]));
 1286 
 1287                 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_TX]);
 1288                 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_RX]);
 1289                 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_TX]);
 1290                 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_RX]);
 1291                 btc->cx.cnt_bt[BTC_BCNT_POLUT] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_POLLUTED]);
 1292 
 1293                 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
 1294                 _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
 1295                              pfwinfo->event[BTF_EVNT_RPT]);
 1296 
 1297                 if (le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
 1298                         bt->rfk_info.map.timeout = 1;
 1299                 else
 1300                         bt->rfk_info.map.timeout = 0;
 1301 
 1302                 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
 1303         }
 1304 
 1305         if (rpt_type >= BTC_RPT_TYPE_BT_VER &&
 1306             rpt_type <= BTC_RPT_TYPE_BT_DEVICE)
 1307                 _update_bt_report(rtwdev, rpt_type, pfinfo);
 1308 
 1309         return (rpt_len + BTC_RPT_HDR_SIZE);
 1310 }
 1311 
 1312 static void _parse_btc_report(struct rtw89_dev *rtwdev,
 1313                               struct rtw89_btc_btf_fwinfo *pfwinfo,
 1314                               u8 *pbuf, u32 buf_len)
 1315 {
 1316         struct rtw89_btc_prpt *btc_prpt = NULL;
 1317         u32 index = 0, rpt_len = 0;
 1318 
 1319         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1320                     "[BTC], %s(): buf_len:%d\n",
 1321                     __func__, buf_len);
 1322 
 1323         while (pbuf) {
 1324                 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
 1325                 if (index + 2 >= BTC_FWINFO_BUF)
 1326                         break;
 1327                 /* At least 3 bytes: type(1) & len(2) */
 1328                 rpt_len = le16_to_cpu(btc_prpt->len);
 1329                 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
 1330                         break;
 1331 
 1332                 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
 1333                 if (!rpt_len)
 1334                         break;
 1335                 index += rpt_len;
 1336         }
 1337 }
 1338 
 1339 #define BTC_TLV_HDR_LEN 2
 1340 
 1341 static void _append_tdma(struct rtw89_dev *rtwdev)
 1342 {
 1343         const struct rtw89_chip_info *chip = rtwdev->chip;
 1344         struct rtw89_btc *btc = &rtwdev->btc;
 1345         struct rtw89_btc_dm *dm = &btc->dm;
 1346         struct rtw89_btc_btf_tlv *tlv;
 1347         struct rtw89_btc_fbtc_tdma *v;
 1348         struct rtw89_btc_fbtc_tdma_v1 *v1;
 1349         u16 len = btc->policy_len;
 1350 
 1351         if (!btc->update_policy_force &&
 1352             !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
 1353                 rtw89_debug(rtwdev,
 1354                             RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
 1355                             __func__);
 1356                 return;
 1357         }
 1358 
 1359         tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
 1360         tlv->type = CXPOLICY_TDMA;
 1361         if (chip->chip_id == RTL8852A) {
 1362                 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
 1363                 tlv->len = sizeof(*v);
 1364                 memcpy(v, &dm->tdma, sizeof(*v));
 1365                 btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
 1366         } else {
 1367                 tlv->len = sizeof(*v1);
 1368                 v1 = (struct rtw89_btc_fbtc_tdma_v1 *)&tlv->val[0];
 1369                 v1->fver = chip->fcxtdma_ver;
 1370                 v1->tdma = dm->tdma;
 1371                 btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v1);
 1372         }
 1373 
 1374         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1375                     "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
 1376                     __func__, dm->tdma.type, dm->tdma.rxflctrl,
 1377                     dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
 1378                     dm->tdma.ext_ctrl);
 1379 }
 1380 
 1381 static void _append_slot(struct rtw89_dev *rtwdev)
 1382 {
 1383         struct rtw89_btc *btc = &rtwdev->btc;
 1384         struct rtw89_btc_dm *dm = &btc->dm;
 1385         struct rtw89_btc_btf_tlv *tlv = NULL;
 1386         struct btc_fbtc_1slot *v = NULL;
 1387         u16 len = 0;
 1388         u8 i, cnt = 0;
 1389 
 1390         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1391                     "[BTC], %s(): A:btc->policy_len = %d\n",
 1392                     __func__, btc->policy_len);
 1393 
 1394         for (i = 0; i < CXST_MAX; i++) {
 1395                 if (!btc->update_policy_force &&
 1396                     !memcmp(&dm->slot[i], &dm->slot_now[i],
 1397                             sizeof(dm->slot[i])))
 1398                         continue;
 1399 
 1400                 len = btc->policy_len;
 1401 
 1402                 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
 1403                 v = (struct btc_fbtc_1slot *)&tlv->val[0];
 1404                 tlv->type = CXPOLICY_SLOT;
 1405                 tlv->len = sizeof(*v);
 1406 
 1407                 v->fver = FCXONESLOT_VER;
 1408                 v->sid = i;
 1409                 v->slot = dm->slot[i];
 1410 
 1411                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1412                             "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
 1413                             __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl,
 1414                             dm->slot[i].cxtype);
 1415                 cnt++;
 1416 
 1417                 btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
 1418         }
 1419 
 1420         if (cnt > 0)
 1421                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1422                             "[BTC], %s(): slot update (cnt=%d)!!\n",
 1423                             __func__, cnt);
 1424 }
 1425 
 1426 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
 1427                                 u32 rpt_map, bool rpt_state)
 1428 {
 1429         struct rtw89_btc *btc = &rtwdev->btc;
 1430         struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
 1431         struct rtw89_btc_btf_set_report r = {0};
 1432         u32 val = 0;
 1433 
 1434         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1435                     "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
 1436                     __func__, rpt_map, rpt_state);
 1437 
 1438         if (rpt_state)
 1439                 val = fwinfo->rpt_en_map | rpt_map;
 1440         else
 1441                 val = fwinfo->rpt_en_map & ~rpt_map;
 1442 
 1443         if (val == fwinfo->rpt_en_map)
 1444                 return;
 1445 
 1446         fwinfo->rpt_en_map = val;
 1447 
 1448         r.fver = BTF_SET_REPORT_VER;
 1449         r.enable = cpu_to_le32(val);
 1450         r.para = cpu_to_le32(rpt_state);
 1451 
 1452         _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r, sizeof(r));
 1453 }
 1454 
 1455 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num,
 1456                                    struct rtw89_btc_fbtc_slot *s)
 1457 {
 1458         struct rtw89_btc_btf_set_slot_table *tbl = NULL;
 1459         u8 *ptr = NULL;
 1460         u16 n = 0;
 1461 
 1462         n = sizeof(*s) * num + sizeof(*tbl);
 1463         tbl = kmalloc(n, GFP_KERNEL);
 1464         if (!tbl)
 1465                 return;
 1466 
 1467         tbl->fver = BTF_SET_SLOT_TABLE_VER;
 1468         tbl->tbl_num = num;
 1469         ptr = &tbl->buf[0];
 1470         memcpy(ptr, s, num * sizeof(*s));
 1471 
 1472         _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
 1473 
 1474         kfree(tbl);
 1475 }
 1476 
 1477 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
 1478 {
 1479         const struct rtw89_chip_info *chip = rtwdev->chip;
 1480         struct rtw89_btc_btf_set_mon_reg *monreg = NULL;
 1481         u8 n, *ptr = NULL, ulen;
 1482         u16 sz = 0;
 1483 
 1484         n = chip->mon_reg_num;
 1485 
 1486         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1487                     "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
 1488         if (n > CXMREG_MAX) {
 1489                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1490                             "[BTC], %s(): mon reg count %d > %d\n",
 1491                             __func__, n, CXMREG_MAX);
 1492                 return;
 1493         }
 1494 
 1495         ulen = sizeof(struct rtw89_btc_fbtc_mreg);
 1496         sz = (ulen * n) + sizeof(*monreg);
 1497         monreg = kmalloc(sz, GFP_KERNEL);
 1498         if (!monreg)
 1499                 return;
 1500 
 1501         monreg->fver = BTF_SET_MON_REG_VER;
 1502         monreg->reg_num = n;
 1503         ptr = &monreg->buf[0];
 1504         memcpy(ptr, chip->mon_reg, n * ulen);
 1505         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1506                     "[BTC], %s(): sz=%d ulen=%d n=%d\n",
 1507                     __func__, sz, ulen, n);
 1508 
 1509         _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, (u8 *)monreg, sz);
 1510         kfree(monreg);
 1511         rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
 1512 }
 1513 
 1514 static void _update_dm_step(struct rtw89_dev *rtwdev,
 1515                             enum btc_reason_and_action reason_or_action)
 1516 {
 1517         struct rtw89_btc *btc = &rtwdev->btc;
 1518         struct rtw89_btc_dm *dm = &btc->dm;
 1519 
 1520         /* use ring-structure to store dm step */
 1521         dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
 1522         dm->dm_step.step_pos++;
 1523 
 1524         if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
 1525                 dm->dm_step.step_pos = 0;
 1526                 dm->dm_step.step_ov = true;
 1527         }
 1528 }
 1529 
 1530 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
 1531                            enum btc_reason_and_action action)
 1532 {
 1533         struct rtw89_btc *btc = &rtwdev->btc;
 1534         struct rtw89_btc_dm *dm = &btc->dm;
 1535 
 1536         dm->run_action = action;
 1537 
 1538         _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
 1539         _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
 1540 
 1541         btc->policy_len = 0;
 1542         btc->policy_type = policy_type;
 1543 
 1544         _append_tdma(rtwdev);
 1545         _append_slot(rtwdev);
 1546 
 1547         if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
 1548                 return;
 1549 
 1550         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1551                     "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
 1552                     __func__, action, policy_type, btc->policy_len);
 1553 
 1554         if (dm->tdma.rxflctrl == CXFLC_NULLP ||
 1555             dm->tdma.rxflctrl == CXFLC_QOSNULL)
 1556                 btc->lps = 1;
 1557         else
 1558                 btc->lps = 0;
 1559 
 1560         if (btc->lps == 1)
 1561                 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
 1562 
 1563         _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
 1564                      btc->policy, btc->policy_len);
 1565 
 1566         memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
 1567         memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now));
 1568 
 1569         if (btc->update_policy_force)
 1570                 btc->update_policy_force = false;
 1571 
 1572         if (btc->lps == 0)
 1573                 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
 1574 }
 1575 
 1576 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
 1577 {
 1578         const struct rtw89_chip_info *chip = rtwdev->chip;
 1579 
 1580         switch (type) {
 1581         case CXDRVINFO_INIT:
 1582                 rtw89_fw_h2c_cxdrv_init(rtwdev);
 1583                 break;
 1584         case CXDRVINFO_ROLE:
 1585                 if (chip->chip_id == RTL8852A)
 1586                         rtw89_fw_h2c_cxdrv_role(rtwdev);
 1587                 else
 1588                         rtw89_fw_h2c_cxdrv_role_v1(rtwdev);
 1589                 break;
 1590         case CXDRVINFO_CTRL:
 1591                 rtw89_fw_h2c_cxdrv_ctrl(rtwdev);
 1592                 break;
 1593         case CXDRVINFO_RFK:
 1594                 rtw89_fw_h2c_cxdrv_rfk(rtwdev);
 1595                 break;
 1596         default:
 1597                 break;
 1598         }
 1599 }
 1600 
 1601 static
 1602 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
 1603 {
 1604         struct rtw89_btc *btc = &rtwdev->btc;
 1605         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 1606 
 1607         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1608                     "[BTC], %s(): evt_id:%d len:%d\n",
 1609                     __func__, evt_id, len);
 1610 
 1611         if (!len || !data)
 1612                 return;
 1613 
 1614         switch (evt_id) {
 1615         case BTF_EVNT_RPT:
 1616                 _parse_btc_report(rtwdev, pfwinfo, data, len);
 1617                 break;
 1618         default:
 1619                 break;
 1620         }
 1621 }
 1622 
 1623 static void _set_gnt_wl(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
 1624 {
 1625         struct rtw89_btc *btc = &rtwdev->btc;
 1626         struct rtw89_btc_dm *dm = &btc->dm;
 1627         struct rtw89_mac_ax_gnt *g = dm->gnt.band;
 1628         u8 i;
 1629 
 1630         if (phy_map > BTC_PHY_ALL)
 1631                 return;
 1632 
 1633         for (i = 0; i < RTW89_PHY_MAX; i++) {
 1634                 if (!(phy_map & BIT(i)))
 1635                         continue;
 1636 
 1637                 switch (state) {
 1638                 case BTC_GNT_HW:
 1639                         g[i].gnt_wl_sw_en = 0;
 1640                         g[i].gnt_wl = 0;
 1641                         break;
 1642                 case BTC_GNT_SW_LO:
 1643                         g[i].gnt_wl_sw_en = 1;
 1644                         g[i].gnt_wl = 0;
 1645                         break;
 1646                 case BTC_GNT_SW_HI:
 1647                         g[i].gnt_wl_sw_en = 1;
 1648                         g[i].gnt_wl = 1;
 1649                         break;
 1650                 }
 1651         }
 1652 
 1653         rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
 1654 }
 1655 
 1656 #define BTC_TDMA_WLROLE_MAX 2
 1657 
 1658 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
 1659 {
 1660         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1661                     "[BTC], %s(): set bt %s wlan_act\n", __func__,
 1662                     enable ? "ignore" : "do not ignore");
 1663 
 1664         _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
 1665 }
 1666 
 1667 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
 1668 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
 1669 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
 1670 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
 1671 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
 1672 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
 1673 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
 1674 
 1675 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
 1676 {
 1677         const struct rtw89_chip_info *chip = rtwdev->chip;
 1678         struct rtw89_btc *btc = &rtwdev->btc;
 1679         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 1680         u32 pwr_val;
 1681 
 1682         if (wl->rf_para.tx_pwr_freerun == level)
 1683                 return;
 1684 
 1685         wl->rf_para.tx_pwr_freerun = level;
 1686         btc->dm.rf_trx_para.wl_tx_power = level;
 1687 
 1688         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1689                     "[BTC], %s(): level = %d\n",
 1690                     __func__, level);
 1691 
 1692         if (level == RTW89_BTC_WL_DEF_TX_PWR) {
 1693                 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
 1694         } else { /* only apply "force tx power" */
 1695                 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
 1696                 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
 1697                         pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
 1698 
 1699                 if (level & B_BTC_WL_TX_POWER_SIGN)
 1700                         pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
 1701                 pwr_val |= WL_TX_POWER_WITH_BT;
 1702         }
 1703 
 1704         chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
 1705 }
 1706 
 1707 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
 1708 {
 1709         struct rtw89_btc *btc = &rtwdev->btc;
 1710         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 1711 
 1712         if (wl->rf_para.rx_gain_freerun == level)
 1713                 return;
 1714 
 1715         wl->rf_para.rx_gain_freerun = level;
 1716         btc->dm.rf_trx_para.wl_rx_gain = level;
 1717 
 1718         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1719                     "[BTC], %s(): level = %d\n",
 1720                     __func__, level);
 1721 }
 1722 
 1723 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
 1724 {
 1725         struct rtw89_btc *btc = &rtwdev->btc;
 1726         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 1727         u8 buf;
 1728 
 1729         if (bt->rf_para.tx_pwr_freerun == level)
 1730                 return;
 1731 
 1732         bt->rf_para.tx_pwr_freerun = level;
 1733         btc->dm.rf_trx_para.bt_tx_power = level;
 1734 
 1735         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1736                     "[BTC], %s(): level = %d\n",
 1737                     __func__, level);
 1738 
 1739         buf = (s8)(-level);
 1740         _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
 1741 }
 1742 
 1743 #define BTC_BT_RX_NORMAL_LVL 7
 1744 
 1745 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
 1746 {
 1747         struct rtw89_btc *btc = &rtwdev->btc;
 1748         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 1749 
 1750         if (bt->rf_para.rx_gain_freerun == level ||
 1751             level > BTC_BT_RX_NORMAL_LVL)
 1752                 return;
 1753 
 1754         bt->rf_para.rx_gain_freerun = level;
 1755         btc->dm.rf_trx_para.bt_rx_gain = level;
 1756 
 1757         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1758                     "[BTC], %s(): level = %d\n",
 1759                     __func__, level);
 1760 
 1761         if (level == BTC_BT_RX_NORMAL_LVL)
 1762                 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
 1763         else
 1764                 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
 1765 
 1766         _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, 1);
 1767 }
 1768 
 1769 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
 1770 {
 1771         const struct rtw89_chip_info *chip = rtwdev->chip;
 1772         struct rtw89_btc *btc = &rtwdev->btc;
 1773         struct rtw89_btc_dm *dm = &btc->dm;
 1774         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 1775         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 1776         struct rtw89_btc_rf_trx_para para;
 1777         u32 wl_stb_chg = 0;
 1778         u8 level_id = 0;
 1779 
 1780         if (!dm->freerun) {
 1781                 dm->trx_para_level = 0;
 1782                 chip->ops->btc_bt_aci_imp(rtwdev);
 1783         }
 1784 
 1785         level_id = (u8)dm->trx_para_level;
 1786 
 1787         if (level_id >= chip->rf_para_dlink_num ||
 1788             level_id >= chip->rf_para_ulink_num) {
 1789                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1790                             "[BTC], %s(): invalid level_id: %d\n",
 1791                             __func__, level_id);
 1792                 return;
 1793         }
 1794 
 1795         if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
 1796                 para = chip->rf_para_ulink[level_id];
 1797         else
 1798                 para = chip->rf_para_dlink[level_id];
 1799 
 1800         if (para.wl_tx_power != RTW89_BTC_WL_DEF_TX_PWR)
 1801                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1802                             "[BTC], %s(): wl_tx_power=%d\n",
 1803                             __func__, para.wl_tx_power);
 1804         _set_wl_tx_power(rtwdev, para.wl_tx_power);
 1805         _set_wl_rx_gain(rtwdev, para.wl_rx_gain);
 1806         _set_bt_tx_power(rtwdev, para.bt_tx_power);
 1807         _set_bt_rx_gain(rtwdev, para.bt_rx_gain);
 1808 
 1809         if (bt->enable.now == 0 || wl->status.map.rf_off == 1 ||
 1810             wl->status.map.lps == BTC_LPS_RF_OFF)
 1811                 wl_stb_chg = 0;
 1812         else
 1813                 wl_stb_chg = 1;
 1814 
 1815         if (wl_stb_chg != dm->wl_stb_chg) {
 1816                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1817                             "[BTC], %s(): wl_stb_chg=%d\n",
 1818                             __func__, wl_stb_chg);
 1819                 dm->wl_stb_chg = wl_stb_chg;
 1820                 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
 1821         }
 1822 }
 1823 
 1824 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
 1825 {
 1826         struct rtw89_btc *btc = &rtwdev->btc;
 1827         struct rtw89_btc_cx *cx = &btc->cx;
 1828         struct rtw89_btc_wl_info *wl = &cx->wl;
 1829         struct rtw89_btc_bt_info *bt = &cx->bt;
 1830         struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
 1831 
 1832         if (wl->status.map.connecting || wl->status.map._4way ||
 1833             wl->status.map.roaming) {
 1834                 cx->state_map = BTC_WLINKING;
 1835         } else if (wl->status.map.scan) { /* wl scan */
 1836                 if (bt_linfo->status.map.inq_pag)
 1837                         cx->state_map = BTC_WSCAN_BSCAN;
 1838                 else
 1839                         cx->state_map = BTC_WSCAN_BNOSCAN;
 1840         } else if (wl->status.map.busy) { /* only busy */
 1841                 if (bt_linfo->status.map.inq_pag)
 1842                         cx->state_map = BTC_WBUSY_BSCAN;
 1843                 else
 1844                         cx->state_map = BTC_WBUSY_BNOSCAN;
 1845         } else { /* wl idle */
 1846                 cx->state_map = BTC_WIDLE;
 1847         }
 1848 }
 1849 
 1850 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
 1851 {
 1852         const struct rtw89_chip_info *chip = rtwdev->chip;
 1853         struct rtw89_btc *btc = &rtwdev->btc;
 1854         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 1855         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 1856         struct rtw89_btc_bt_link_info *b = &bt->link_info;
 1857         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 1858         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 1859         struct rtw89_btc_wl_active_role *r;
 1860         struct rtw89_btc_wl_active_role_v1 *r1;
 1861         u8 en = 0, i, ch = 0, bw = 0;
 1862         u8 mode, connect_cnt;
 1863 
 1864         if (btc->ctrl.manual || wl->status.map.scan)
 1865                 return;
 1866 
 1867         if (chip->chip_id == RTL8852A) {
 1868                 mode = wl_rinfo->link_mode;
 1869                 connect_cnt = wl_rinfo->connect_cnt;
 1870         } else {
 1871                 mode = wl_rinfo_v1->link_mode;
 1872                 connect_cnt = wl_rinfo_v1->connect_cnt;
 1873         }
 1874 
 1875         if (wl->status.map.rf_off || bt->whql_test ||
 1876             mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
 1877             connect_cnt > BTC_TDMA_WLROLE_MAX) {
 1878                 en = false;
 1879         } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
 1880                 en = true;
 1881                 /* get p2p channel */
 1882                 for (i = 0; i < RTW89_PORT_NUM; i++) {
 1883                         r = &wl_rinfo->active_role[i];
 1884                         r1 = &wl_rinfo_v1->active_role_v1[i];
 1885 
 1886                         if (chip->chip_id == RTL8852A &&
 1887                             (r->role == RTW89_WIFI_ROLE_P2P_GO ||
 1888                              r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
 1889                                 ch = r->ch;
 1890                                 bw = r->bw;
 1891                                 break;
 1892                         } else if (chip->chip_id != RTL8852A &&
 1893                                    (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
 1894                                     r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
 1895                                 ch = r1->ch;
 1896                                 bw = r1->bw;
 1897                                 break;
 1898                         }
 1899                 }
 1900         } else {
 1901                 en = true;
 1902                 /* get 2g channel  */
 1903                 for (i = 0; i < RTW89_PORT_NUM; i++) {
 1904                         r = &wl_rinfo->active_role[i];
 1905                         r1 = &wl_rinfo_v1->active_role_v1[i];
 1906 
 1907                         if (chip->chip_id == RTL8852A &&
 1908                             r->connected && r->band == RTW89_BAND_2G) {
 1909                                 ch = r->ch;
 1910                                 bw = r->bw;
 1911                                 break;
 1912                         } else if (chip->chip_id != RTL8852A &&
 1913                                    r1->connected && r1->band == RTW89_BAND_2G) {
 1914                                 ch = r1->ch;
 1915                                 bw = r1->bw;
 1916                                 break;
 1917                         }
 1918                 }
 1919         }
 1920 
 1921         switch (bw) {
 1922         case RTW89_CHANNEL_WIDTH_20:
 1923                 bw = 20 + chip->afh_guard_ch * 2;
 1924                 break;
 1925         case RTW89_CHANNEL_WIDTH_40:
 1926                 bw = 40 + chip->afh_guard_ch * 2;
 1927                 break;
 1928         case RTW89_CHANNEL_WIDTH_5:
 1929                 bw = 5 + chip->afh_guard_ch * 2;
 1930                 break;
 1931         case RTW89_CHANNEL_WIDTH_10:
 1932                 bw = 10 + chip->afh_guard_ch * 2;
 1933                 break;
 1934         default:
 1935                 bw = 0;
 1936                 en = false; /* turn off AFH info if BW > 40 */
 1937                 break;
 1938         }
 1939 
 1940         if (wl->afh_info.en == en &&
 1941             wl->afh_info.ch == ch &&
 1942             wl->afh_info.bw == bw &&
 1943             b->profile_cnt.last == b->profile_cnt.now) {
 1944                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1945                             "[BTC], %s(): return because no change!\n",
 1946                             __func__);
 1947                 return;
 1948         }
 1949 
 1950         wl->afh_info.en = en;
 1951         wl->afh_info.ch = ch;
 1952         wl->afh_info.bw = bw;
 1953 
 1954         _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
 1955 
 1956         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 1957                     "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
 1958                     __func__, en, ch, bw);
 1959         btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
 1960 }
 1961 
 1962 static bool _check_freerun(struct rtw89_dev *rtwdev)
 1963 {
 1964         struct rtw89_btc *btc = &rtwdev->btc;
 1965         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 1966         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 1967         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 1968         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 1969         struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
 1970         struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
 1971 
 1972         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
 1973                 btc->dm.trx_para_level = 0;
 1974                 return false;
 1975         }
 1976 
 1977         /* The below is dedicated antenna case */
 1978         if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX ||
 1979             wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) {
 1980                 btc->dm.trx_para_level = 5;
 1981                 return true;
 1982         }
 1983 
 1984         if (bt_linfo->profile_cnt.now == 0) {
 1985                 btc->dm.trx_para_level = 5;
 1986                 return true;
 1987         }
 1988 
 1989         if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
 1990                 btc->dm.trx_para_level = 5;
 1991                 return true;
 1992         }
 1993 
 1994         /* TODO get isolation by BT psd */
 1995         if (btc->mdinfo.ant.isolation >= BTC_FREERUN_ANTISO_MIN) {
 1996                 btc->dm.trx_para_level = 5;
 1997                 return true;
 1998         }
 1999 
 2000         if (!wl->status.map.busy) {/* wl idle -> freerun */
 2001                 btc->dm.trx_para_level = 5;
 2002                 return true;
 2003         } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
 2004                 btc->dm.trx_para_level = 0;
 2005                 return false;
 2006         } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
 2007                 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
 2008                         btc->dm.trx_para_level = 6;
 2009                         return true;
 2010                 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
 2011                         btc->dm.trx_para_level = 7;
 2012                         return true;
 2013                 }
 2014                 btc->dm.trx_para_level = 0;
 2015                 return false;
 2016         } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
 2017                 if (bt_linfo->rssi > 28) {
 2018                         btc->dm.trx_para_level = 6;
 2019                         return true;
 2020                 }
 2021         }
 2022 
 2023         btc->dm.trx_para_level = 0;
 2024         return false;
 2025 }
 2026 
 2027 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
 2028 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
 2029 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
 2030 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
 2031 
 2032 #define _slot_set(btc, sid, dura, tbl, type) \
 2033         do { \
 2034                 typeof(sid) _sid = (sid); \
 2035                 typeof(btc) _btc = (btc); \
 2036                 _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\
 2037                 _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \
 2038                 _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \
 2039         } while (0)
 2040 
 2041 #define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura)
 2042 #define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl)
 2043 #define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type)
 2044 
 2045 struct btc_btinfo_lb2 {
 2046         u8 connect: 1;
 2047         u8 sco_busy: 1;
 2048         u8 inq_pag: 1;
 2049         u8 acl_busy: 1;
 2050         u8 hfp: 1;
 2051         u8 hid: 1;
 2052         u8 a2dp: 1;
 2053         u8 pan: 1;
 2054 };
 2055 
 2056 struct btc_btinfo_lb3 {
 2057         u8 retry: 4;
 2058         u8 cqddr: 1;
 2059         u8 inq: 1;
 2060         u8 mesh_busy: 1;
 2061         u8 pag: 1;
 2062 };
 2063 
 2064 struct btc_btinfo_hb0 {
 2065         s8 rssi;
 2066 };
 2067 
 2068 struct btc_btinfo_hb1 {
 2069         u8 ble_connect: 1;
 2070         u8 reinit: 1;
 2071         u8 relink: 1;
 2072         u8 igno_wl: 1;
 2073         u8 voice: 1;
 2074         u8 ble_scan: 1;
 2075         u8 role_sw: 1;
 2076         u8 multi_link: 1;
 2077 };
 2078 
 2079 struct btc_btinfo_hb2 {
 2080         u8 pan_active: 1;
 2081         u8 afh_update: 1;
 2082         u8 a2dp_active: 1;
 2083         u8 slave: 1;
 2084         u8 hid_slot: 2;
 2085         u8 hid_cnt: 2;
 2086 };
 2087 
 2088 struct btc_btinfo_hb3 {
 2089         u8 a2dp_bitpool: 6;
 2090         u8 tx_3m: 1;
 2091         u8 a2dp_sink: 1;
 2092 };
 2093 
 2094 union btc_btinfo {
 2095         u8 val;
 2096         struct btc_btinfo_lb2 lb2;
 2097         struct btc_btinfo_lb3 lb3;
 2098         struct btc_btinfo_hb0 hb0;
 2099         struct btc_btinfo_hb1 hb1;
 2100         struct btc_btinfo_hb2 hb2;
 2101         struct btc_btinfo_hb3 hb3;
 2102 };
 2103 
 2104 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
 2105                         enum btc_reason_and_action action)
 2106 {
 2107         const struct rtw89_chip_info *chip = rtwdev->chip;
 2108 
 2109         chip->ops->btc_set_policy(rtwdev, policy_type);
 2110         _fw_set_policy(rtwdev, policy_type, action);
 2111 }
 2112 
 2113 #define BTC_B1_MAX 250 /* unit ms */
 2114 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
 2115 {
 2116         struct rtw89_btc *btc = &rtwdev->btc;
 2117         struct rtw89_btc_dm *dm = &btc->dm;
 2118         struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
 2119         struct rtw89_btc_fbtc_slot *s = dm->slot;
 2120         u8 type;
 2121         u32 tbl_w1, tbl_b1, tbl_b4;
 2122 
 2123         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
 2124                 if (btc->cx.wl.status.map._4way)
 2125                         tbl_w1 = cxtbl[1];
 2126                 else
 2127                         tbl_w1 = cxtbl[8];
 2128                 tbl_b1 = cxtbl[3];
 2129                 tbl_b4 = cxtbl[3];
 2130         } else {
 2131                 tbl_w1 = cxtbl[16];
 2132                 tbl_b1 = cxtbl[17];
 2133                 tbl_b4 = cxtbl[17];
 2134         }
 2135 
 2136         type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
 2137         btc->bt_req_en = false;
 2138 
 2139         switch (type) {
 2140         case BTC_CXP_USERDEF0:
 2141                 *t = t_def[CXTD_OFF];
 2142                 s[CXST_OFF] = s_def[CXST_OFF];
 2143                 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
 2144                 btc->update_policy_force = true;
 2145                 break;
 2146         case BTC_CXP_OFF: /* TDMA off */
 2147                 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
 2148                 *t = t_def[CXTD_OFF];
 2149                 s[CXST_OFF] = s_def[CXST_OFF];
 2150 
 2151                 switch (policy_type) {
 2152                 case BTC_CXP_OFF_BT:
 2153                         _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
 2154                         break;
 2155                 case BTC_CXP_OFF_WL:
 2156                         _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
 2157                         break;
 2158                 case BTC_CXP_OFF_EQ0:
 2159                         _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
 2160                         break;
 2161                 case BTC_CXP_OFF_EQ1:
 2162                         _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
 2163                         break;
 2164                 case BTC_CXP_OFF_EQ2:
 2165                         _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
 2166                         break;
 2167                 case BTC_CXP_OFF_EQ3:
 2168                         _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
 2169                         break;
 2170                 case BTC_CXP_OFF_BWB0:
 2171                         _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
 2172                         break;
 2173                 case BTC_CXP_OFF_BWB1:
 2174                         _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
 2175                         break;
 2176                 }
 2177                 break;
 2178         case BTC_CXP_OFFB: /* TDMA off + beacon protect */
 2179                 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
 2180                 *t = t_def[CXTD_OFF_B2];
 2181                 s[CXST_OFF] = s_def[CXST_OFF];
 2182                 switch (policy_type) {
 2183                 case BTC_CXP_OFFB_BWB0:
 2184                         _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
 2185                         break;
 2186                 }
 2187                 break;
 2188         case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
 2189                 btc->bt_req_en = true;
 2190                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2191                 *t = t_def[CXTD_OFF_EXT];
 2192                 switch (policy_type) {
 2193                 case BTC_CXP_OFFE_DEF:
 2194                         s[CXST_E2G] = s_def[CXST_E2G];
 2195                         s[CXST_E5G] = s_def[CXST_E5G];
 2196                         s[CXST_EBT] = s_def[CXST_EBT];
 2197                         s[CXST_ENULL] = s_def[CXST_ENULL];
 2198                         break;
 2199                 case BTC_CXP_OFFE_DEF2:
 2200                         _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
 2201                         s[CXST_E5G] = s_def[CXST_E5G];
 2202                         s[CXST_EBT] = s_def[CXST_EBT];
 2203                         s[CXST_ENULL] = s_def[CXST_ENULL];
 2204                         break;
 2205                 }
 2206                 break;
 2207         case BTC_CXP_FIX: /* TDMA Fix-Slot */
 2208                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2209                 *t = t_def[CXTD_FIX];
 2210                 switch (policy_type) {
 2211                 case BTC_CXP_FIX_TD3030:
 2212                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2213                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2214                         break;
 2215                 case BTC_CXP_FIX_TD5050:
 2216                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2217                         _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
 2218                         break;
 2219                 case BTC_CXP_FIX_TD2030:
 2220                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2221                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2222                         break;
 2223                 case BTC_CXP_FIX_TD4010:
 2224                         _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
 2225                         _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
 2226                         break;
 2227                 case BTC_CXP_FIX_TD4020:
 2228                         _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX);
 2229                         _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX);
 2230                         break;
 2231                 case BTC_CXP_FIX_TD7010:
 2232                         _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
 2233                         _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
 2234                         break;
 2235                 case BTC_CXP_FIX_TD2060:
 2236                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2237                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2238                         break;
 2239                 case BTC_CXP_FIX_TD3060:
 2240                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2241                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2242                         break;
 2243                 case BTC_CXP_FIX_TD2080:
 2244                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2245                         _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
 2246                         break;
 2247                 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
 2248                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2249                                   tbl_w1, SLOT_ISO);
 2250                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2251                                   tbl_b1, SLOT_MIX);
 2252                         break;
 2253                 }
 2254                 break;
 2255         case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
 2256                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2257                 *t = t_def[CXTD_PFIX];
 2258                 if (btc->cx.wl.role_info.role_map.role.ap)
 2259                         _tdma_set_flctrl(btc, CXFLC_QOSNULL);
 2260 
 2261                 switch (policy_type) {
 2262                 case BTC_CXP_PFIX_TD3030:
 2263                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2264                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2265                         break;
 2266                 case BTC_CXP_PFIX_TD5050:
 2267                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2268                         _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
 2269                         break;
 2270                 case BTC_CXP_PFIX_TD2030:
 2271                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2272                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2273                         break;
 2274                 case BTC_CXP_PFIX_TD2060:
 2275                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2276                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2277                         break;
 2278                 case BTC_CXP_PFIX_TD3070:
 2279                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2280                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2281                         break;
 2282                 case BTC_CXP_PFIX_TD2080:
 2283                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2284                         _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
 2285                         break;
 2286                 }
 2287                 break;
 2288         case BTC_CXP_AUTO: /* TDMA Auto-Slot */
 2289                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2290                 *t = t_def[CXTD_AUTO];
 2291                 switch (policy_type) {
 2292                 case BTC_CXP_AUTO_TD50B1:
 2293                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2294                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2295                         break;
 2296                 case BTC_CXP_AUTO_TD60B1:
 2297                         _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
 2298                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2299                         break;
 2300                 case BTC_CXP_AUTO_TD20B1:
 2301                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2302                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2303                         break;
 2304                 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
 2305                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2306                                   tbl_w1, SLOT_ISO);
 2307                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2308                                   tbl_b1, SLOT_MIX);
 2309                         break;
 2310                 }
 2311                 break;
 2312         case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
 2313                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2314                 *t = t_def[CXTD_PAUTO];
 2315                 switch (policy_type) {
 2316                 case BTC_CXP_PAUTO_TD50B1:
 2317                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2318                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2319                         break;
 2320                 case BTC_CXP_PAUTO_TD60B1:
 2321                         _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
 2322                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2323                         break;
 2324                 case BTC_CXP_PAUTO_TD20B1:
 2325                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2326                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2327                         break;
 2328                 case BTC_CXP_PAUTO_TDW1B1:
 2329                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2330                                   tbl_w1, SLOT_ISO);
 2331                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2332                                   tbl_b1, SLOT_MIX);
 2333                         break;
 2334                 }
 2335                 break;
 2336         case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
 2337                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2338                 *t = t_def[CXTD_AUTO2];
 2339                 switch (policy_type) {
 2340                 case BTC_CXP_AUTO2_TD3050:
 2341                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2342                         _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
 2343                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2344                         break;
 2345                 case BTC_CXP_AUTO2_TD3070:
 2346                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2347                         _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
 2348                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2349                         break;
 2350                 case BTC_CXP_AUTO2_TD5050:
 2351                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2352                         _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
 2353                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2354                         break;
 2355                 case BTC_CXP_AUTO2_TD6060:
 2356                         _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
 2357                         _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
 2358                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2359                         break;
 2360                 case BTC_CXP_AUTO2_TD2080:
 2361                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2362                         _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
 2363                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2364                         break;
 2365                 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
 2366                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2367                                   tbl_w1, SLOT_ISO);
 2368                         _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
 2369                                   tbl_b4, SLOT_MIX);
 2370                         break;
 2371                 }
 2372                 break;
 2373         case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
 2374                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2375                 *t = t_def[CXTD_PAUTO2];
 2376                 switch (policy_type) {
 2377                 case BTC_CXP_PAUTO2_TD3050:
 2378                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2379                         _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
 2380                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2381                         break;
 2382                 case BTC_CXP_PAUTO2_TD3070:
 2383                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2384                         _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
 2385                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2386                         break;
 2387                 case BTC_CXP_PAUTO2_TD5050:
 2388                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2389                         _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
 2390                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2391                         break;
 2392                 case BTC_CXP_PAUTO2_TD6060:
 2393                         _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
 2394                         _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
 2395                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2396                         break;
 2397                 case BTC_CXP_PAUTO2_TD2080:
 2398                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2399                         _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
 2400                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2401                         break;
 2402                 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
 2403                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2404                                   tbl_w1, SLOT_ISO);
 2405                         _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
 2406                                   tbl_b4, SLOT_MIX);
 2407                         break;
 2408                 }
 2409                 break;
 2410         }
 2411 }
 2412 EXPORT_SYMBOL(rtw89_btc_set_policy);
 2413 
 2414 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
 2415 {
 2416         struct rtw89_btc *btc = &rtwdev->btc;
 2417         struct rtw89_btc_dm *dm = &btc->dm;
 2418         struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
 2419         struct rtw89_btc_fbtc_slot *s = dm->slot;
 2420         struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
 2421         struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
 2422         struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
 2423         u8 type, null_role;
 2424         u32 tbl_w1, tbl_b1, tbl_b4;
 2425 
 2426         type = FIELD_GET(BTC_CXP_MASK, policy_type);
 2427 
 2428         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
 2429                 if (btc->cx.wl.status.map._4way)
 2430                         tbl_w1 = cxtbl[1];
 2431                 else if (hid->exist && hid->type == BTC_HID_218)
 2432                         tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
 2433                 else
 2434                         tbl_w1 = cxtbl[8];
 2435 
 2436                 if (dm->leak_ap &&
 2437                     (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
 2438                         tbl_b1 = cxtbl[3];
 2439                         tbl_b4 = cxtbl[3];
 2440                 } else if (hid->exist && hid->type == BTC_HID_218) {
 2441                         tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
 2442                         tbl_b4 = cxtbl[4];
 2443                 } else {
 2444                         tbl_b1 = cxtbl[2];
 2445                         tbl_b4 = cxtbl[2];
 2446                 }
 2447         } else {
 2448                 tbl_w1 = cxtbl[16];
 2449                 tbl_b1 = cxtbl[17];
 2450                 tbl_b4 = cxtbl[17];
 2451         }
 2452 
 2453         btc->bt_req_en = false;
 2454 
 2455         switch (type) {
 2456         case BTC_CXP_USERDEF0:
 2457                 btc->update_policy_force = true;
 2458                 *t = t_def[CXTD_OFF];
 2459                 s[CXST_OFF] = s_def[CXST_OFF];
 2460                 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
 2461                 break;
 2462         case BTC_CXP_OFF: /* TDMA off */
 2463                 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
 2464                 *t = t_def[CXTD_OFF];
 2465                 s[CXST_OFF] = s_def[CXST_OFF];
 2466 
 2467                 switch (policy_type) {
 2468                 case BTC_CXP_OFF_BT:
 2469                         _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
 2470                         break;
 2471                 case BTC_CXP_OFF_WL:
 2472                         _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
 2473                         break;
 2474                 case BTC_CXP_OFF_EQ0:
 2475                         _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
 2476                         break;
 2477                 case BTC_CXP_OFF_EQ1:
 2478                         _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
 2479                         break;
 2480                 case BTC_CXP_OFF_EQ2:
 2481                         _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
 2482                         break;
 2483                 case BTC_CXP_OFF_EQ3:
 2484                         _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
 2485                         break;
 2486                 case BTC_CXP_OFF_BWB0:
 2487                         _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
 2488                         break;
 2489                 case BTC_CXP_OFF_BWB1:
 2490                         _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
 2491                         break;
 2492                 case BTC_CXP_OFF_BWB2:
 2493                         _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
 2494                         break;
 2495                 default:
 2496                         break;
 2497                 }
 2498                 break;
 2499         case BTC_CXP_OFFB: /* TDMA off + beacon protect */
 2500                 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
 2501                 *t = t_def[CXTD_OFF_B2];
 2502                 s[CXST_OFF] = s_def[CXST_OFF];
 2503 
 2504                 switch (policy_type) {
 2505                 case BTC_CXP_OFFB_BWB0:
 2506                         _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
 2507                         break;
 2508                 default:
 2509                         break;
 2510                 }
 2511                 break;
 2512         case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
 2513                 btc->bt_req_en = true;
 2514                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2515                 *t = t_def[CXTD_OFF_EXT];
 2516 
 2517                 /* To avoid wl-s0 tx break by hid/hfp tx */
 2518                 if (hid->exist || hfp->exist)
 2519                         tbl_w1 = cxtbl[16];
 2520 
 2521                 switch (policy_type) {
 2522                 case BTC_CXP_OFFE_DEF:
 2523                         s[CXST_E2G] = s_def[CXST_E2G];
 2524                         s[CXST_E5G] = s_def[CXST_E5G];
 2525                         s[CXST_EBT] = s_def[CXST_EBT];
 2526                         s[CXST_ENULL] = s_def[CXST_ENULL];
 2527                         break;
 2528                 case BTC_CXP_OFFE_DEF2:
 2529                         _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
 2530                         s[CXST_E5G] = s_def[CXST_E5G];
 2531                         s[CXST_EBT] = s_def[CXST_EBT];
 2532                         s[CXST_ENULL] = s_def[CXST_ENULL];
 2533                         break;
 2534                 default:
 2535                         break;
 2536                 }
 2537                 break;
 2538         case BTC_CXP_FIX: /* TDMA Fix-Slot */
 2539                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2540                 *t = t_def[CXTD_FIX];
 2541 
 2542                 switch (policy_type) {
 2543                 case BTC_CXP_FIX_TD3030:
 2544                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2545                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2546                         break;
 2547                 case BTC_CXP_FIX_TD5050:
 2548                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2549                         _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
 2550                         break;
 2551                 case BTC_CXP_FIX_TD2030:
 2552                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2553                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2554                         break;
 2555                 case BTC_CXP_FIX_TD4010:
 2556                         _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
 2557                         _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
 2558                         break;
 2559                 case BTC_CXP_FIX_TD4010ISO:
 2560                         _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
 2561                         _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
 2562                         break;
 2563                 case BTC_CXP_FIX_TD7010:
 2564                         _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
 2565                         _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
 2566                         break;
 2567                 case BTC_CXP_FIX_TD2060:
 2568                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2569                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2570                         break;
 2571                 case BTC_CXP_FIX_TD3060:
 2572                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2573                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2574                         break;
 2575                 case BTC_CXP_FIX_TD2080:
 2576                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2577                         _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
 2578                         break;
 2579                 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
 2580                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2581                                   tbl_w1, SLOT_ISO);
 2582                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2583                                   tbl_b1, SLOT_MIX);
 2584                         break;
 2585                 default:
 2586                         break;
 2587                 }
 2588                 break;
 2589         case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
 2590                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2591                 *t = t_def[CXTD_PFIX];
 2592 
 2593                 switch (policy_type) {
 2594                 case BTC_CXP_PFIX_TD3030:
 2595                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2596                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2597                         break;
 2598                 case BTC_CXP_PFIX_TD5050:
 2599                         _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
 2600                         _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
 2601                         break;
 2602                 case BTC_CXP_PFIX_TD2030:
 2603                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2604                         _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
 2605                         break;
 2606                 case BTC_CXP_PFIX_TD2060:
 2607                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2608                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2609                         break;
 2610                 case BTC_CXP_PFIX_TD3070:
 2611                         _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
 2612                         _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
 2613                         break;
 2614                 case BTC_CXP_PFIX_TD2080:
 2615                         _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
 2616                         _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
 2617                         break;
 2618                 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
 2619                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2620                                   tbl_w1, SLOT_ISO);
 2621                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2622                                   tbl_b1, SLOT_MIX);
 2623                         break;
 2624                 default:
 2625                         break;
 2626                 }
 2627                 break;
 2628         case BTC_CXP_AUTO: /* TDMA Auto-Slot */
 2629                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2630                 *t = t_def[CXTD_AUTO];
 2631 
 2632                 switch (policy_type) {
 2633                 case BTC_CXP_AUTO_TD50B1:
 2634                         _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
 2635                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2636                         break;
 2637                 case BTC_CXP_AUTO_TD60B1:
 2638                         _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
 2639                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2640                         break;
 2641                 case BTC_CXP_AUTO_TD20B1:
 2642                         _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
 2643                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2644                         break;
 2645                 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
 2646                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2647                                   tbl_w1, SLOT_ISO);
 2648                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2649                                   tbl_b1, SLOT_MIX);
 2650                         break;
 2651                 default:
 2652                         break;
 2653                 }
 2654                 break;
 2655         case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
 2656                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2657                 *t = t_def[CXTD_PAUTO];
 2658 
 2659                 switch (policy_type) {
 2660                 case BTC_CXP_PAUTO_TD50B1:
 2661                         _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
 2662                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2663                         break;
 2664                 case BTC_CXP_PAUTO_TD60B1:
 2665                         _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
 2666                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2667                         break;
 2668                 case BTC_CXP_PAUTO_TD20B1:
 2669                         _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
 2670                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2671                         break;
 2672                 case BTC_CXP_PAUTO_TDW1B1:
 2673                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2674                                   tbl_w1, SLOT_ISO);
 2675                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2676                                   tbl_b1, SLOT_MIX);
 2677                         break;
 2678                 default:
 2679                         break;
 2680                 }
 2681                 break;
 2682         case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
 2683                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2684                 *t = t_def[CXTD_AUTO2];
 2685 
 2686                 switch (policy_type) {
 2687                 case BTC_CXP_AUTO2_TD3050:
 2688                         _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
 2689                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2690                         _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
 2691                         break;
 2692                 case BTC_CXP_AUTO2_TD3070:
 2693                         _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
 2694                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2695                         _slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
 2696                         break;
 2697                 case BTC_CXP_AUTO2_TD5050:
 2698                         _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
 2699                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2700                         _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
 2701                         break;
 2702                 case BTC_CXP_AUTO2_TD6060:
 2703                         _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
 2704                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2705                         _slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
 2706                         break;
 2707                 case BTC_CXP_AUTO2_TD2080:
 2708                         _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
 2709                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2710                         _slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
 2711                         break;
 2712                 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
 2713                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2714                                   tbl_w1, SLOT_ISO);
 2715                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2716                                   tbl_b1, SLOT_MIX);
 2717                         _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
 2718                                   tbl_b4, SLOT_MIX);
 2719                         break;
 2720                 default:
 2721                         break;
 2722                 }
 2723                 break;
 2724         case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
 2725                 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
 2726                 *t = t_def[CXTD_PAUTO2];
 2727 
 2728                 switch (policy_type) {
 2729                 case BTC_CXP_PAUTO2_TD3050:
 2730                         _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
 2731                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2732                         _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
 2733                         break;
 2734                 case BTC_CXP_PAUTO2_TD3070:
 2735                         _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
 2736                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2737                         _slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
 2738                         break;
 2739                 case BTC_CXP_PAUTO2_TD5050:
 2740                         _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
 2741                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2742                         _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
 2743                         break;
 2744                 case BTC_CXP_PAUTO2_TD6060:
 2745                         _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
 2746                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2747                         _slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
 2748                         break;
 2749                 case BTC_CXP_PAUTO2_TD2080:
 2750                         _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
 2751                         _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
 2752                         _slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
 2753                         break;
 2754                 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
 2755                         _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
 2756                                   tbl_w1, SLOT_ISO);
 2757                         _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
 2758                                   tbl_b1, SLOT_MIX);
 2759                         _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
 2760                                   tbl_b4, SLOT_MIX);
 2761                         break;
 2762                 default:
 2763                         break;
 2764                 }
 2765                 break;
 2766         }
 2767 
 2768         if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
 2769                 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
 2770                             FIELD_PREP(0xf0, dm->wl_scc.null_role2);
 2771                 _tdma_set_flctrl_role(btc, null_role);
 2772         }
 2773 
 2774         /* enter leak_slot after each null-1 */
 2775         if (dm->leak_ap && dm->tdma.leak_n > 1)
 2776                 _tdma_set_lek(btc, 1);
 2777 
 2778         if (dm->tdma_instant_excute) {
 2779                 btc->dm.tdma.option_ctrl |= BIT(0);
 2780                 btc->update_policy_force = true;
 2781         }
 2782 }
 2783 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
 2784 
 2785 static void _set_gnt_bt(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
 2786 {
 2787         struct rtw89_btc *btc = &rtwdev->btc;
 2788         struct rtw89_btc_dm *dm = &btc->dm;
 2789         struct rtw89_mac_ax_gnt *g = dm->gnt.band;
 2790         u8 i;
 2791 
 2792         if (phy_map > BTC_PHY_ALL)
 2793                 return;
 2794 
 2795         for (i = 0; i < RTW89_PHY_MAX; i++) {
 2796                 if (!(phy_map & BIT(i)))
 2797                         continue;
 2798 
 2799                 switch (state) {
 2800                 case BTC_GNT_HW:
 2801                         g[i].gnt_bt_sw_en = 0;
 2802                         g[i].gnt_bt = 0;
 2803                         break;
 2804                 case BTC_GNT_SW_LO:
 2805                         g[i].gnt_bt_sw_en = 1;
 2806                         g[i].gnt_bt = 0;
 2807                         break;
 2808                 case BTC_GNT_SW_HI:
 2809                         g[i].gnt_bt_sw_en = 1;
 2810                         g[i].gnt_bt = 1;
 2811                         break;
 2812                 }
 2813         }
 2814 
 2815         rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
 2816 }
 2817 
 2818 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
 2819                          u8 tx_val, u8 rx_val)
 2820 {
 2821         struct rtw89_mac_ax_plt plt;
 2822 
 2823         plt.band = RTW89_MAC_0;
 2824         plt.tx = tx_val;
 2825         plt.rx = rx_val;
 2826 
 2827         if (phy_map & BTC_PHY_0)
 2828                 rtw89_mac_cfg_plt(rtwdev, &plt);
 2829 
 2830         if (!rtwdev->dbcc_en)
 2831                 return;
 2832 
 2833         plt.band = RTW89_MAC_1;
 2834         if (phy_map & BTC_PHY_1)
 2835                 rtw89_mac_cfg_plt(rtwdev, &plt);
 2836 }
 2837 
 2838 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
 2839                      u8 phy_map, u8 type)
 2840 {
 2841         struct rtw89_btc *btc = &rtwdev->btc;
 2842         struct rtw89_btc_dm *dm = &btc->dm;
 2843         struct rtw89_btc_cx *cx = &btc->cx;
 2844         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 2845         struct rtw89_btc_bt_info *bt = &cx->bt;
 2846         struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
 2847         u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
 2848         u32 ant_path_type;
 2849 
 2850         ant_path_type = ((phy_map << 8) + type);
 2851 
 2852         if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
 2853             btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
 2854             btc->dm.run_reason == BTC_RSN_CMD_SET_COEX)
 2855                 force_exec = FC_EXEC;
 2856 
 2857         if (!force_exec && ant_path_type == dm->set_ant_path) {
 2858                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 2859                             "[BTC], %s(): return by no change!!\n",
 2860                              __func__);
 2861                 return;
 2862         } else if (bt->rfk_info.map.run) {
 2863                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 2864                             "[BTC], %s(): return by bt rfk!!\n", __func__);
 2865                 return;
 2866         } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
 2867                    wl->rfk_info.state != BTC_WRFK_STOP) {
 2868                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 2869                             "[BTC], %s(): return by wl rfk!!\n", __func__);
 2870                 return;
 2871         }
 2872 
 2873         dm->set_ant_path = ant_path_type;
 2874 
 2875         rtw89_debug(rtwdev,
 2876                     RTW89_DBG_BTC,
 2877                     "[BTC], %s(): path=0x%x, set_type=0x%x\n",
 2878                     __func__, phy_map, dm->set_ant_path & 0xff);
 2879 
 2880         switch (type) {
 2881         case BTC_ANT_WPOWERON:
 2882                 rtw89_chip_cfg_ctrl_path(rtwdev, false);
 2883                 break;
 2884         case BTC_ANT_WINIT:
 2885                 if (bt->enable.now) {
 2886                         _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
 2887                         _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
 2888                 } else {
 2889                         _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
 2890                         _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
 2891                 }
 2892                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2893                 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
 2894                 break;
 2895         case BTC_ANT_WONLY:
 2896                 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
 2897                 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
 2898                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2899                 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
 2900                 break;
 2901         case BTC_ANT_WOFF:
 2902                 rtw89_chip_cfg_ctrl_path(rtwdev, false);
 2903                 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
 2904                 break;
 2905         case BTC_ANT_W2G:
 2906                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2907                 if (rtwdev->dbcc_en) {
 2908                         for (i = 0; i < RTW89_PHY_MAX; i++) {
 2909                                 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
 2910 
 2911                                 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
 2912                                 _set_gnt_wl(rtwdev, BIT(i), gnt_wl_ctrl);
 2913 
 2914                                 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
 2915                                 /* BT should control by GNT_BT if WL_2G at S0 */
 2916                                 if (i == 1 &&
 2917                                     wl_dinfo->real_band[0] == RTW89_BAND_2G &&
 2918                                     wl_dinfo->real_band[1] == RTW89_BAND_5G)
 2919                                         gnt_bt_ctrl = BTC_GNT_HW;
 2920                                 _set_gnt_bt(rtwdev, BIT(i), gnt_bt_ctrl);
 2921 
 2922                                 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
 2923                                 _set_bt_plut(rtwdev, BIT(i),
 2924                                              plt_ctrl, plt_ctrl);
 2925                         }
 2926                 } else {
 2927                         _set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
 2928                         _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
 2929                         _set_bt_plut(rtwdev, BTC_PHY_ALL,
 2930                                      BTC_PLT_BT, BTC_PLT_BT);
 2931                 }
 2932                 break;
 2933         case BTC_ANT_W5G:
 2934                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2935                 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
 2936                 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
 2937                 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
 2938                 break;
 2939         case BTC_ANT_W25G:
 2940                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2941                 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
 2942                 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
 2943                 _set_bt_plut(rtwdev, BTC_PHY_ALL,
 2944                              BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
 2945                 break;
 2946         case BTC_ANT_FREERUN:
 2947                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2948                 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
 2949                 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
 2950                 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
 2951                 break;
 2952         case BTC_ANT_WRFK:
 2953                 rtw89_chip_cfg_ctrl_path(rtwdev, true);
 2954                 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
 2955                 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
 2956                 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
 2957                 break;
 2958         case BTC_ANT_BRFK:
 2959                 rtw89_chip_cfg_ctrl_path(rtwdev, false);
 2960                 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
 2961                 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
 2962                 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
 2963                 break;
 2964         default:
 2965                 break;
 2966         }
 2967 }
 2968 
 2969 static void _action_wl_only(struct rtw89_dev *rtwdev)
 2970 {
 2971         _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
 2972         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
 2973 }
 2974 
 2975 static void _action_wl_init(struct rtw89_dev *rtwdev)
 2976 {
 2977         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 2978 
 2979         _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
 2980         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
 2981 }
 2982 
 2983 static void _action_wl_off(struct rtw89_dev *rtwdev)
 2984 {
 2985         struct rtw89_btc *btc = &rtwdev->btc;
 2986         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 2987 
 2988         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 2989 
 2990         if (wl->status.map.rf_off || btc->dm.bt_only)
 2991                 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
 2992 
 2993         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
 2994 }
 2995 
 2996 static void _action_freerun(struct rtw89_dev *rtwdev)
 2997 {
 2998         struct rtw89_btc *btc = &rtwdev->btc;
 2999 
 3000         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 3001 
 3002         _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
 3003         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
 3004 
 3005         btc->dm.freerun = true;
 3006 }
 3007 
 3008 static void _action_bt_whql(struct rtw89_dev *rtwdev)
 3009 {
 3010         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 3011 
 3012         _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3013         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
 3014 }
 3015 
 3016 static void _action_bt_off(struct rtw89_dev *rtwdev)
 3017 {
 3018         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 3019 
 3020         _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
 3021         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
 3022 }
 3023 
 3024 static void _action_bt_idle(struct rtw89_dev *rtwdev)
 3025 {
 3026         struct rtw89_btc *btc = &rtwdev->btc;
 3027         struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
 3028 
 3029         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3030 
 3031         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
 3032                 switch (btc->cx.state_map) {
 3033                 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
 3034                         if (b->profile_cnt.now > 0)
 3035                                 _set_policy(rtwdev, BTC_CXP_FIX_TD4010,
 3036                                             BTC_ACT_BT_IDLE);
 3037                         else
 3038                                 _set_policy(rtwdev, BTC_CXP_FIX_TD4020,
 3039                                             BTC_ACT_BT_IDLE);
 3040                         break;
 3041                 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
 3042                         _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
 3043                                     BTC_ACT_BT_IDLE);
 3044                         break;
 3045                 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
 3046                         if (b->profile_cnt.now > 0)
 3047                                 _set_policy(rtwdev, BTC_CXP_FIX_TD4010,
 3048                                             BTC_ACT_BT_IDLE);
 3049                         else
 3050                                 _set_policy(rtwdev, BTC_CXP_FIX_TD4020,
 3051                                             BTC_ACT_BT_IDLE);
 3052                         break;
 3053                 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
 3054                         _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
 3055                                     BTC_ACT_BT_IDLE);
 3056                         break;
 3057                 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
 3058                         _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
 3059                                     BTC_ACT_BT_IDLE);
 3060                         break;
 3061                 case BTC_WIDLE:  /* wl-idle + bt-idle */
 3062                         _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
 3063                         break;
 3064                 }
 3065         } else { /* dedicated-antenna */
 3066                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
 3067         }
 3068 }
 3069 
 3070 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
 3071 {
 3072         struct rtw89_btc *btc = &rtwdev->btc;
 3073 
 3074         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3075 
 3076         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
 3077                 if (btc->cx.wl.status.map._4way)
 3078                         _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
 3079                 else
 3080                         _set_policy(rtwdev, BTC_CXP_OFF_BWB0, BTC_ACT_BT_HFP);
 3081         } else {
 3082                 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
 3083         }
 3084 }
 3085 
 3086 static void _action_bt_hid(struct rtw89_dev *rtwdev)
 3087 {
 3088         struct rtw89_btc *btc = &rtwdev->btc;
 3089 
 3090         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3091 
 3092         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) /* shared-antenna */
 3093                 if (btc->cx.wl.status.map._4way)
 3094                         _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HID);
 3095                 else
 3096                         _set_policy(rtwdev, BTC_CXP_OFF_BWB0, BTC_ACT_BT_HID);
 3097         else /* dedicated-antenna */
 3098                 _set_policy(rtwdev, BTC_CXP_OFF_EQ3, BTC_ACT_BT_HID);
 3099 }
 3100 
 3101 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
 3102 {
 3103         struct rtw89_btc *btc = &rtwdev->btc;
 3104         struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
 3105         struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
 3106         struct rtw89_btc_dm *dm = &btc->dm;
 3107 
 3108         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3109 
 3110         switch (btc->cx.state_map) {
 3111         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
 3112                 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
 3113                         dm->slot_dur[CXST_W1] = 40;
 3114                         dm->slot_dur[CXST_B1] = 200;
 3115                         _set_policy(rtwdev,
 3116                                     BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
 3117                 } else {
 3118                         _set_policy(rtwdev,
 3119                                     BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
 3120                 }
 3121                 break;
 3122         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
 3123                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
 3124                 break;
 3125         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
 3126                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
 3127                 break;
 3128         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
 3129         case BTC_WLINKING: /* wl-connecting + bt-A2DP */
 3130                 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
 3131                         dm->slot_dur[CXST_W1] = 40;
 3132                         dm->slot_dur[CXST_B1] = 200;
 3133                         _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
 3134                                     BTC_ACT_BT_A2DP);
 3135                 } else {
 3136                         _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
 3137                                     BTC_ACT_BT_A2DP);
 3138                 }
 3139                 break;
 3140         case BTC_WIDLE:  /* wl-idle + bt-A2DP */
 3141                 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
 3142                 break;
 3143         }
 3144 }
 3145 
 3146 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
 3147 {
 3148         struct rtw89_btc *btc = &rtwdev->btc;
 3149 
 3150         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3151 
 3152         switch (btc->cx.state_map) {
 3153         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
 3154                 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
 3155                 break;
 3156         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
 3157                 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
 3158                 break;
 3159         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
 3160                 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
 3161                 break;
 3162         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
 3163                 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
 3164                 break;
 3165         case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
 3166                 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
 3167                 break;
 3168         case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
 3169                 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
 3170                 break;
 3171         }
 3172 }
 3173 
 3174 static void _action_bt_pan(struct rtw89_dev *rtwdev)
 3175 {
 3176         struct rtw89_btc *btc = &rtwdev->btc;
 3177 
 3178         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3179 
 3180         switch (btc->cx.state_map) {
 3181         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
 3182                 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
 3183                 break;
 3184         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
 3185                 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
 3186                 break;
 3187         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
 3188                 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
 3189                 break;
 3190         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
 3191                 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
 3192                 break;
 3193         case BTC_WLINKING: /* wl-connecting + bt-PAN */
 3194                 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, BTC_ACT_BT_PAN);
 3195                 break;
 3196         case BTC_WIDLE: /* wl-idle + bt-pan */
 3197                 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
 3198                 break;
 3199         }
 3200 }
 3201 
 3202 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
 3203 {
 3204         struct rtw89_btc *btc = &rtwdev->btc;
 3205         struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
 3206         struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
 3207         struct rtw89_btc_dm *dm = &btc->dm;
 3208 
 3209         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3210 
 3211         switch (btc->cx.state_map) {
 3212         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
 3213         case BTC_WIDLE:  /* wl-idle + bt-A2DP */
 3214                 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
 3215                         dm->slot_dur[CXST_W1] = 40;
 3216                         dm->slot_dur[CXST_B1] = 200;
 3217                         _set_policy(rtwdev,
 3218                                     BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
 3219                 } else {
 3220                         _set_policy(rtwdev,
 3221                                     BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
 3222                 }
 3223                 break;
 3224         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
 3225                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
 3226                 break;
 3227 
 3228         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
 3229                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
 3230                 break;
 3231         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
 3232         case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
 3233                 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
 3234                         dm->slot_dur[CXST_W1] = 40;
 3235                         dm->slot_dur[CXST_B1] = 200;
 3236                         _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
 3237                                     BTC_ACT_BT_A2DP_HID);
 3238                 } else {
 3239                         _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
 3240                                     BTC_ACT_BT_A2DP_HID);
 3241                 }
 3242                 break;
 3243         }
 3244 }
 3245 
 3246 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
 3247 {
 3248         struct rtw89_btc *btc = &rtwdev->btc;
 3249 
 3250         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3251 
 3252         switch (btc->cx.state_map) {
 3253         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
 3254                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
 3255                 break;
 3256         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
 3257                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
 3258                 break;
 3259         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
 3260                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
 3261                 break;
 3262         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
 3263                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
 3264                 break;
 3265         case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
 3266                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
 3267                 break;
 3268         case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN */
 3269                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
 3270                 break;
 3271         }
 3272 }
 3273 
 3274 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
 3275 {
 3276         struct rtw89_btc *btc = &rtwdev->btc;
 3277 
 3278         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3279 
 3280         switch (btc->cx.state_map) {
 3281         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
 3282                 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
 3283                 break;
 3284         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
 3285                 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
 3286                 break;
 3287         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
 3288                 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
 3289                 break;
 3290         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
 3291                 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
 3292                 break;
 3293         case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
 3294                 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
 3295                 break;
 3296         case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
 3297                 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
 3298                 break;
 3299         }
 3300 }
 3301 
 3302 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
 3303 {
 3304         struct rtw89_btc *btc = &rtwdev->btc;
 3305 
 3306         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3307 
 3308         switch (btc->cx.state_map) {
 3309         case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
 3310                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
 3311                             BTC_ACT_BT_A2DP_PAN_HID);
 3312                 break;
 3313         case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
 3314                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
 3315                             BTC_ACT_BT_A2DP_PAN_HID);
 3316                 break;
 3317         case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
 3318                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
 3319                             BTC_ACT_BT_A2DP_PAN_HID);
 3320                 break;
 3321         case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
 3322         case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
 3323                 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
 3324                             BTC_ACT_BT_A2DP_PAN_HID);
 3325                 break;
 3326         case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN+HID */
 3327                 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
 3328                             BTC_ACT_BT_A2DP_PAN_HID);
 3329                 break;
 3330         }
 3331 }
 3332 
 3333 static void _action_wl_5g(struct rtw89_dev *rtwdev)
 3334 {
 3335         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
 3336         _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
 3337 }
 3338 
 3339 static void _action_wl_other(struct rtw89_dev *rtwdev)
 3340 {
 3341         struct rtw89_btc *btc = &rtwdev->btc;
 3342 
 3343         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3344 
 3345         if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
 3346                 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
 3347         else
 3348                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
 3349 }
 3350 
 3351 static void _action_wl_nc(struct rtw89_dev *rtwdev)
 3352 {
 3353         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3354         _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
 3355 }
 3356 
 3357 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
 3358 {
 3359         struct rtw89_btc *btc = &rtwdev->btc;
 3360         struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
 3361 
 3362         if (rfk.state != BTC_WRFK_START)
 3363                 return;
 3364 
 3365         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
 3366                     __func__, rfk.band);
 3367 
 3368         _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
 3369         _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
 3370 }
 3371 
 3372 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
 3373 {
 3374         const struct rtw89_chip_info *chip = rtwdev->chip;
 3375         struct rtw89_btc *btc = &rtwdev->btc;
 3376         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 3377         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 3378         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 3379         struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
 3380         bool is_btg;
 3381         u8 mode;
 3382 
 3383         if (btc->ctrl.manual)
 3384                 return;
 3385 
 3386         if (chip->chip_id == RTL8852A)
 3387                 mode = wl_rinfo->link_mode;
 3388         else
 3389                 mode = wl_rinfo_v1->link_mode;
 3390 
 3391         /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
 3392         if (mode == BTC_WLINK_5G) /* always 0 if 5G */
 3393                 is_btg = false;
 3394         else if (mode == BTC_WLINK_25G_DBCC &&
 3395                  wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
 3396                 is_btg = false;
 3397         else
 3398                 is_btg = true;
 3399 
 3400         if (btc->dm.run_reason != BTC_RSN_NTFY_INIT &&
 3401             is_btg == btc->dm.wl_btg_rx)
 3402                 return;
 3403 
 3404         btc->dm.wl_btg_rx = is_btg;
 3405 
 3406         if (mode == BTC_WLINK_25G_MCC)
 3407                 return;
 3408 
 3409         rtw89_ctrl_btg(rtwdev, is_btg);
 3410 }
 3411 
 3412 struct rtw89_txtime_data {
 3413         struct rtw89_dev *rtwdev;
 3414         int type;
 3415         u32 tx_time;
 3416         u8 tx_retry;
 3417         u16 enable;
 3418         bool reenable;
 3419 };
 3420 
 3421 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
 3422 {
 3423         struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
 3424         struct rtw89_txtime_data *iter_data =
 3425                                 (struct rtw89_txtime_data *)data;
 3426         struct rtw89_dev *rtwdev = iter_data->rtwdev;
 3427         struct rtw89_vif *rtwvif = rtwsta->rtwvif;
 3428         struct rtw89_btc *btc = &rtwdev->btc;
 3429         struct rtw89_btc_cx *cx = &btc->cx;
 3430         struct rtw89_btc_wl_info *wl = &cx->wl;
 3431         struct rtw89_btc_wl_link_info *plink = NULL;
 3432         u8 port = rtwvif->port;
 3433         u32 tx_time = iter_data->tx_time;
 3434         u8 tx_retry = iter_data->tx_retry;
 3435         u16 enable = iter_data->enable;
 3436         bool reenable = iter_data->reenable;
 3437 
 3438         plink = &wl->link_info[port];
 3439 
 3440         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 3441                     "[BTC], %s(): port = %d\n", __func__, port);
 3442 
 3443         if (!plink->connected) {
 3444                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 3445                             "[BTC], %s(): connected = %d\n",
 3446                             __func__, plink->connected);
 3447                 return;
 3448         }
 3449 
 3450         /* backup the original tx time before tx-limit on */
 3451         if (reenable) {
 3452                 rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time);
 3453                 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry);
 3454                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 3455                             "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
 3456                             __func__, plink->tx_time, plink->tx_retry);
 3457         }
 3458 
 3459         /* restore the original tx time if no tx-limit */
 3460         if (!enable) {
 3461                 rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time);
 3462                 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true,
 3463                                              plink->tx_retry);
 3464                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 3465                             "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
 3466                             __func__, plink->tx_time, plink->tx_retry);
 3467 
 3468         } else {
 3469                 rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time);
 3470                 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry);
 3471                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 3472                             "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
 3473                             __func__, tx_time, tx_retry);
 3474         }
 3475 }
 3476 
 3477 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
 3478 {
 3479         const struct rtw89_chip_info *chip = rtwdev->chip;
 3480         struct rtw89_btc *btc = &rtwdev->btc;
 3481         struct rtw89_btc_cx *cx = &btc->cx;
 3482         struct rtw89_btc_dm *dm = &btc->dm;
 3483         struct rtw89_btc_wl_info *wl = &cx->wl;
 3484         struct rtw89_btc_bt_info *bt = &cx->bt;
 3485         struct rtw89_btc_bt_link_info *b = &bt->link_info;
 3486         struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
 3487         struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
 3488         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 3489         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 3490         struct rtw89_txtime_data data = {.rtwdev = rtwdev};
 3491         u8 mode;
 3492         u8 tx_retry;
 3493         u32 tx_time;
 3494         u16 enable;
 3495         bool reenable = false;
 3496 
 3497         if (btc->ctrl.manual)
 3498                 return;
 3499 
 3500         if (chip->chip_id == RTL8852A)
 3501                 mode = wl_rinfo->link_mode;
 3502         else
 3503                 mode = wl_rinfo_v1->link_mode;
 3504 
 3505         if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 ||
 3506             mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
 3507                 enable = 0;
 3508                 tx_time = BTC_MAX_TX_TIME_DEF;
 3509                 tx_retry = BTC_MAX_TX_RETRY_DEF;
 3510         } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
 3511                 enable = 1;
 3512                 tx_time = BTC_MAX_TX_TIME_L2;
 3513                 tx_retry = BTC_MAX_TX_RETRY_L1;
 3514         } else if (hfp->exist || hid->exist) {
 3515                 enable = 1;
 3516                 tx_time = BTC_MAX_TX_TIME_L3;
 3517                 tx_retry = BTC_MAX_TX_RETRY_L1;
 3518         } else {
 3519                 enable = 0;
 3520                 tx_time = BTC_MAX_TX_TIME_DEF;
 3521                 tx_retry = BTC_MAX_TX_RETRY_DEF;
 3522         }
 3523 
 3524         if (dm->wl_tx_limit.enable == enable &&
 3525             dm->wl_tx_limit.tx_time == tx_time &&
 3526             dm->wl_tx_limit.tx_retry == tx_retry)
 3527                 return;
 3528 
 3529         if (!dm->wl_tx_limit.enable && enable)
 3530                 reenable = true;
 3531 
 3532         dm->wl_tx_limit.enable = enable;
 3533         dm->wl_tx_limit.tx_time = tx_time;
 3534         dm->wl_tx_limit.tx_retry = tx_retry;
 3535 
 3536         data.enable = enable;
 3537         data.tx_time = tx_time;
 3538         data.tx_retry = tx_retry;
 3539         data.reenable = reenable;
 3540 
 3541         ieee80211_iterate_stations_atomic(rtwdev->hw,
 3542                                           rtw89_tx_time_iter,
 3543                                           &data);
 3544 }
 3545 
 3546 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
 3547 {
 3548         const struct rtw89_chip_info *chip = rtwdev->chip;
 3549         struct rtw89_btc *btc = &rtwdev->btc;
 3550         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 3551         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 3552         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 3553         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 3554         bool bt_hi_lna_rx = false;
 3555         u8 mode;
 3556 
 3557         if (chip->chip_id == RTL8852A)
 3558                 mode = wl_rinfo->link_mode;
 3559         else
 3560                 mode = wl_rinfo_v1->link_mode;
 3561 
 3562         if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
 3563                 bt_hi_lna_rx = true;
 3564 
 3565         if (bt_hi_lna_rx == bt->hi_lna_rx)
 3566                 return;
 3567 
 3568         _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
 3569 }
 3570 
 3571 /* TODO add these functions */
 3572 static void _action_common(struct rtw89_dev *rtwdev)
 3573 {
 3574         _set_btg_ctrl(rtwdev);
 3575         _set_wl_tx_limit(rtwdev);
 3576         _set_bt_afh_info(rtwdev);
 3577         _set_bt_rx_agc(rtwdev);
 3578         _set_rf_trx_para(rtwdev);
 3579 }
 3580 
 3581 static void _action_by_bt(struct rtw89_dev *rtwdev)
 3582 {
 3583         struct rtw89_btc *btc = &rtwdev->btc;
 3584         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 3585         struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
 3586         struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
 3587         struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
 3588         struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
 3589         u8 profile_map = 0;
 3590 
 3591         if (bt_linfo->hfp_desc.exist)
 3592                 profile_map |= BTC_BT_HFP;
 3593 
 3594         if (bt_linfo->hid_desc.exist)
 3595                 profile_map |= BTC_BT_HID;
 3596 
 3597         if (bt_linfo->a2dp_desc.exist)
 3598                 profile_map |= BTC_BT_A2DP;
 3599 
 3600         if (bt_linfo->pan_desc.exist)
 3601                 profile_map |= BTC_BT_PAN;
 3602 
 3603         switch (profile_map) {
 3604         case BTC_BT_NOPROFILE:
 3605                 if (_check_freerun(rtwdev))
 3606                         _action_freerun(rtwdev);
 3607                 else if (a2dp.active || pan.active)
 3608                         _action_bt_pan(rtwdev);
 3609                 else
 3610                         _action_bt_idle(rtwdev);
 3611                 break;
 3612         case BTC_BT_HFP:
 3613                 if (_check_freerun(rtwdev))
 3614                         _action_freerun(rtwdev);
 3615                 else
 3616                         _action_bt_hfp(rtwdev);
 3617                 break;
 3618         case BTC_BT_HFP | BTC_BT_HID:
 3619         case BTC_BT_HID:
 3620                 if (_check_freerun(rtwdev))
 3621                         _action_freerun(rtwdev);
 3622                 else
 3623                         _action_bt_hid(rtwdev);
 3624                 break;
 3625         case BTC_BT_A2DP:
 3626                 if (_check_freerun(rtwdev))
 3627                         _action_freerun(rtwdev);
 3628                 else if (a2dp.sink)
 3629                         _action_bt_a2dpsink(rtwdev);
 3630                 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
 3631                         _action_bt_a2dp_pan(rtwdev);
 3632                 else
 3633                         _action_bt_a2dp(rtwdev);
 3634                 break;
 3635         case BTC_BT_PAN:
 3636                 _action_bt_pan(rtwdev);
 3637                 break;
 3638         case BTC_BT_A2DP | BTC_BT_HFP:
 3639         case BTC_BT_A2DP | BTC_BT_HID:
 3640         case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
 3641                 if (_check_freerun(rtwdev))
 3642                         _action_freerun(rtwdev);
 3643                 else
 3644                         _action_bt_a2dp_hid(rtwdev);
 3645                 break;
 3646         case BTC_BT_A2DP | BTC_BT_PAN:
 3647                 _action_bt_a2dp_pan(rtwdev);
 3648                 break;
 3649         case BTC_BT_PAN | BTC_BT_HFP:
 3650         case BTC_BT_PAN | BTC_BT_HID:
 3651         case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
 3652                 _action_bt_pan_hid(rtwdev);
 3653                 break;
 3654         case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
 3655         case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
 3656         default:
 3657                 _action_bt_a2dp_pan_hid(rtwdev);
 3658                 break;
 3659         }
 3660 }
 3661 
 3662 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
 3663 {
 3664         _action_by_bt(rtwdev);
 3665 }
 3666 
 3667 static void _action_wl_scan(struct rtw89_dev *rtwdev)
 3668 {
 3669         struct rtw89_btc *btc = &rtwdev->btc;
 3670         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 3671         struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
 3672 
 3673         if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
 3674                 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
 3675                 if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
 3676                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
 3677                                     BTC_RSN_NTFY_SCAN_START);
 3678                 else
 3679                         _set_policy(rtwdev, BTC_CXP_OFF_EQ0,
 3680                                     BTC_RSN_NTFY_SCAN_START);
 3681 
 3682                 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
 3683         } else if (rtwdev->dbcc_en) {
 3684                 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
 3685                     wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
 3686                         _action_wl_5g(rtwdev);
 3687                 else
 3688                         _action_by_bt(rtwdev);
 3689         } else {
 3690                 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
 3691                         _action_wl_5g(rtwdev);
 3692                 else
 3693                         _action_by_bt(rtwdev);
 3694         }
 3695 }
 3696 
 3697 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
 3698 {
 3699         struct rtw89_btc *btc = &rtwdev->btc;
 3700 
 3701         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
 3702 
 3703         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
 3704                 if (btc->cx.bt.link_info.profile_cnt.now == 0)
 3705                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
 3706                                     BTC_ACT_WL_25G_MCC);
 3707                 else
 3708                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
 3709                                     BTC_ACT_WL_25G_MCC);
 3710         } else { /* dedicated-antenna */
 3711                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC);
 3712         }
 3713 }
 3714 
 3715 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
 3716 {       struct rtw89_btc *btc = &rtwdev->btc;
 3717 
 3718         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3719 
 3720         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
 3721                 if (btc->cx.bt.link_info.profile_cnt.now == 0)
 3722                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
 3723                                     BTC_ACT_WL_2G_MCC);
 3724                 else
 3725                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
 3726                                     BTC_ACT_WL_2G_MCC);
 3727         } else { /* dedicated-antenna */
 3728                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
 3729         }
 3730 }
 3731 
 3732 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
 3733 {
 3734         struct rtw89_btc *btc = &rtwdev->btc;
 3735 
 3736         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3737 
 3738         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
 3739                 if (btc->cx.bt.link_info.profile_cnt.now == 0)
 3740                         _set_policy(rtwdev,
 3741                                     BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
 3742                 else
 3743                         _set_policy(rtwdev,
 3744                                     BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
 3745         } else { /* dedicated-antenna */
 3746                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
 3747         }
 3748 }
 3749 
 3750 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
 3751 {
 3752         struct rtw89_btc *btc = &rtwdev->btc;
 3753         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 3754         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 3755         struct rtw89_btc_dm *dm = &btc->dm;
 3756         struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
 3757         u16 policy_type = BTC_CXP_OFF_BT;
 3758         u32 dur;
 3759 
 3760         if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) {
 3761                 policy_type = BTC_CXP_OFF_EQ0;
 3762         } else {
 3763                 /* shared-antenna */
 3764                 switch (wl_rinfo->mrole_type) {
 3765                 case BTC_WLMROLE_STA_GC:
 3766                         dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
 3767                         dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
 3768                         dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
 3769                         _action_by_bt(rtwdev);
 3770                         return;
 3771                 case BTC_WLMROLE_STA_STA:
 3772                         dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
 3773                         dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
 3774                         dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
 3775                         _action_by_bt(rtwdev);
 3776                         return;
 3777                 case BTC_WLMROLE_STA_GC_NOA:
 3778                 case BTC_WLMROLE_STA_GO:
 3779                 case BTC_WLMROLE_STA_GO_NOA:
 3780                         dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
 3781                         dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
 3782                         dur = wl_rinfo->mrole_noa_duration;
 3783 
 3784                         if (wl->status.map._4way) {
 3785                                 dm->wl_scc.ebt_null = 0;
 3786                                 policy_type = BTC_CXP_OFFE_WL;
 3787                         } else if (bt->link_info.status.map.connect == 0) {
 3788                                 dm->wl_scc.ebt_null = 0;
 3789                                 policy_type = BTC_CXP_OFFE_2GISOB;
 3790                         } else if (bt->link_info.a2dp_desc.exist &&
 3791                                    dur < btc->bt_req_len) {
 3792                                 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
 3793                                 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
 3794                         } else if (bt->link_info.a2dp_desc.exist ||
 3795                                    bt->link_info.pan_desc.exist) {
 3796                                 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
 3797                                 policy_type = BTC_CXP_OFFE_2GBWISOB;
 3798                         } else {
 3799                                 dm->wl_scc.ebt_null = 0;
 3800                                 policy_type = BTC_CXP_OFFE_2GBWISOB;
 3801                         }
 3802                         break;
 3803                 default:
 3804                         break;
 3805                 }
 3806         }
 3807 
 3808         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3809         _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
 3810 }
 3811 
 3812 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
 3813 {
 3814         struct rtw89_btc *btc = &rtwdev->btc;
 3815 
 3816         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3817 
 3818         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
 3819                 if (btc->cx.bt.link_info.profile_cnt.now == 0)
 3820                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
 3821                                     BTC_ACT_WL_2G_AP);
 3822                 else
 3823                         _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
 3824         } else {/* dedicated-antenna */
 3825                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
 3826         }
 3827 }
 3828 
 3829 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
 3830 {
 3831         struct rtw89_btc *btc = &rtwdev->btc;
 3832 
 3833         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3834 
 3835         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
 3836                 if (btc->cx.bt.link_info.profile_cnt.now == 0)
 3837                         _set_policy(rtwdev,
 3838                                     BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
 3839                 else
 3840                         _set_policy(rtwdev,
 3841                                     BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
 3842         } else { /* dedicated-antenna */
 3843                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
 3844         }
 3845 }
 3846 
 3847 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
 3848 {
 3849         struct rtw89_btc *btc = &rtwdev->btc;
 3850 
 3851         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3852 
 3853         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
 3854                 _action_by_bt(rtwdev);
 3855         } else {/* dedicated-antenna */
 3856                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
 3857         }
 3858 }
 3859 
 3860 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
 3861 {
 3862         struct rtw89_btc *btc = &rtwdev->btc;
 3863 
 3864         _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 3865 
 3866         if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
 3867                 if (btc->cx.bt.link_info.profile_cnt.now == 0)
 3868                         _set_policy(rtwdev,
 3869                                     BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
 3870                 else
 3871                         _set_policy(rtwdev,
 3872                                     BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
 3873         } else { /* dedicated-antenna */
 3874                 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
 3875         }
 3876 }
 3877 
 3878 static u32 _read_scbd(struct rtw89_dev *rtwdev)
 3879 {
 3880         const struct rtw89_chip_info *chip = rtwdev->chip;
 3881         struct rtw89_btc *btc = &rtwdev->btc;
 3882         u32 scbd_val = 0;
 3883 
 3884         if (!chip->scbd)
 3885                 return 0;
 3886 
 3887         scbd_val = rtw89_mac_get_sb(rtwdev);
 3888         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
 3889                     scbd_val);
 3890 
 3891         btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
 3892         return scbd_val;
 3893 }
 3894 
 3895 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
 3896 {
 3897         const struct rtw89_chip_info *chip = rtwdev->chip;
 3898         struct rtw89_btc *btc = &rtwdev->btc;
 3899         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 3900         u32 scbd_val = 0;
 3901 
 3902         if (!chip->scbd)
 3903                 return;
 3904 
 3905         scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
 3906 
 3907         if (scbd_val == wl->scbd)
 3908                 return;
 3909         rtw89_mac_cfg_sb(rtwdev, scbd_val);
 3910         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
 3911                     scbd_val);
 3912         wl->scbd = scbd_val;
 3913 
 3914         btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
 3915 }
 3916 
 3917 static u8
 3918 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
 3919 {
 3920         const struct rtw89_chip_info *chip = rtwdev->chip;
 3921         u8 next_state, tol = chip->rssi_tol;
 3922 
 3923         if (pre_state == BTC_RSSI_ST_LOW ||
 3924             pre_state == BTC_RSSI_ST_STAY_LOW) {
 3925                 if (rssi >= (thresh + tol))
 3926                         next_state = BTC_RSSI_ST_HIGH;
 3927                 else
 3928                         next_state = BTC_RSSI_ST_STAY_LOW;
 3929         } else {
 3930                 if (rssi < thresh)
 3931                         next_state = BTC_RSSI_ST_LOW;
 3932                 else
 3933                         next_state = BTC_RSSI_ST_STAY_HIGH;
 3934         }
 3935 
 3936         return next_state;
 3937 }
 3938 
 3939 static
 3940 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
 3941 {
 3942         struct rtw89_btc *btc = &rtwdev->btc;
 3943 
 3944         btc->cx.wl.dbcc_info.real_band[phy_idx] =
 3945                 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
 3946                 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
 3947                 btc->cx.wl.dbcc_info.op_band[phy_idx];
 3948 }
 3949 
 3950 static void _update_wl_info(struct rtw89_dev *rtwdev)
 3951 {
 3952         struct rtw89_btc *btc = &rtwdev->btc;
 3953         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 3954         struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
 3955         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 3956         struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
 3957         u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
 3958         u8 cnt_2g = 0, cnt_5g = 0, phy;
 3959         u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
 3960         bool b2g = false, b5g = false, client_joined = false;
 3961 
 3962         memset(wl_rinfo, 0, sizeof(*wl_rinfo));
 3963 
 3964         for (i = 0; i < RTW89_PORT_NUM; i++) {
 3965                 /* check if role active? */
 3966                 if (!wl_linfo[i].active)
 3967                         continue;
 3968 
 3969                 cnt_active++;
 3970                 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
 3971                 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
 3972                 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
 3973                 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
 3974                 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
 3975                 wl_rinfo->active_role[cnt_active - 1].connected = 0;
 3976 
 3977                 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
 3978 
 3979                 phy = wl_linfo[i].phy;
 3980 
 3981                 /* check dbcc role */
 3982                 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
 3983                         wl_dinfo->role[phy] = wl_linfo[i].role;
 3984                         wl_dinfo->op_band[phy] = wl_linfo[i].band;
 3985                         _update_dbcc_band(rtwdev, phy);
 3986                         _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
 3987                 }
 3988 
 3989                 if (wl_linfo[i].connected == MLME_NO_LINK) {
 3990                         continue;
 3991                 } else if (wl_linfo[i].connected == MLME_LINKING) {
 3992                         cnt_connecting++;
 3993                 } else {
 3994                         cnt_connect++;
 3995                         if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
 3996                              wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
 3997                              wl_linfo[i].client_cnt > 1)
 3998                                 client_joined = true;
 3999                 }
 4000 
 4001                 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
 4002                 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
 4003                 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
 4004                 wl_rinfo->active_role[cnt_active - 1].connected = 1;
 4005 
 4006                 /* only care 2 roles + BT coex */
 4007                 if (wl_linfo[i].band != RTW89_BAND_2G) {
 4008                         if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
 4009                                 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
 4010                         cnt_5g++;
 4011                         b5g = true;
 4012                 } else {
 4013                         if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
 4014                                 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
 4015                         cnt_2g++;
 4016                         b2g = true;
 4017                 }
 4018         }
 4019 
 4020         wl_rinfo->connect_cnt = cnt_connect;
 4021 
 4022         /* Be careful to change the following sequence!! */
 4023         if (cnt_connect == 0) {
 4024                 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
 4025                 wl_rinfo->role_map.role.none = 1;
 4026         } else if (!b2g && b5g) {
 4027                 wl_rinfo->link_mode = BTC_WLINK_5G;
 4028         } else if (wl_rinfo->role_map.role.nan) {
 4029                 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
 4030         } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
 4031                 wl_rinfo->link_mode = BTC_WLINK_OTHER;
 4032         } else  if (b2g && b5g && cnt_connect == 2) {
 4033                 if (rtwdev->dbcc_en) {
 4034                         switch (wl_dinfo->role[RTW89_PHY_0]) {
 4035                         case RTW89_WIFI_ROLE_STATION:
 4036                                 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
 4037                                 break;
 4038                         case RTW89_WIFI_ROLE_P2P_GO:
 4039                                 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
 4040                                 break;
 4041                         case RTW89_WIFI_ROLE_P2P_CLIENT:
 4042                                 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
 4043                                 break;
 4044                         case RTW89_WIFI_ROLE_AP:
 4045                                 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
 4046                                 break;
 4047                         default:
 4048                                 wl_rinfo->link_mode = BTC_WLINK_OTHER;
 4049                                 break;
 4050                         }
 4051                 } else {
 4052                         wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
 4053                 }
 4054         } else if (!b5g && cnt_connect == 2) {
 4055                 if (wl_rinfo->role_map.role.station &&
 4056                     (wl_rinfo->role_map.role.p2p_go ||
 4057                     wl_rinfo->role_map.role.p2p_gc ||
 4058                     wl_rinfo->role_map.role.ap)) {
 4059                         if (wl_2g_ch[0] == wl_2g_ch[1])
 4060                                 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
 4061                         else
 4062                                 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
 4063                 } else {
 4064                         wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
 4065                 }
 4066         } else if (!b5g && cnt_connect == 1) {
 4067                 if (wl_rinfo->role_map.role.station)
 4068                         wl_rinfo->link_mode = BTC_WLINK_2G_STA;
 4069                 else if (wl_rinfo->role_map.role.ap)
 4070                         wl_rinfo->link_mode = BTC_WLINK_2G_AP;
 4071                 else if (wl_rinfo->role_map.role.p2p_go)
 4072                         wl_rinfo->link_mode = BTC_WLINK_2G_GO;
 4073                 else if (wl_rinfo->role_map.role.p2p_gc)
 4074                         wl_rinfo->link_mode = BTC_WLINK_2G_GC;
 4075                 else
 4076                         wl_rinfo->link_mode = BTC_WLINK_OTHER;
 4077         }
 4078 
 4079         /* if no client_joined, don't care P2P-GO/AP role */
 4080         if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
 4081                 if (!client_joined) {
 4082                         if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
 4083                             wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
 4084                                 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
 4085                                 wl_rinfo->connect_cnt = 1;
 4086                         } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
 4087                                  wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
 4088                                 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
 4089                                 wl_rinfo->connect_cnt = 0;
 4090                         }
 4091                 }
 4092         }
 4093 
 4094         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4095                     "[BTC], cnt_connect = %d, link_mode = %d\n",
 4096                     cnt_connect, wl_rinfo->link_mode);
 4097 
 4098         _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
 4099 }
 4100 
 4101 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
 4102 {
 4103         struct rtw89_btc *btc = &rtwdev->btc;
 4104         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4105         struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
 4106         struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
 4107         struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
 4108         u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
 4109         u8 cnt_2g = 0, cnt_5g = 0, phy;
 4110         u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
 4111         bool b2g = false, b5g = false, client_joined = false;
 4112         u8 i;
 4113 
 4114         memset(wl_rinfo, 0, sizeof(*wl_rinfo));
 4115 
 4116         for (i = 0; i < RTW89_PORT_NUM; i++) {
 4117                 if (!wl_linfo[i].active)
 4118                         continue;
 4119 
 4120                 cnt_active++;
 4121                 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
 4122                 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
 4123                 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
 4124                 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
 4125                 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
 4126                 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
 4127 
 4128                 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
 4129 
 4130                 phy = wl_linfo[i].phy;
 4131 
 4132                 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
 4133                         wl_dinfo->role[phy] = wl_linfo[i].role;
 4134                         wl_dinfo->op_band[phy] = wl_linfo[i].band;
 4135                         _update_dbcc_band(rtwdev, phy);
 4136                         _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
 4137                 }
 4138 
 4139                 if (wl_linfo[i].connected == MLME_NO_LINK) {
 4140                         continue;
 4141                 } else if (wl_linfo[i].connected == MLME_LINKING) {
 4142                         cnt_connecting++;
 4143                 } else {
 4144                         cnt_connect++;
 4145                         if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
 4146                              wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
 4147                              wl_linfo[i].client_cnt > 1)
 4148                                 client_joined = true;
 4149                 }
 4150 
 4151                 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
 4152                 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
 4153                 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
 4154                 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
 4155 
 4156                 /* only care 2 roles + BT coex */
 4157                 if (wl_linfo[i].band != RTW89_BAND_2G) {
 4158                         if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
 4159                                 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
 4160                         cnt_5g++;
 4161                         b5g = true;
 4162                 } else {
 4163                         if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
 4164                                 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
 4165                         cnt_2g++;
 4166                         b2g = true;
 4167                 }
 4168         }
 4169 
 4170         wl_rinfo->connect_cnt = cnt_connect;
 4171 
 4172         /* Be careful to change the following sequence!! */
 4173         if (cnt_connect == 0) {
 4174                 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
 4175                 wl_rinfo->role_map.role.none = 1;
 4176         } else if (!b2g && b5g) {
 4177                 wl_rinfo->link_mode = BTC_WLINK_5G;
 4178         } else if (wl_rinfo->role_map.role.nan) {
 4179                 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
 4180         } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
 4181                 wl_rinfo->link_mode = BTC_WLINK_OTHER;
 4182         } else  if (b2g && b5g && cnt_connect == 2) {
 4183                 if (rtwdev->dbcc_en) {
 4184                         switch (wl_dinfo->role[RTW89_PHY_0]) {
 4185                         case RTW89_WIFI_ROLE_STATION:
 4186                                 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
 4187                                 break;
 4188                         case RTW89_WIFI_ROLE_P2P_GO:
 4189                                 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
 4190                                 break;
 4191                         case RTW89_WIFI_ROLE_P2P_CLIENT:
 4192                                 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
 4193                                 break;
 4194                         case RTW89_WIFI_ROLE_AP:
 4195                                 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
 4196                                 break;
 4197                         default:
 4198                                 wl_rinfo->link_mode = BTC_WLINK_OTHER;
 4199                                 break;
 4200                         }
 4201                 } else {
 4202                         wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
 4203                 }
 4204         } else if (!b5g && cnt_connect == 2) {
 4205                 if (wl_rinfo->role_map.role.station &&
 4206                     (wl_rinfo->role_map.role.p2p_go ||
 4207                     wl_rinfo->role_map.role.p2p_gc ||
 4208                     wl_rinfo->role_map.role.ap)) {
 4209                         if (wl_2g_ch[0] == wl_2g_ch[1])
 4210                                 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
 4211                         else
 4212                                 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
 4213                 } else {
 4214                         wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
 4215                 }
 4216         } else if (!b5g && cnt_connect == 1) {
 4217                 if (wl_rinfo->role_map.role.station)
 4218                         wl_rinfo->link_mode = BTC_WLINK_2G_STA;
 4219                 else if (wl_rinfo->role_map.role.ap)
 4220                         wl_rinfo->link_mode = BTC_WLINK_2G_AP;
 4221                 else if (wl_rinfo->role_map.role.p2p_go)
 4222                         wl_rinfo->link_mode = BTC_WLINK_2G_GO;
 4223                 else if (wl_rinfo->role_map.role.p2p_gc)
 4224                         wl_rinfo->link_mode = BTC_WLINK_2G_GC;
 4225                 else
 4226                         wl_rinfo->link_mode = BTC_WLINK_OTHER;
 4227         }
 4228 
 4229         /* if no client_joined, don't care P2P-GO/AP role */
 4230         if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
 4231                 if (!client_joined) {
 4232                         if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
 4233                             wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
 4234                                 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
 4235                                 wl_rinfo->connect_cnt = 1;
 4236                         } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
 4237                                  wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
 4238                                 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
 4239                                 wl_rinfo->connect_cnt = 0;
 4240                         }
 4241                 }
 4242         }
 4243 
 4244         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4245                     "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
 4246                     cnt_connect, cnt_connecting, wl_rinfo->link_mode);
 4247 
 4248         _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
 4249 }
 4250 
 4251 #define BTC_CHK_HANG_MAX 3
 4252 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
 4253 
 4254 void rtw89_coex_act1_work(struct work_struct *work)
 4255 {
 4256         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4257                                                 coex_act1_work.work);
 4258         struct rtw89_btc *btc = &rtwdev->btc;
 4259         struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
 4260         struct rtw89_btc_cx *cx = &btc->cx;
 4261         struct rtw89_btc_wl_info *wl = &cx->wl;
 4262 
 4263         mutex_lock(&rtwdev->mutex);
 4264         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
 4265         dm->cnt_notify[BTC_NCNT_TIMER]++;
 4266         if (wl->status.map._4way)
 4267                 wl->status.map._4way = false;
 4268         if (wl->status.map.connecting)
 4269                 wl->status.map.connecting = false;
 4270 
 4271         _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
 4272         mutex_unlock(&rtwdev->mutex);
 4273 }
 4274 
 4275 void rtw89_coex_bt_devinfo_work(struct work_struct *work)
 4276 {
 4277         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4278                                                 coex_bt_devinfo_work.work);
 4279         struct rtw89_btc *btc = &rtwdev->btc;
 4280         struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
 4281         struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
 4282 
 4283         mutex_lock(&rtwdev->mutex);
 4284         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
 4285         dm->cnt_notify[BTC_NCNT_TIMER]++;
 4286         a2dp->play_latency = 0;
 4287         _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
 4288         mutex_unlock(&rtwdev->mutex);
 4289 }
 4290 
 4291 void rtw89_coex_rfk_chk_work(struct work_struct *work)
 4292 {
 4293         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4294                                                 coex_rfk_chk_work.work);
 4295         struct rtw89_btc *btc = &rtwdev->btc;
 4296         struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
 4297         struct rtw89_btc_cx *cx = &btc->cx;
 4298         struct rtw89_btc_wl_info *wl = &cx->wl;
 4299 
 4300         mutex_lock(&rtwdev->mutex);
 4301         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
 4302         dm->cnt_notify[BTC_NCNT_TIMER]++;
 4303         if (wl->rfk_info.state != BTC_WRFK_STOP) {
 4304                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4305                             "[BTC], %s(): RFK timeout\n", __func__);
 4306                 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
 4307                 dm->error.map.wl_rfk_timeout = true;
 4308                 wl->rfk_info.state = BTC_WRFK_STOP;
 4309                 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
 4310                 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
 4311         }
 4312         mutex_unlock(&rtwdev->mutex);
 4313 }
 4314 
 4315 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
 4316 {
 4317         const struct rtw89_chip_info *chip = rtwdev->chip;
 4318         struct rtw89_btc *btc = &rtwdev->btc;
 4319         struct rtw89_btc_cx *cx = &btc->cx;
 4320         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 4321         u32 val;
 4322         bool status_change = false;
 4323 
 4324         if (!chip->scbd)
 4325                 return;
 4326 
 4327         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
 4328 
 4329         val = _read_scbd(rtwdev);
 4330         if (val == BTC_SCB_INV_VALUE) {
 4331                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4332                             "[BTC], %s(): return by invalid scbd value\n",
 4333                             __func__);
 4334                 return;
 4335         }
 4336 
 4337         if (!(val & BTC_BSCB_ON) ||
 4338             btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX)
 4339                 bt->enable.now = 0;
 4340         else
 4341                 bt->enable.now = 1;
 4342 
 4343         if (bt->enable.now != bt->enable.last)
 4344                 status_change = true;
 4345 
 4346         /* reset bt info if bt re-enable */
 4347         if (bt->enable.now && !bt->enable.last) {
 4348                 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
 4349                 cx->cnt_bt[BTC_BCNT_REENABLE]++;
 4350                 bt->enable.now = 1;
 4351         }
 4352 
 4353         bt->enable.last = bt->enable.now;
 4354         bt->scbd = val;
 4355         bt->mbx_avl = !!(val & BTC_BSCB_ACT);
 4356 
 4357         if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
 4358                 status_change = true;
 4359 
 4360         bt->whql_test = !!(val & BTC_BSCB_WHQL);
 4361         bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
 4362         bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT);
 4363 
 4364         /* if rfk run 1->0 */
 4365         if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
 4366                 status_change = true;
 4367 
 4368         bt->rfk_info.map.run  = !!(val & BTC_BSCB_RFK_RUN);
 4369         bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
 4370         bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
 4371         bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
 4372         bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
 4373 
 4374         if (!only_update && status_change)
 4375                 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
 4376 }
 4377 
 4378 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
 4379 {
 4380         struct rtw89_btc *btc = &rtwdev->btc;
 4381         struct rtw89_btc_cx *cx = &btc->cx;
 4382         struct rtw89_btc_bt_info *bt = &cx->bt;
 4383 
 4384         _update_bt_scbd(rtwdev, true);
 4385 
 4386         cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
 4387 
 4388         if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
 4389             !bt->rfk_info.map.timeout) {
 4390                 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
 4391         } else {
 4392                 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
 4393                 return true;
 4394         }
 4395         return false;
 4396 }
 4397 
 4398 static
 4399 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
 4400 {
 4401         const struct rtw89_chip_info *chip = rtwdev->chip;
 4402         struct rtw89_btc *btc = &rtwdev->btc;
 4403         struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
 4404         struct rtw89_btc_cx *cx = &btc->cx;
 4405         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4406         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 4407         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 4408         u8 mode;
 4409 
 4410         lockdep_assert_held(&rtwdev->mutex);
 4411 
 4412         dm->run_reason = reason;
 4413         _update_dm_step(rtwdev, reason);
 4414         _update_btc_state_map(rtwdev);
 4415 
 4416         if (chip->chip_id == RTL8852A)
 4417                 mode = wl_rinfo->link_mode;
 4418         else
 4419                 mode = wl_rinfo_v1->link_mode;
 4420 
 4421         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
 4422                     __func__, reason, mode);
 4423         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
 4424                     __func__, dm->wl_only, dm->bt_only);
 4425 
 4426         /* Be careful to change the following function sequence!! */
 4427         if (btc->ctrl.manual) {
 4428                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4429                             "[BTC], %s(): return for Manual CTRL!!\n",
 4430                             __func__);
 4431                 return;
 4432         }
 4433 
 4434         if (btc->ctrl.igno_bt &&
 4435             (reason == BTC_RSN_UPDATE_BT_INFO ||
 4436              reason == BTC_RSN_UPDATE_BT_SCBD)) {
 4437                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4438                             "[BTC], %s(): return for Stop Coex DM!!\n",
 4439                             __func__);
 4440                 return;
 4441         }
 4442 
 4443         if (!wl->status.map.init_ok) {
 4444                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4445                             "[BTC], %s(): return for WL init fail!!\n",
 4446                             __func__);
 4447                 return;
 4448         }
 4449 
 4450         if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
 4451             wl->status.map.lps_pre == wl->status.map.lps &&
 4452             (reason == BTC_RSN_NTFY_POWEROFF ||
 4453             reason == BTC_RSN_NTFY_RADIO_STATE)) {
 4454                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4455                             "[BTC], %s(): return for WL rf off state no change!!\n",
 4456                             __func__);
 4457                 return;
 4458         }
 4459 
 4460         dm->cnt_dm[BTC_DCNT_RUN]++;
 4461 
 4462         if (btc->ctrl.always_freerun) {
 4463                 _action_freerun(rtwdev);
 4464                 btc->ctrl.igno_bt = true;
 4465                 goto exit;
 4466         }
 4467 
 4468         if (dm->wl_only) {
 4469                 _action_wl_only(rtwdev);
 4470                 btc->ctrl.igno_bt = true;
 4471                 goto exit;
 4472         }
 4473 
 4474         if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
 4475                 _action_wl_off(rtwdev);
 4476                 btc->ctrl.igno_bt = true;
 4477                 goto exit;
 4478         }
 4479 
 4480         btc->ctrl.igno_bt = false;
 4481         dm->freerun = false;
 4482 
 4483         if (reason == BTC_RSN_NTFY_INIT) {
 4484                 _action_wl_init(rtwdev);
 4485                 goto exit;
 4486         }
 4487 
 4488         if (!cx->bt.enable.now && !cx->other.type) {
 4489                 _action_bt_off(rtwdev);
 4490                 goto exit;
 4491         }
 4492 
 4493         if (cx->bt.whql_test) {
 4494                 _action_bt_whql(rtwdev);
 4495                 goto exit;
 4496         }
 4497 
 4498         if (wl->rfk_info.state != BTC_WRFK_STOP) {
 4499                 _action_wl_rfk(rtwdev);
 4500                 goto exit;
 4501         }
 4502 
 4503         if (cx->state_map == BTC_WLINKING) {
 4504                 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
 4505                     mode == BTC_WLINK_5G) {
 4506                         _action_wl_scan(rtwdev);
 4507                         goto exit;
 4508                 }
 4509         }
 4510 
 4511         if (wl->status.map.scan) {
 4512                 _action_wl_scan(rtwdev);
 4513                 goto exit;
 4514         }
 4515 
 4516         switch (mode) {
 4517         case BTC_WLINK_NOLINK:
 4518                 _action_wl_nc(rtwdev);
 4519                 break;
 4520         case BTC_WLINK_2G_STA:
 4521                 _action_wl_2g_sta(rtwdev);
 4522                 break;
 4523         case BTC_WLINK_2G_AP:
 4524                 _action_wl_2g_ap(rtwdev);
 4525                 break;
 4526         case BTC_WLINK_2G_GO:
 4527                 _action_wl_2g_go(rtwdev);
 4528                 break;
 4529         case BTC_WLINK_2G_GC:
 4530                 _action_wl_2g_gc(rtwdev);
 4531                 break;
 4532         case BTC_WLINK_2G_SCC:
 4533                 if (chip->chip_id == RTL8852A)
 4534                         _action_wl_2g_scc(rtwdev);
 4535                 else if (chip->chip_id == RTL8852C)
 4536                         _action_wl_2g_scc_v1(rtwdev);
 4537                 break;
 4538         case BTC_WLINK_2G_MCC:
 4539                 _action_wl_2g_mcc(rtwdev);
 4540                 break;
 4541         case BTC_WLINK_25G_MCC:
 4542                 _action_wl_25g_mcc(rtwdev);
 4543                 break;
 4544         case BTC_WLINK_5G:
 4545                 _action_wl_5g(rtwdev);
 4546                 break;
 4547         case BTC_WLINK_2G_NAN:
 4548                 _action_wl_2g_nan(rtwdev);
 4549                 break;
 4550         default:
 4551                 _action_wl_other(rtwdev);
 4552                 break;
 4553         }
 4554 
 4555 exit:
 4556         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
 4557         _action_common(rtwdev);
 4558 }
 4559 
 4560 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
 4561 {
 4562         struct rtw89_btc *btc = &rtwdev->btc;
 4563 
 4564         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 4565         btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
 4566 }
 4567 
 4568 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
 4569 {
 4570         struct rtw89_btc *btc = &rtwdev->btc;
 4571         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4572 
 4573         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
 4574         btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
 4575 
 4576         btc->cx.wl.status.map.rf_off = 1;
 4577         btc->cx.wl.status.map.busy = 0;
 4578         wl->status.map.lps = BTC_LPS_OFF;
 4579 
 4580         _write_scbd(rtwdev, BTC_WSCB_ALL, false);
 4581         _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
 4582 
 4583         rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
 4584 
 4585         btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
 4586 }
 4587 
 4588 static void _set_init_info(struct rtw89_dev *rtwdev)
 4589 {
 4590         const struct rtw89_chip_info *chip = rtwdev->chip;
 4591         struct rtw89_btc *btc = &rtwdev->btc;
 4592         struct rtw89_btc_dm *dm = &btc->dm;
 4593         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4594 
 4595         dm->init_info.wl_only = (u8)dm->wl_only;
 4596         dm->init_info.bt_only = (u8)dm->bt_only;
 4597         dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok;
 4598         dm->init_info.dbcc_en = rtwdev->dbcc_en;
 4599         dm->init_info.cx_other = btc->cx.other.type;
 4600         dm->init_info.wl_guard_ch = chip->afh_guard_ch;
 4601         dm->init_info.module = btc->mdinfo;
 4602 }
 4603 
 4604 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
 4605 {
 4606         struct rtw89_btc *btc = &rtwdev->btc;
 4607         struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
 4608         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4609         const struct rtw89_chip_info *chip = rtwdev->chip;
 4610 
 4611         _reset_btc_var(rtwdev, BTC_RESET_ALL);
 4612         btc->dm.run_reason = BTC_RSN_NONE;
 4613         btc->dm.run_action = BTC_ACT_NONE;
 4614         btc->ctrl.igno_bt = true;
 4615 
 4616         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4617                     "[BTC], %s(): mode=%d\n", __func__, mode);
 4618 
 4619         dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
 4620         dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
 4621         dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
 4622         wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
 4623 
 4624         chip->ops->btc_set_rfe(rtwdev);
 4625         chip->ops->btc_init_cfg(rtwdev);
 4626 
 4627         if (!wl->status.map.init_ok) {
 4628                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4629                             "[BTC], %s(): return for WL init fail!!\n",
 4630                             __func__);
 4631                 dm->error.map.init = true;
 4632                 return;
 4633         }
 4634 
 4635         _write_scbd(rtwdev,
 4636                     BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
 4637         _update_bt_scbd(rtwdev, true);
 4638         if (rtw89_mac_get_ctrl_path(rtwdev)) {
 4639                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4640                             "[BTC], %s(): PTA owner warning!!\n",
 4641                             __func__);
 4642                 dm->error.map.pta_owner = true;
 4643         }
 4644 
 4645         _set_init_info(rtwdev);
 4646         _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
 4647         rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
 4648         btc_fw_set_monreg(rtwdev);
 4649         _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
 4650         _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
 4651 
 4652         _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
 4653 }
 4654 
 4655 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
 4656 {
 4657         struct rtw89_btc *btc = &rtwdev->btc;
 4658         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4659 
 4660         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4661                     "[BTC], %s(): phy_idx=%d, band=%d\n",
 4662                     __func__, phy_idx, band);
 4663         btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
 4664         wl->status.map.scan = true;
 4665         wl->scan_info.band[phy_idx] = band;
 4666         wl->scan_info.phy_map |= BIT(phy_idx);
 4667         _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
 4668 
 4669         if (rtwdev->dbcc_en) {
 4670                 wl->dbcc_info.scan_band[phy_idx] = band;
 4671                 _update_dbcc_band(rtwdev, phy_idx);
 4672                 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
 4673         }
 4674 
 4675         _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
 4676 }
 4677 
 4678 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
 4679 {
 4680         struct rtw89_btc *btc = &rtwdev->btc;
 4681         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4682 
 4683         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4684                     "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
 4685         btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
 4686 
 4687         wl->status.map.scan = false;
 4688         wl->scan_info.phy_map &= ~BIT(phy_idx);
 4689         _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
 4690 
 4691         if (rtwdev->dbcc_en) {
 4692                 _update_dbcc_band(rtwdev, phy_idx);
 4693                 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
 4694         }
 4695 
 4696         _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
 4697 }
 4698 
 4699 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
 4700 {
 4701         struct rtw89_btc *btc = &rtwdev->btc;
 4702         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4703 
 4704         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4705                     "[BTC], %s(): phy_idx=%d, band=%d\n",
 4706                     __func__, phy_idx, band);
 4707         btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
 4708 
 4709         wl->scan_info.band[phy_idx] = band;
 4710         wl->scan_info.phy_map |= BIT(phy_idx);
 4711         _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
 4712 
 4713         if (rtwdev->dbcc_en) {
 4714                 wl->dbcc_info.scan_band[phy_idx] = band;
 4715                 _update_dbcc_band(rtwdev, phy_idx);
 4716                 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
 4717         }
 4718         _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
 4719 }
 4720 
 4721 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
 4722                                     enum btc_pkt_type pkt_type)
 4723 {
 4724         struct rtw89_btc *btc = &rtwdev->btc;
 4725         struct rtw89_btc_cx *cx = &btc->cx;
 4726         struct rtw89_btc_wl_info *wl = &cx->wl;
 4727         struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
 4728         struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
 4729         struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
 4730         u32 cnt;
 4731         u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
 4732         bool delay_work = false;
 4733 
 4734         switch (pkt_type) {
 4735         case PACKET_DHCP:
 4736                 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
 4737                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4738                             "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
 4739                 wl->status.map.connecting = true;
 4740                 delay_work = true;
 4741                 break;
 4742         case PACKET_EAPOL:
 4743                 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
 4744                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4745                             "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
 4746                 wl->status.map._4way = true;
 4747                 delay_work = true;
 4748                 if (hfp->exist || hid->exist)
 4749                         delay /= 2;
 4750                 break;
 4751         case PACKET_EAPOL_END:
 4752                 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
 4753                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4754                             "[BTC], %s(): EAPOL_End cnt=%d\n",
 4755                             __func__, cnt);
 4756                 wl->status.map._4way = false;
 4757                 cancel_delayed_work(&rtwdev->coex_act1_work);
 4758                 break;
 4759         case PACKET_ARP:
 4760                 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
 4761                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4762                             "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
 4763                 return;
 4764         case PACKET_ICMP:
 4765                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4766                             "[BTC], %s(): ICMP pkt\n", __func__);
 4767                 return;
 4768         default:
 4769                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4770                             "[BTC], %s(): unknown packet type %d\n",
 4771                             __func__, pkt_type);
 4772                 return;
 4773         }
 4774 
 4775         if (delay_work) {
 4776                 cancel_delayed_work(&rtwdev->coex_act1_work);
 4777                 ieee80211_queue_delayed_work(rtwdev->hw,
 4778                                              &rtwdev->coex_act1_work, delay);
 4779         }
 4780 
 4781         btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
 4782         _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
 4783 }
 4784 
 4785 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
 4786 {
 4787         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4788                                                 btc.eapol_notify_work);
 4789 
 4790         mutex_lock(&rtwdev->mutex);
 4791         rtw89_leave_ps_mode(rtwdev);
 4792         rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
 4793         mutex_unlock(&rtwdev->mutex);
 4794 }
 4795 
 4796 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
 4797 {
 4798         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4799                                                 btc.arp_notify_work);
 4800 
 4801         mutex_lock(&rtwdev->mutex);
 4802         rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
 4803         mutex_unlock(&rtwdev->mutex);
 4804 }
 4805 
 4806 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
 4807 {
 4808         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4809                                                 btc.dhcp_notify_work);
 4810 
 4811         mutex_lock(&rtwdev->mutex);
 4812         rtw89_leave_ps_mode(rtwdev);
 4813         rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
 4814         mutex_unlock(&rtwdev->mutex);
 4815 }
 4816 
 4817 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
 4818 {
 4819         struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
 4820                                                 btc.icmp_notify_work);
 4821 
 4822         mutex_lock(&rtwdev->mutex);
 4823         rtw89_leave_ps_mode(rtwdev);
 4824         rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
 4825         mutex_unlock(&rtwdev->mutex);
 4826 }
 4827 
 4828 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
 4829 {
 4830         const struct rtw89_chip_info *chip = rtwdev->chip;
 4831         struct rtw89_btc *btc = &rtwdev->btc;
 4832         struct rtw89_btc_cx *cx = &btc->cx;
 4833         struct rtw89_btc_bt_info *bt = &cx->bt;
 4834         struct rtw89_btc_bt_link_info *b = &bt->link_info;
 4835         struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
 4836         struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
 4837         struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
 4838         struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
 4839         union btc_btinfo btinfo;
 4840 
 4841         if (buf[BTC_BTINFO_L1] != 6)
 4842                 return;
 4843 
 4844         if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
 4845                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4846                             "[BTC], %s(): return by bt-info duplicate!!\n",
 4847                             __func__);
 4848                 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
 4849                 return;
 4850         }
 4851 
 4852         memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
 4853 
 4854         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4855                     "[BTC], %s(): bt_info[2]=0x%02x\n",
 4856                     __func__, bt->raw_info[2]);
 4857 
 4858         /* reset to mo-connect before update */
 4859         b->status.val = BTC_BLINK_NOCONNECT;
 4860         b->profile_cnt.last = b->profile_cnt.now;
 4861         b->relink.last = b->relink.now;
 4862         a2dp->exist_last = a2dp->exist;
 4863         b->multi_link.last = b->multi_link.now;
 4864         bt->inq_pag.last = bt->inq_pag.now;
 4865         b->profile_cnt.now = 0;
 4866         hid->type = 0;
 4867 
 4868         /* parse raw info low-Byte2 */
 4869         btinfo.val = bt->raw_info[BTC_BTINFO_L2];
 4870         b->status.map.connect = btinfo.lb2.connect;
 4871         b->status.map.sco_busy = btinfo.lb2.sco_busy;
 4872         b->status.map.acl_busy = btinfo.lb2.acl_busy;
 4873         b->status.map.inq_pag = btinfo.lb2.inq_pag;
 4874         bt->inq_pag.now = btinfo.lb2.inq_pag;
 4875         cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
 4876 
 4877         hfp->exist = btinfo.lb2.hfp;
 4878         b->profile_cnt.now += (u8)hfp->exist;
 4879         hid->exist = btinfo.lb2.hid;
 4880         b->profile_cnt.now += (u8)hid->exist;
 4881         a2dp->exist = btinfo.lb2.a2dp;
 4882         b->profile_cnt.now += (u8)a2dp->exist;
 4883         pan->active = btinfo.lb2.pan;
 4884 
 4885         /* parse raw info low-Byte3 */
 4886         btinfo.val = bt->raw_info[BTC_BTINFO_L3];
 4887         if (btinfo.lb3.retry != 0)
 4888                 cx->cnt_bt[BTC_BCNT_RETRY]++;
 4889         b->cqddr = btinfo.lb3.cqddr;
 4890         cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
 4891         bt->inq = btinfo.lb3.inq;
 4892         cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
 4893         bt->pag = btinfo.lb3.pag;
 4894 
 4895         b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
 4896         /* parse raw info high-Byte0 */
 4897         btinfo.val = bt->raw_info[BTC_BTINFO_H0];
 4898         /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
 4899         b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
 4900 
 4901         /* parse raw info high-Byte1 */
 4902         btinfo.val = bt->raw_info[BTC_BTINFO_H1];
 4903         b->status.map.ble_connect = btinfo.hb1.ble_connect;
 4904         if (btinfo.hb1.ble_connect)
 4905                 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
 4906 
 4907         cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
 4908         bt->reinit = btinfo.hb1.reinit;
 4909         cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
 4910         b->relink.now = btinfo.hb1.relink;
 4911         cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
 4912         bt->igno_wl = btinfo.hb1.igno_wl;
 4913 
 4914         if (bt->igno_wl && !cx->wl.status.map.rf_off)
 4915                 _set_bt_ignore_wlan_act(rtwdev, false);
 4916 
 4917         hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
 4918         bt->ble_scan_en = btinfo.hb1.ble_scan;
 4919 
 4920         cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
 4921         b->role_sw = btinfo.hb1.role_sw;
 4922 
 4923         b->multi_link.now = btinfo.hb1.multi_link;
 4924 
 4925         /* parse raw info high-Byte2 */
 4926         btinfo.val = bt->raw_info[BTC_BTINFO_H2];
 4927         pan->exist = btinfo.hb2.pan_active;
 4928         b->profile_cnt.now += (u8)pan->exist;
 4929 
 4930         cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
 4931         b->afh_update = btinfo.hb2.afh_update;
 4932         a2dp->active = btinfo.hb2.a2dp_active;
 4933         b->slave_role = btinfo.hb2.slave;
 4934         hid->slot_info = btinfo.hb2.hid_slot;
 4935         hid->pair_cnt = btinfo.hb2.hid_cnt;
 4936         hid->type |= (hid->slot_info == BTC_HID_218 ?
 4937                       BTC_HID_218 : BTC_HID_418);
 4938         /* parse raw info high-Byte3 */
 4939         btinfo.val = bt->raw_info[BTC_BTINFO_H3];
 4940         a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
 4941 
 4942         if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
 4943                 cx->cnt_bt[BTC_BCNT_RATECHG]++;
 4944         b->tx_3m = (u32)btinfo.hb3.tx_3m;
 4945 
 4946         a2dp->sink = btinfo.hb3.a2dp_sink;
 4947 
 4948         if (b->profile_cnt.now || b->status.map.ble_connect)
 4949                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1);
 4950         else
 4951                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0);
 4952 
 4953         if (!a2dp->exist_last && a2dp->exist) {
 4954                 a2dp->vendor_id = 0;
 4955                 a2dp->flush_time = 0;
 4956                 a2dp->play_latency = 1;
 4957                 ieee80211_queue_delayed_work(rtwdev->hw,
 4958                                              &rtwdev->coex_bt_devinfo_work,
 4959                                              RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
 4960         }
 4961 
 4962         if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 ||
 4963                             a2dp->play_latency == 1))
 4964                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1);
 4965         else
 4966                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0);
 4967 
 4968         _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
 4969 }
 4970 
 4971 enum btc_wl_mode {
 4972         BTC_WL_MODE_HT = 0,
 4973         BTC_WL_MODE_VHT = 1,
 4974         BTC_WL_MODE_HE = 2,
 4975         BTC_WL_MODE_NUM,
 4976 };
 4977 
 4978 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 4979                               struct rtw89_sta *rtwsta, enum btc_role_state state)
 4980 {
 4981         const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
 4982         const struct rtw89_chip_info *chip = rtwdev->chip;
 4983         struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
 4984         struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
 4985         struct rtw89_btc *btc = &rtwdev->btc;
 4986         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 4987         struct rtw89_btc_wl_link_info r = {0};
 4988         struct rtw89_btc_wl_link_info *wlinfo = NULL;
 4989         u8 mode = 0;
 4990 
 4991         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
 4992         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 4993                     "[BTC], role is STA=%d\n",
 4994                     vif->type == NL80211_IFTYPE_STATION);
 4995         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
 4996         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
 4997                     chan->band_type, chan->channel, chan->band_width);
 4998         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
 4999                     state == BTC_ROLE_MSTS_STA_CONN_END);
 5000         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5001                     "[BTC], bcn_period=%d dtim_period=%d\n",
 5002                     vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
 5003 
 5004         if (rtwsta) {
 5005                 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
 5006                             rtwsta->mac_id);
 5007 
 5008                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5009                             "[BTC], STA support HE=%d VHT=%d HT=%d\n",
 5010                             sta->deflink.he_cap.has_he,
 5011                             sta->deflink.vht_cap.vht_supported,
 5012                             sta->deflink.ht_cap.ht_supported);
 5013                 if (sta->deflink.he_cap.has_he)
 5014                         mode |= BIT(BTC_WL_MODE_HE);
 5015                 if (sta->deflink.vht_cap.vht_supported)
 5016                         mode |= BIT(BTC_WL_MODE_VHT);
 5017                 if (sta->deflink.ht_cap.ht_supported)
 5018                         mode |= BIT(BTC_WL_MODE_HT);
 5019 
 5020                 r.mode = mode;
 5021         }
 5022 
 5023         if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
 5024                 return;
 5025 
 5026         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5027                     "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
 5028 
 5029         r.role = rtwvif->wifi_role;
 5030         r.phy = rtwvif->phy_idx;
 5031         r.pid = rtwvif->port;
 5032         r.active = true;
 5033         r.connected = MLME_LINKED;
 5034         r.bcn_period = vif->bss_conf.beacon_int;
 5035         r.dtim_period = vif->bss_conf.dtim_period;
 5036         r.band = chan->band_type;
 5037         r.ch = chan->channel;
 5038         r.bw = chan->band_width;
 5039         ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
 5040 
 5041         if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
 5042                 r.mac_id = rtwsta->mac_id;
 5043 
 5044         btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
 5045 
 5046         wlinfo = &wl->link_info[r.pid];
 5047 
 5048         memcpy(wlinfo, &r, sizeof(*wlinfo));
 5049         if (chip->chip_id == RTL8852A)
 5050                 _update_wl_info(rtwdev);
 5051         else
 5052                 _update_wl_info_v1(rtwdev);
 5053 
 5054         if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
 5055             wlinfo->connected == MLME_NO_LINK)
 5056                 btc->dm.leak_ap = 0;
 5057 
 5058         if (state == BTC_ROLE_MSTS_STA_CONN_START)
 5059                 wl->status.map.connecting = 1;
 5060         else
 5061                 wl->status.map.connecting = 0;
 5062 
 5063         if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
 5064                 wl->status.map._4way = false;
 5065 
 5066         _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
 5067 }
 5068 
 5069 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
 5070 {
 5071         const struct rtw89_chip_info *chip = rtwdev->chip;
 5072         struct rtw89_btc *btc = &rtwdev->btc;
 5073         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 5074         u32 val;
 5075 
 5076         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
 5077                     __func__, rf_state);
 5078         btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
 5079 
 5080         switch (rf_state) {
 5081         case BTC_RFCTRL_WL_OFF:
 5082                 wl->status.map.rf_off = 1;
 5083                 wl->status.map.lps = BTC_LPS_OFF;
 5084                 wl->status.map.busy = 0;
 5085                 break;
 5086         case BTC_RFCTRL_FW_CTRL:
 5087                 wl->status.map.rf_off = 0;
 5088                 wl->status.map.lps = BTC_LPS_RF_OFF;
 5089                 wl->status.map.busy = 0;
 5090                 break;
 5091         case BTC_RFCTRL_WL_ON:
 5092         default:
 5093                 wl->status.map.rf_off = 0;
 5094                 wl->status.map.lps = BTC_LPS_OFF;
 5095                 break;
 5096         }
 5097 
 5098         if (rf_state == BTC_RFCTRL_WL_ON) {
 5099                 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
 5100                 rtw89_btc_fw_en_rpt(rtwdev,
 5101                                     RPT_EN_MREG | RPT_EN_BT_VER_INFO, true);
 5102                 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
 5103                 _write_scbd(rtwdev, val, true);
 5104                 _update_bt_scbd(rtwdev, true);
 5105                 chip->ops->btc_init_cfg(rtwdev);
 5106         } else {
 5107                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
 5108                 if (rf_state == BTC_RFCTRL_WL_OFF)
 5109                         _write_scbd(rtwdev, BTC_WSCB_ALL, false);
 5110         }
 5111 
 5112         _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
 5113 
 5114         wl->status.map.rf_off_pre = wl->status.map.rf_off;
 5115         wl->status.map.lps_pre = wl->status.map.lps;
 5116 }
 5117 
 5118 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
 5119                          enum btc_wl_rfk_type type,
 5120                          enum btc_wl_rfk_state state)
 5121 {
 5122         struct rtw89_btc *btc = &rtwdev->btc;
 5123         struct rtw89_btc_cx *cx = &btc->cx;
 5124         struct rtw89_btc_wl_info *wl = &cx->wl;
 5125         bool result = BTC_WRFK_REJECT;
 5126 
 5127         wl->rfk_info.type = type;
 5128         wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
 5129         wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
 5130         wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
 5131 
 5132         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5133                     "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
 5134                     __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
 5135                     type, state);
 5136 
 5137         switch (state) {
 5138         case BTC_WRFK_START:
 5139                 result = _chk_wl_rfk_request(rtwdev);
 5140                 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
 5141 
 5142                 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
 5143 
 5144                 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
 5145                 break;
 5146         case BTC_WRFK_ONESHOT_START:
 5147         case BTC_WRFK_ONESHOT_STOP:
 5148                 if (wl->rfk_info.state == BTC_WRFK_STOP) {
 5149                         result = BTC_WRFK_REJECT;
 5150                 } else {
 5151                         result = BTC_WRFK_ALLOW;
 5152                         wl->rfk_info.state = state;
 5153                 }
 5154                 break;
 5155         case BTC_WRFK_STOP:
 5156                 result = BTC_WRFK_ALLOW;
 5157                 wl->rfk_info.state = BTC_WRFK_STOP;
 5158 
 5159                 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
 5160                 cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
 5161                 break;
 5162         default:
 5163                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5164                             "[BTC], %s() warning state=%d\n", __func__, state);
 5165                 break;
 5166         }
 5167 
 5168         if (result == BTC_WRFK_ALLOW) {
 5169                 if (wl->rfk_info.state == BTC_WRFK_START ||
 5170                     wl->rfk_info.state == BTC_WRFK_STOP)
 5171                         _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
 5172 
 5173                 if (wl->rfk_info.state == BTC_WRFK_START)
 5174                         ieee80211_queue_delayed_work(rtwdev->hw,
 5175                                                      &rtwdev->coex_rfk_chk_work,
 5176                                                      RTW89_COEX_RFK_CHK_WORK_PERIOD);
 5177         }
 5178 
 5179         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5180                     "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
 5181                     __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
 5182 
 5183         return result == BTC_WRFK_ALLOW;
 5184 }
 5185 
 5186 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
 5187                            enum btc_wl_rfk_type type,
 5188                            enum btc_wl_rfk_state state)
 5189 {
 5190         u8 band;
 5191         bool allow;
 5192         int ret;
 5193 
 5194         band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
 5195 
 5196         rtw89_debug(rtwdev, RTW89_DBG_RFK,
 5197                     "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
 5198                     band == RTW89_BAND_2G ? "2G" :
 5199                     band == RTW89_BAND_5G ? "5G" : "6G",
 5200                     !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
 5201                     type,
 5202                     FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
 5203                     state == BTC_WRFK_STOP ? "RFK_STOP" :
 5204                     state == BTC_WRFK_START ? "RFK_START" :
 5205                     state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
 5206                     "ONE-SHOT_STOP");
 5207 
 5208         if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
 5209                 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
 5210                 return;
 5211         }
 5212 
 5213         ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
 5214                                 rtwdev, phy_map, type, state);
 5215         if (ret) {
 5216                 rtw89_warn(rtwdev, "RFK notify timeout\n");
 5217                 rtwdev->is_bt_iqk_timeout = true;
 5218         }
 5219 }
 5220 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
 5221 
 5222 struct rtw89_btc_wl_sta_iter_data {
 5223         struct rtw89_dev *rtwdev;
 5224         u8 busy_all;
 5225         u8 dir_all;
 5226         u8 rssi_map_all;
 5227         bool is_sta_change;
 5228         bool is_traffic_change;
 5229 };
 5230 
 5231 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
 5232 {
 5233         struct rtw89_btc_wl_sta_iter_data *iter_data =
 5234                                 (struct rtw89_btc_wl_sta_iter_data *)data;
 5235         struct rtw89_dev *rtwdev = iter_data->rtwdev;
 5236         struct rtw89_btc *btc = &rtwdev->btc;
 5237         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 5238         struct rtw89_btc_wl_link_info *link_info = NULL;
 5239         struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
 5240         struct rtw89_traffic_stats *link_info_t = NULL;
 5241         struct rtw89_vif *rtwvif = rtwsta->rtwvif;
 5242         struct rtw89_traffic_stats *stats = &rtwvif->stats;
 5243         const struct rtw89_chip_info *chip = rtwdev->chip;
 5244         u32 last_tx_rate, last_rx_rate;
 5245         u16 last_tx_lvl, last_rx_lvl;
 5246         u8 port = rtwvif->port;
 5247         u8 rssi;
 5248         u8 busy = 0;
 5249         u8 dir = 0;
 5250         u8 rssi_map = 0;
 5251         u8 i = 0;
 5252         bool is_sta_change = false, is_traffic_change = false;
 5253 
 5254         rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
 5255         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
 5256 
 5257         link_info = &wl->link_info[port];
 5258         link_info->stat.traffic = rtwvif->stats;
 5259         link_info_t = &link_info->stat.traffic;
 5260 
 5261         if (link_info->connected == MLME_NO_LINK) {
 5262                 link_info->rx_rate_drop_cnt = 0;
 5263                 return;
 5264         }
 5265 
 5266         link_info->stat.rssi = rssi;
 5267         for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
 5268                 link_info->rssi_state[i] =
 5269                         _update_rssi_state(rtwdev,
 5270                                            link_info->rssi_state[i],
 5271                                            link_info->stat.rssi,
 5272                                            chip->wl_rssi_thres[i]);
 5273                 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
 5274                         rssi_map |= BIT(i);
 5275 
 5276                 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED &&
 5277                     BTC_RSSI_CHANGE(link_info->rssi_state[i]))
 5278                         is_sta_change = true;
 5279         }
 5280         iter_data->rssi_map_all |= rssi_map;
 5281 
 5282         last_tx_rate = link_info_t->tx_rate;
 5283         last_rx_rate = link_info_t->rx_rate;
 5284         last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
 5285         last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
 5286 
 5287         if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
 5288             stats->rx_tfc_lv != RTW89_TFC_IDLE)
 5289                 busy = 1;
 5290 
 5291         if (stats->tx_tfc_lv > stats->rx_tfc_lv)
 5292                 dir = RTW89_TFC_UL;
 5293         else
 5294                 dir = RTW89_TFC_DL;
 5295 
 5296         link_info = &wl->link_info[port];
 5297         if (link_info->busy != busy || link_info->dir != dir) {
 5298                 is_sta_change = true;
 5299                 link_info->busy = busy;
 5300                 link_info->dir = dir;
 5301         }
 5302 
 5303         iter_data->busy_all |= busy;
 5304         iter_data->dir_all |= BIT(dir);
 5305 
 5306         if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
 5307             last_rx_rate > RTW89_HW_RATE_CCK2 &&
 5308             link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
 5309                 link_info->rx_rate_drop_cnt++;
 5310 
 5311         if (last_tx_rate != rtwsta->ra_report.hw_rate ||
 5312             last_rx_rate != rtwsta->rx_hw_rate ||
 5313             last_tx_lvl != link_info_t->tx_tfc_lv ||
 5314             last_rx_lvl != link_info_t->rx_tfc_lv)
 5315                 is_traffic_change = true;
 5316 
 5317         link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
 5318         link_info_t->rx_rate = rtwsta->rx_hw_rate;
 5319 
 5320         wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv;
 5321         wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv;
 5322         wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
 5323         wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate;
 5324 
 5325         if (is_sta_change)
 5326                 iter_data->is_sta_change = true;
 5327 
 5328         if (is_traffic_change)
 5329                 iter_data->is_traffic_change = true;
 5330 }
 5331 
 5332 #define BTC_NHM_CHK_INTVL 20
 5333 
 5334 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
 5335 {
 5336         struct rtw89_btc *btc = &rtwdev->btc;
 5337         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 5338         struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
 5339         u8 i;
 5340 
 5341         ieee80211_iterate_stations_atomic(rtwdev->hw,
 5342                                           rtw89_btc_ntfy_wl_sta_iter,
 5343                                           &data);
 5344 
 5345         wl->rssi_level = 0;
 5346         btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
 5347         for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
 5348                 /* set RSSI level 4 ~ 0 if rssi bit map match */
 5349                 if (data.rssi_map_all & BIT(i - 1)) {
 5350                         wl->rssi_level = i;
 5351                         break;
 5352                 }
 5353         }
 5354 
 5355         rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
 5356                     __func__, !!wl->status.map.busy);
 5357 
 5358         _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
 5359 
 5360         if (data.is_traffic_change)
 5361                 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
 5362         if (data.is_sta_change) {
 5363                 wl->status.map.busy = data.busy_all;
 5364                 wl->status.map.traffic_dir = data.dir_all;
 5365                 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
 5366         } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
 5367                    btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
 5368                 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
 5369                         btc->dm.cnt_notify[BTC_NCNT_WL_STA];
 5370         } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
 5371                    btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
 5372                 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
 5373                 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
 5374         }
 5375 }
 5376 
 5377 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
 5378                           u32 len, u8 class, u8 func)
 5379 {
 5380         struct rtw89_btc *btc = &rtwdev->btc;
 5381         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 5382         u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
 5383 
 5384         len -= RTW89_C2H_HEADER_LEN;
 5385 
 5386         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5387                     "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
 5388                     __func__, len, class, func);
 5389 
 5390         if (class != BTFC_FW_EVENT)
 5391                 return;
 5392 
 5393         switch (func) {
 5394         case BTF_EVNT_RPT:
 5395         case BTF_EVNT_BUF_OVERFLOW:
 5396                 pfwinfo->event[func]++;
 5397                 /* Don't need rtw89_leave_ps_mode() */
 5398                 btc_fw_event(rtwdev, func, buf, len);
 5399                 break;
 5400         case BTF_EVNT_BT_INFO:
 5401                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5402                             "[BTC], handle C2H BT INFO with data %8ph\n", buf);
 5403                 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
 5404                 _update_bt_info(rtwdev, buf, len);
 5405                 break;
 5406         case BTF_EVNT_BT_SCBD:
 5407                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 5408                             "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
 5409                 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
 5410                 _update_bt_scbd(rtwdev, false);
 5411                 break;
 5412         case BTF_EVNT_BT_PSD:
 5413                 break;
 5414         case BTF_EVNT_BT_REG:
 5415                 btc->dbg.rb_done = true;
 5416                 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
 5417 
 5418                 break;
 5419         case BTF_EVNT_C2H_LOOPBACK:
 5420                 btc->dbg.rb_done = true;
 5421                 btc->dbg.rb_val = buf[0];
 5422                 break;
 5423         case BTF_EVNT_CX_RUNINFO:
 5424                 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
 5425                 break;
 5426         }
 5427 }
 5428 
 5429 #define BTC_CX_FW_OFFLOAD 0
 5430 
 5431 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 5432 {
 5433         const struct rtw89_chip_info *chip = rtwdev->chip;
 5434         struct rtw89_hal *hal = &rtwdev->hal;
 5435         struct rtw89_btc *btc = &rtwdev->btc;
 5436         struct rtw89_btc_dm *dm = &btc->dm;
 5437         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 5438         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 5439         u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
 5440 
 5441         if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
 5442                 return;
 5443 
 5444         dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
 5445 
 5446         seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
 5447                    chip->chip_id);
 5448 
 5449         ver_main = FIELD_GET(GENMASK(31, 24), chip->para_ver);
 5450         ver_sub = FIELD_GET(GENMASK(23, 16), chip->para_ver);
 5451         ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->para_ver);
 5452         id_branch = FIELD_GET(GENMASK(7, 0), chip->para_ver);
 5453         seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
 5454                    "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
 5455 
 5456         if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD)
 5457                 dm->error.map.offload_mismatch = true;
 5458         else
 5459                 dm->error.map.offload_mismatch = false;
 5460 
 5461         ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
 5462         ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
 5463         ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
 5464         id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
 5465         seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
 5466                    ver_main, ver_sub, ver_hotfix, id_branch);
 5467 
 5468         ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
 5469         ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
 5470         ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
 5471         seq_printf(m, "(%s, desired:%d.%d.%d), ",
 5472                    (wl->ver_info.fw_coex >= chip->wlcx_desired ?
 5473                    "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
 5474 
 5475         seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
 5476                    bt->ver_info.fw_coex,
 5477                    (bt->ver_info.fw_coex >= chip->btcx_desired ?
 5478                    "Match" : "Mismatch"), chip->btcx_desired);
 5479 
 5480         if (bt->enable.now && bt->ver_info.fw == 0)
 5481                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
 5482         else
 5483                 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
 5484 
 5485         ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
 5486         ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
 5487         ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
 5488         id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
 5489         seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
 5490                    "[sub_module]",
 5491                    ver_main, ver_sub, ver_hotfix, id_branch,
 5492                    bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
 5493 
 5494         seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
 5495                    "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type,
 5496                    btc->mdinfo.ant.isolation, btc->mdinfo.ant.num,
 5497                    (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ?
 5498                    "1Ant_Pos:S1, " : "1Ant_Pos:S0, ")));
 5499 
 5500         seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
 5501                    btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
 5502                    hal->rx_nss);
 5503 }
 5504 
 5505 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 5506 {
 5507         struct rtw89_btc *btc = &rtwdev->btc;
 5508         struct rtw89_btc_wl_link_info *plink = NULL;
 5509         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 5510         struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
 5511         struct rtw89_traffic_stats *t;
 5512         u8 i;
 5513 
 5514         if (rtwdev->dbcc_en) {
 5515                 seq_printf(m,
 5516                            " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
 5517                            "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
 5518                            wl_dinfo->scan_band[RTW89_PHY_0],
 5519                            wl_dinfo->real_band[RTW89_PHY_0]);
 5520                 seq_printf(m,
 5521                            "PHY1_band(op:%d/scan:%d/real:%d)\n",
 5522                            wl_dinfo->op_band[RTW89_PHY_1],
 5523                            wl_dinfo->scan_band[RTW89_PHY_1],
 5524                            wl_dinfo->real_band[RTW89_PHY_1]);
 5525         }
 5526 
 5527         for (i = 0; i < RTW89_PORT_NUM; i++) {
 5528                 plink = &btc->cx.wl.link_info[i];
 5529 
 5530                 if (!plink->active)
 5531                         continue;
 5532 
 5533                 seq_printf(m,
 5534                            " [port_%d]        : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
 5535                            plink->pid, (u32)plink->role, plink->phy,
 5536                            (u32)plink->connected, plink->client_cnt - 1,
 5537                            (u32)plink->mode, plink->ch, (u32)plink->bw);
 5538 
 5539                 if (plink->connected == MLME_NO_LINK)
 5540                         continue;
 5541 
 5542                 seq_printf(m,
 5543                            ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
 5544                            plink->mac_id, plink->tx_time, plink->tx_retry);
 5545 
 5546                 seq_printf(m,
 5547                            " [port_%d]        : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
 5548                            plink->pid, 110 - plink->stat.rssi,
 5549                            plink->stat.rssi, plink->busy,
 5550                            plink->dir == RTW89_TFC_UL ? "UL" : "DL");
 5551 
 5552                 t = &plink->stat.traffic;
 5553 
 5554                 seq_printf(m,
 5555                            "tx[rate:%d/busy_level:%d], ",
 5556                            (u32)t->tx_rate, t->tx_tfc_lv);
 5557 
 5558                 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
 5559                            (u32)t->rx_rate,
 5560                            t->rx_tfc_lv, plink->rx_rate_drop_cnt);
 5561         }
 5562 }
 5563 
 5564 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 5565 {
 5566         const struct rtw89_chip_info *chip = rtwdev->chip;
 5567         struct rtw89_btc *btc = &rtwdev->btc;
 5568         struct rtw89_btc_cx *cx = &btc->cx;
 5569         struct rtw89_btc_wl_info *wl = &cx->wl;
 5570         struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
 5571         struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
 5572         u8 mode;
 5573 
 5574         if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
 5575                 return;
 5576 
 5577         seq_puts(m, "========== [WL Status] ==========\n");
 5578 
 5579         if (chip->chip_id == RTL8852A)
 5580                 mode = wl_rinfo->link_mode;
 5581         else
 5582                 mode = wl_rinfo_v1->link_mode;
 5583 
 5584         seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
 5585 
 5586         seq_printf(m,
 5587                    "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
 5588                    wl->status.map.rf_off, wl->status.map.lps,
 5589                    wl->status.map.scan ? "Y" : "N",
 5590                    wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
 5591 
 5592         seq_printf(m,
 5593                    "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
 5594                    wl->status.map.connecting ? "Y" : "N",
 5595                    wl->status.map.roaming ?  "Y" : "N",
 5596                    wl->status.map._4way ? "Y" : "N",
 5597                    wl->status.map.init_ok ? "Y" : "N");
 5598 
 5599         _show_wl_role_info(rtwdev, m);
 5600 }
 5601 
 5602 enum btc_bt_a2dp_type {
 5603         BTC_A2DP_LEGACY = 0,
 5604         BTC_A2DP_TWS_SNIFF = 1,
 5605         BTC_A2DP_TWS_RELAY = 2,
 5606 };
 5607 
 5608 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 5609 {
 5610         struct rtw89_btc *btc = &rtwdev->btc;
 5611         struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
 5612         struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
 5613         struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
 5614         struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
 5615         struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
 5616 
 5617         if (hfp.exist) {
 5618                 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
 5619                            "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
 5620                            bt_linfo->sut_pwr_level[0],
 5621                            bt_linfo->golden_rx_shift[0]);
 5622         }
 5623 
 5624         if (hid.exist) {
 5625                 seq_printf(m,
 5626                            "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
 5627                            "[HID]",
 5628                            hid.type & BTC_HID_218 ? "2/18," : "",
 5629                            hid.type & BTC_HID_418 ? "4/18," : "",
 5630                            hid.type & BTC_HID_BLE ? "BLE," : "",
 5631                            hid.type & BTC_HID_RCU ? "RCU," : "",
 5632                            hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
 5633                            hid.pair_cnt, bt_linfo->sut_pwr_level[1],
 5634                            bt_linfo->golden_rx_shift[1]);
 5635         }
 5636 
 5637         if (a2dp.exist) {
 5638                 seq_printf(m,
 5639                            " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
 5640                            "[A2DP]",
 5641                            a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
 5642                             a2dp.bitpool, a2dp.flush_time);
 5643 
 5644                 seq_printf(m,
 5645                            "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
 5646                            a2dp.vendor_id, a2dp.device_name,
 5647                            bt_linfo->sut_pwr_level[2],
 5648                            bt_linfo->golden_rx_shift[2]);
 5649         }
 5650 
 5651         if (pan.exist) {
 5652                 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
 5653                            "[PAN]",
 5654                            bt_linfo->sut_pwr_level[3],
 5655                            bt_linfo->golden_rx_shift[3]);
 5656         }
 5657 }
 5658 
 5659 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 5660 {
 5661         struct rtw89_btc *btc = &rtwdev->btc;
 5662         struct rtw89_btc_cx *cx = &btc->cx;
 5663         struct rtw89_btc_bt_info *bt = &cx->bt;
 5664         struct rtw89_btc_wl_info *wl = &cx->wl;
 5665         struct rtw89_btc_module *module = &btc->mdinfo;
 5666         struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
 5667         u8 *afh = bt_linfo->afh_map;
 5668 
 5669         if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
 5670                 return;
 5671 
 5672         seq_puts(m, "========== [BT Status] ==========\n");
 5673 
 5674         seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
 5675                    "[status]", bt->enable.now ? "Y" : "N",
 5676                    bt->btg_type ? "Y" : "N",
 5677                    (bt->enable.now && (bt->btg_type != module->bt_pos) ?
 5678                    "(efuse-mismatch!!)" : ""),
 5679                    (bt_linfo->status.map.connect ? "Y" : "N"));
 5680 
 5681         seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
 5682                    bt->igno_wl ? "Y" : "N",
 5683                    bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
 5684 
 5685         seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
 5686                    "[profile]",
 5687                    (bt_linfo->profile_cnt.now == 0) ? "None," : "",
 5688                    bt_linfo->hfp_desc.exist ? "HFP," : "",
 5689                    bt_linfo->hid_desc.exist ? "HID," : "",
 5690                    bt_linfo->a2dp_desc.exist ?
 5691                    (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
 5692                    bt_linfo->pan_desc.exist ? "PAN," : "");
 5693 
 5694         seq_printf(m,
 5695                    "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
 5696                    bt_linfo->multi_link.now ? "Y" : "N",
 5697                    bt_linfo->slave_role ? "Slave" : "Master",
 5698                    bt_linfo->status.map.ble_connect ? "Y" : "N",
 5699                    bt_linfo->cqddr ? "Y" : "N",
 5700                    bt_linfo->a2dp_desc.active ? "Y" : "N",
 5701                    bt_linfo->pan_desc.active ? "Y" : "N");
 5702 
 5703         seq_printf(m,
 5704                    " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s",
 5705                    "[link]", bt_linfo->rssi - 100,
 5706                    bt_linfo->tx_3m ? 3 : 2,
 5707                    bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
 5708                    bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
 5709                    bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
 5710 
 5711         seq_printf(m,
 5712                    "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
 5713                    bt_linfo->relink.now ? " ReLink!!" : "",
 5714                    afh[0], afh[1], afh[2], afh[3], afh[4],
 5715                    afh[5], afh[6], afh[7], afh[8], afh[9]);
 5716 
 5717         seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
 5718                    wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
 5719 
 5720         seq_printf(m,
 5721                    " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
 5722                    "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
 5723                    cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
 5724                    cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
 5725 
 5726         seq_printf(m,
 5727                    "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
 5728                    cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
 5729                    cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
 5730                    cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
 5731 
 5732         _show_bt_profile_info(rtwdev, m);
 5733 
 5734         seq_printf(m,
 5735                    " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
 5736                    "[bt_info]", bt->raw_info[2], bt->raw_info[3],
 5737                    bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
 5738                    bt->raw_info[7],
 5739                    bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
 5740                    cx->cnt_bt[BTC_BCNT_INFOUPDATE],
 5741                    cx->cnt_bt[BTC_BCNT_INFOSAME]);
 5742 
 5743         seq_printf(m,
 5744                    " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n",
 5745                    "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
 5746                    cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
 5747                    cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
 5748 }
 5749 
 5750 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
 5751 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
 5752 #define CASE_BTC_POLICY_STR(e) \
 5753         case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
 5754 
 5755 static const char *steps_to_str(u16 step)
 5756 {
 5757         switch (step) {
 5758         CASE_BTC_RSN_STR(NONE);
 5759         CASE_BTC_RSN_STR(NTFY_INIT);
 5760         CASE_BTC_RSN_STR(NTFY_SWBAND);
 5761         CASE_BTC_RSN_STR(NTFY_WL_STA);
 5762         CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
 5763         CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
 5764         CASE_BTC_RSN_STR(NTFY_WL_RFK);
 5765         CASE_BTC_RSN_STR(UPDATE_BT_INFO);
 5766         CASE_BTC_RSN_STR(NTFY_SCAN_START);
 5767         CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
 5768         CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
 5769         CASE_BTC_RSN_STR(NTFY_POWEROFF);
 5770         CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
 5771         CASE_BTC_RSN_STR(CMD_SET_COEX);
 5772         CASE_BTC_RSN_STR(ACT1_WORK);
 5773         CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
 5774         CASE_BTC_RSN_STR(RFK_CHK_WORK);
 5775 
 5776         CASE_BTC_ACT_STR(NONE);
 5777         CASE_BTC_ACT_STR(WL_ONLY);
 5778         CASE_BTC_ACT_STR(WL_5G);
 5779         CASE_BTC_ACT_STR(WL_OTHER);
 5780         CASE_BTC_ACT_STR(WL_IDLE);
 5781         CASE_BTC_ACT_STR(WL_NC);
 5782         CASE_BTC_ACT_STR(WL_RFK);
 5783         CASE_BTC_ACT_STR(WL_INIT);
 5784         CASE_BTC_ACT_STR(WL_OFF);
 5785         CASE_BTC_ACT_STR(FREERUN);
 5786         CASE_BTC_ACT_STR(BT_WHQL);
 5787         CASE_BTC_ACT_STR(BT_RFK);
 5788         CASE_BTC_ACT_STR(BT_OFF);
 5789         CASE_BTC_ACT_STR(BT_IDLE);
 5790         CASE_BTC_ACT_STR(BT_HFP);
 5791         CASE_BTC_ACT_STR(BT_HID);
 5792         CASE_BTC_ACT_STR(BT_A2DP);
 5793         CASE_BTC_ACT_STR(BT_A2DPSINK);
 5794         CASE_BTC_ACT_STR(BT_PAN);
 5795         CASE_BTC_ACT_STR(BT_A2DP_HID);
 5796         CASE_BTC_ACT_STR(BT_A2DP_PAN);
 5797         CASE_BTC_ACT_STR(BT_PAN_HID);
 5798         CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
 5799         CASE_BTC_ACT_STR(WL_25G_MCC);
 5800         CASE_BTC_ACT_STR(WL_2G_MCC);
 5801         CASE_BTC_ACT_STR(WL_2G_SCC);
 5802         CASE_BTC_ACT_STR(WL_2G_AP);
 5803         CASE_BTC_ACT_STR(WL_2G_GO);
 5804         CASE_BTC_ACT_STR(WL_2G_GC);
 5805         CASE_BTC_ACT_STR(WL_2G_NAN);
 5806 
 5807         CASE_BTC_POLICY_STR(OFF_BT);
 5808         CASE_BTC_POLICY_STR(OFF_WL);
 5809         CASE_BTC_POLICY_STR(OFF_EQ0);
 5810         CASE_BTC_POLICY_STR(OFF_EQ1);
 5811         CASE_BTC_POLICY_STR(OFF_EQ2);
 5812         CASE_BTC_POLICY_STR(OFF_EQ3);
 5813         CASE_BTC_POLICY_STR(OFF_BWB0);
 5814         CASE_BTC_POLICY_STR(OFF_BWB1);
 5815         CASE_BTC_POLICY_STR(OFF_BWB2);
 5816         CASE_BTC_POLICY_STR(OFFB_BWB0);
 5817         CASE_BTC_POLICY_STR(OFFE_DEF);
 5818         CASE_BTC_POLICY_STR(OFFE_DEF2);
 5819         CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
 5820         CASE_BTC_POLICY_STR(OFFE_2GISOB);
 5821         CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
 5822         CASE_BTC_POLICY_STR(OFFE_WL);
 5823         CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
 5824         CASE_BTC_POLICY_STR(FIX_TD3030);
 5825         CASE_BTC_POLICY_STR(FIX_TD5050);
 5826         CASE_BTC_POLICY_STR(FIX_TD2030);
 5827         CASE_BTC_POLICY_STR(FIX_TD4010);
 5828         CASE_BTC_POLICY_STR(FIX_TD7010);
 5829         CASE_BTC_POLICY_STR(FIX_TD2060);
 5830         CASE_BTC_POLICY_STR(FIX_TD3060);
 5831         CASE_BTC_POLICY_STR(FIX_TD2080);
 5832         CASE_BTC_POLICY_STR(FIX_TDW1B1);
 5833         CASE_BTC_POLICY_STR(FIX_TD4020);
 5834         CASE_BTC_POLICY_STR(FIX_TD4010ISO);
 5835         CASE_BTC_POLICY_STR(PFIX_TD3030);
 5836         CASE_BTC_POLICY_STR(PFIX_TD5050);
 5837         CASE_BTC_POLICY_STR(PFIX_TD2030);
 5838         CASE_BTC_POLICY_STR(PFIX_TD2060);
 5839         CASE_BTC_POLICY_STR(PFIX_TD3070);
 5840         CASE_BTC_POLICY_STR(PFIX_TD2080);
 5841         CASE_BTC_POLICY_STR(PFIX_TDW1B1);
 5842         CASE_BTC_POLICY_STR(AUTO_TD50B1);
 5843         CASE_BTC_POLICY_STR(AUTO_TD60B1);
 5844         CASE_BTC_POLICY_STR(AUTO_TD20B1);
 5845         CASE_BTC_POLICY_STR(AUTO_TDW1B1);
 5846         CASE_BTC_POLICY_STR(PAUTO_TD50B1);
 5847         CASE_BTC_POLICY_STR(PAUTO_TD60B1);
 5848         CASE_BTC_POLICY_STR(PAUTO_TD20B1);
 5849         CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
 5850         CASE_BTC_POLICY_STR(AUTO2_TD3050);
 5851         CASE_BTC_POLICY_STR(AUTO2_TD3070);
 5852         CASE_BTC_POLICY_STR(AUTO2_TD5050);
 5853         CASE_BTC_POLICY_STR(AUTO2_TD6060);
 5854         CASE_BTC_POLICY_STR(AUTO2_TD2080);
 5855         CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
 5856         CASE_BTC_POLICY_STR(PAUTO2_TD3050);
 5857         CASE_BTC_POLICY_STR(PAUTO2_TD3070);
 5858         CASE_BTC_POLICY_STR(PAUTO2_TD5050);
 5859         CASE_BTC_POLICY_STR(PAUTO2_TD6060);
 5860         CASE_BTC_POLICY_STR(PAUTO2_TD2080);
 5861         CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
 5862         default:
 5863                 return "unknown step";
 5864         }
 5865 }
 5866 
 5867 static
 5868 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
 5869                        u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
 5870 {
 5871         u8 i;
 5872         u8 cur_index;
 5873 
 5874         for (i = 0; i < len ; i++) {
 5875                 if ((i % seg_len) == 0)
 5876                         seq_printf(m, " %-15s : ", prefix);
 5877                 cur_index = (start_idx + i) % ring_len;
 5878                 if (i % 3 == 0)
 5879                         seq_printf(m, "-> %-20s",
 5880                                    steps_to_str(*(data + cur_index)));
 5881                 else if (i % 3 == 1)
 5882                         seq_printf(m, "-> %-15s",
 5883                                    steps_to_str(*(data + cur_index)));
 5884                 else
 5885                         seq_printf(m, "-> %-13s",
 5886                                    steps_to_str(*(data + cur_index)));
 5887                 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
 5888                         seq_puts(m, "\n");
 5889         }
 5890 }
 5891 
 5892 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
 5893 {
 5894         struct rtw89_btc *btc = &rtwdev->btc;
 5895         struct rtw89_btc_dm *dm = &btc->dm;
 5896         u8 start_idx;
 5897         u8 len;
 5898 
 5899         len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
 5900         start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
 5901 
 5902         seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
 5903                           ARRAY_SIZE(dm->dm_step.step));
 5904 }
 5905 
 5906 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 5907 {
 5908         struct rtw89_btc *btc = &rtwdev->btc;
 5909         struct rtw89_btc_module *module = &btc->mdinfo;
 5910         struct rtw89_btc_dm *dm = &btc->dm;
 5911         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 5912         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 5913 
 5914         if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
 5915                 return;
 5916 
 5917         seq_printf(m, "========== [Mechanism Status %s] ==========\n",
 5918                    (btc->ctrl.manual ? "(Manual)" : "(Auto)"));
 5919 
 5920         seq_printf(m,
 5921                    " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n",
 5922                    "[status]",
 5923                    module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated",
 5924                    steps_to_str(dm->run_reason),
 5925                    steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
 5926                    FIELD_GET(GENMASK(7, 0), dm->set_ant_path),
 5927                    dm->cnt_dm[BTC_DCNT_RUN]);
 5928 
 5929         _show_dm_step(rtwdev, m);
 5930 
 5931         seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
 5932                    "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
 5933                    dm->freerun, btc->lps, dm->wl_mimo_ps);
 5934 
 5935         seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
 5936                    (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
 5937                    (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
 5938                     "" : "(Mismatch!!)"));
 5939 
 5940         if (dm->rf_trx_para.wl_tx_power == 0xff)
 5941                 seq_printf(m,
 5942                            " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
 5943                            "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
 5944 
 5945         else
 5946                 seq_printf(m,
 5947                            " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
 5948                            "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
 5949                            dm->rf_trx_para.wl_tx_power);
 5950 
 5951         seq_printf(m,
 5952                    "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
 5953                    dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
 5954                    dm->rf_trx_para.bt_rx_gain,
 5955                    (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
 5956 
 5957         seq_printf(m,
 5958                    " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU\n",
 5959                    "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
 5960                    dm->wl_tx_limit.tx_retry, btc->bt_req_len);
 5961 }
 5962 
 5963 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
 5964 {
 5965         struct rtw89_btc *btc = &rtwdev->btc;
 5966         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 5967         struct rtw89_btc_fbtc_cysta *pcysta = NULL;
 5968 
 5969         pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
 5970 
 5971         if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 &&
 5972             pcysta->except_cnt == 0 &&
 5973             !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
 5974                 return;
 5975 
 5976         seq_printf(m, " %-15s : ", "[error]");
 5977 
 5978         if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
 5979                 seq_printf(m,
 5980                            "overflow-cnt: %d, ",
 5981                            pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
 5982         }
 5983 
 5984         if (pfwinfo->len_mismch) {
 5985                 seq_printf(m,
 5986                            "len-mismatch: 0x%x, ",
 5987                            pfwinfo->len_mismch);
 5988         }
 5989 
 5990         if (pfwinfo->fver_mismch) {
 5991                 seq_printf(m,
 5992                            "fver-mismatch: 0x%x, ",
 5993                            pfwinfo->fver_mismch);
 5994         }
 5995 
 5996         /* cycle statistics exceptions */
 5997         if (pcysta->exception || pcysta->except_cnt) {
 5998                 seq_printf(m,
 5999                            "exception-type: 0x%x, exception-cnt = %d",
 6000                            pcysta->exception, pcysta->except_cnt);
 6001         }
 6002         seq_puts(m, "\n");
 6003 }
 6004 
 6005 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
 6006 {
 6007         struct rtw89_btc *btc = &rtwdev->btc;
 6008         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6009         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6010         struct rtw89_btc_fbtc_tdma *t = NULL;
 6011         struct rtw89_btc_fbtc_slot *s = NULL;
 6012         struct rtw89_btc_dm *dm = &btc->dm;
 6013         u8 i, cnt = 0;
 6014 
 6015         pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
 6016         if (!pcinfo->valid)
 6017                 return;
 6018 
 6019         t = &pfwinfo->rpt_fbtc_tdma.finfo;
 6020 
 6021         seq_printf(m,
 6022                    " %-15s : ", "[tdma_policy]");
 6023         seq_printf(m,
 6024                    "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
 6025                    (u32)t->type,
 6026                    t->rxflctrl, t->txpause);
 6027 
 6028         seq_printf(m,
 6029                    "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
 6030                    t->wtgle_n, t->leak_n, t->ext_ctrl);
 6031 
 6032         seq_printf(m,
 6033                    "policy_type:%d",
 6034                    (u32)btc->policy_type);
 6035 
 6036         s = pfwinfo->rpt_fbtc_slots.finfo.slot;
 6037 
 6038         for (i = 0; i < CXST_MAX; i++) {
 6039                 if (dm->update_slot_map == BIT(CXST_MAX) - 1)
 6040                         break;
 6041 
 6042                 if (!(dm->update_slot_map & BIT(i)))
 6043                         continue;
 6044 
 6045                 if (cnt % 6 == 0)
 6046                         seq_printf(m,
 6047                                    " %-15s : %d[%d/0x%x/%d]",
 6048                                    "[slot_policy]",
 6049                                    (u32)i,
 6050                                    s[i].dur, s[i].cxtbl, s[i].cxtype);
 6051                 else
 6052                         seq_printf(m,
 6053                                    ", %d[%d/0x%x/%d]",
 6054                                    (u32)i,
 6055                                    s[i].dur, s[i].cxtbl, s[i].cxtype);
 6056                 if (cnt % 6 == 5)
 6057                         seq_puts(m, "\n");
 6058                 cnt++;
 6059         }
 6060         seq_puts(m, "\n");
 6061 }
 6062 
 6063 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
 6064 {
 6065         struct rtw89_btc *btc = &rtwdev->btc;
 6066         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6067         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6068         struct rtw89_btc_fbtc_slots *pslots = NULL;
 6069         struct rtw89_btc_fbtc_slot s;
 6070         u8 i = 0;
 6071 
 6072         pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
 6073         if (!pcinfo->valid)
 6074                 return;
 6075 
 6076         pslots = &pfwinfo->rpt_fbtc_slots.finfo;
 6077 
 6078         for (i = 0; i < CXST_MAX; i++) {
 6079                 s = pslots->slot[i];
 6080                 if (i % 6 == 0)
 6081                         seq_printf(m,
 6082                                    " %-15s : %02d[%03d/0x%x/%d]",
 6083                                    "[slot_list]",
 6084                                    (u32)i,
 6085                                    s.dur, s.cxtbl, s.cxtype);
 6086                 else
 6087                         seq_printf(m,
 6088                                    ", %02d[%03d/0x%x/%d]",
 6089                                    (u32)i,
 6090                                    s.dur, s.cxtbl, s.cxtype);
 6091                 if (i % 6 == 5)
 6092                         seq_puts(m, "\n");
 6093         }
 6094 }
 6095 
 6096 static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m)
 6097 {
 6098         struct rtw89_btc *btc = &rtwdev->btc;
 6099         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6100         struct rtw89_btc_dm *dm = &btc->dm;
 6101         struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
 6102         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6103         struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
 6104         struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
 6105         union rtw89_btc_fbtc_rxflct r;
 6106         u8 i, cnt = 0, slot_pair;
 6107         u16 cycle, c_begin, c_end, store_index;
 6108 
 6109         pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
 6110         if (!pcinfo->valid)
 6111                 return;
 6112 
 6113         pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
 6114         rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
 6115         seq_printf(m,
 6116                    " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
 6117                    "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL],
 6118                    pcysta->bcn_cnt[CXBCN_ALL_OK],
 6119                    pcysta->bcn_cnt[CXBCN_BT_SLOT],
 6120                    pcysta->bcn_cnt[CXBCN_BT_OK]);
 6121 
 6122         for (i = 0; i < CXST_MAX; i++) {
 6123                 if (!pcysta->slot_cnt[i])
 6124                         continue;
 6125                 seq_printf(m,
 6126                            ", %d:%d", (u32)i, pcysta->slot_cnt[i]);
 6127         }
 6128 
 6129         if (dm->tdma_now.rxflctrl) {
 6130                 seq_printf(m,
 6131                            ", leak_rx:%d", pcysta->leakrx_cnt);
 6132         }
 6133 
 6134         if (pcysta->collision_cnt) {
 6135                 seq_printf(m,
 6136                            ", collision:%d", pcysta->collision_cnt);
 6137         }
 6138 
 6139         if (pcysta->skip_cnt) {
 6140                 seq_printf(m,
 6141                            ", skip:%d", pcysta->skip_cnt);
 6142         }
 6143         seq_puts(m, "\n");
 6144 
 6145         seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
 6146                    "[cycle_time]",
 6147                    pcysta->tavg_cycle[CXT_WL],
 6148                    pcysta->tavg_cycle[CXT_BT],
 6149                    pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000);
 6150         seq_printf(m,
 6151                    ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
 6152                    pcysta->tmax_cycle[CXT_WL],
 6153                    pcysta->tmax_cycle[CXT_BT],
 6154                    pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000);
 6155         seq_printf(m,
 6156                    ", maxdiff_t[wl:%d/bt:%d]\n",
 6157                    pcysta->tmaxdiff_cycle[CXT_WL],
 6158                    pcysta->tmaxdiff_cycle[CXT_BT]);
 6159 
 6160         if (pcysta->cycles == 0)
 6161                 return;
 6162 
 6163         /* 1 cycle record 1 wl-slot and 1 bt-slot */
 6164         slot_pair = BTC_CYCLE_SLOT_MAX / 2;
 6165 
 6166         if (pcysta->cycles <= slot_pair)
 6167                 c_begin = 1;
 6168         else
 6169                 c_begin = pcysta->cycles - slot_pair + 1;
 6170 
 6171         c_end = pcysta->cycles;
 6172 
 6173         for (cycle = c_begin; cycle <= c_end; cycle++) {
 6174                 cnt++;
 6175                 store_index = ((cycle - 1) % slot_pair) * 2;
 6176 
 6177                 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
 6178                         seq_printf(m,
 6179                                    " %-15s : ->b%02d->w%02d", "[cycle_step]",
 6180                                    pcysta->tslot_cycle[store_index],
 6181                                    pcysta->tslot_cycle[store_index + 1]);
 6182                 else
 6183                         seq_printf(m,
 6184                                    "->b%02d->w%02d",
 6185                                    pcysta->tslot_cycle[store_index],
 6186                                    pcysta->tslot_cycle[store_index + 1]);
 6187                 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
 6188                         seq_puts(m, "\n");
 6189         }
 6190 
 6191         if (a2dp->exist) {
 6192                 seq_printf(m,
 6193                            " %-15s : a2dp_ept:%d, a2dp_late:%d",
 6194                            "[a2dp_t_sta]",
 6195                            pcysta->a2dpept, pcysta->a2dpeptto);
 6196 
 6197                 seq_printf(m,
 6198                            ", avg_t:%d, max_t:%d",
 6199                            pcysta->tavg_a2dpept, pcysta->tmax_a2dpept);
 6200                 r.val = dm->tdma_now.rxflctrl;
 6201 
 6202                 if (r.type && r.tgln_n) {
 6203                         seq_printf(m,
 6204                                    ", cycle[PSTDMA:%d/TDMA:%d], ",
 6205                                    pcysta->cycles_a2dp[CXT_FLCTRL_ON],
 6206                                    pcysta->cycles_a2dp[CXT_FLCTRL_OFF]);
 6207 
 6208                         seq_printf(m,
 6209                                    "avg_t[PSTDMA:%d/TDMA:%d], ",
 6210                                    pcysta->tavg_a2dp[CXT_FLCTRL_ON],
 6211                                    pcysta->tavg_a2dp[CXT_FLCTRL_OFF]);
 6212 
 6213                         seq_printf(m,
 6214                                    "max_t[PSTDMA:%d/TDMA:%d]",
 6215                                    pcysta->tmax_a2dp[CXT_FLCTRL_ON],
 6216                                    pcysta->tmax_a2dp[CXT_FLCTRL_OFF]);
 6217                 }
 6218                 seq_puts(m, "\n");
 6219         }
 6220 }
 6221 
 6222 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
 6223 {
 6224         struct rtw89_btc *btc = &rtwdev->btc;
 6225         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6226         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6227         struct rtw89_btc_fbtc_cynullsta *ns = NULL;
 6228         u8 i = 0;
 6229 
 6230         if (!btc->dm.tdma_now.rxflctrl)
 6231                 return;
 6232 
 6233         pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
 6234         if (!pcinfo->valid)
 6235                 return;
 6236 
 6237         ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
 6238 
 6239         seq_printf(m, " %-15s : ", "[null_sta]");
 6240 
 6241         for (i = 0; i < 2; i++) {
 6242                 if (i != 0)
 6243                         seq_printf(m, ", null-%d", i);
 6244                 else
 6245                         seq_printf(m, "null-%d", i);
 6246                 seq_printf(m, "[ok:%d/", le32_to_cpu(ns->result[i][1]));
 6247                 seq_printf(m, "fail:%d/", le32_to_cpu(ns->result[i][0]));
 6248                 seq_printf(m, "on_time:%d/", le32_to_cpu(ns->result[i][2]));
 6249                 seq_printf(m, "retry:%d/", le32_to_cpu(ns->result[i][3]));
 6250                 seq_printf(m, "avg_t:%d.%03d/",
 6251                            le32_to_cpu(ns->avg_t[i]) / 1000,
 6252                            le32_to_cpu(ns->avg_t[i]) % 1000);
 6253                 seq_printf(m, "max_t:%d.%03d]",
 6254                            le32_to_cpu(ns->max_t[i]) / 1000,
 6255                            le32_to_cpu(ns->max_t[i]) % 1000);
 6256         }
 6257         seq_puts(m, "\n");
 6258 }
 6259 
 6260 static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m)
 6261 {
 6262         struct rtw89_btc *btc = &rtwdev->btc;
 6263         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6264         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6265         struct rtw89_btc_fbtc_steps *pstep = NULL;
 6266         u8 type, val, cnt = 0, state = 0;
 6267         bool outloop = false;
 6268         u16 i, diff_t, n_start = 0, n_stop = 0;
 6269         u16 pos_old, pos_new;
 6270 
 6271         pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
 6272         if (!pcinfo->valid)
 6273                 return;
 6274 
 6275         pstep = &pfwinfo->rpt_fbtc_step.finfo;
 6276         pos_old = le16_to_cpu(pstep->pos_old);
 6277         pos_new = le16_to_cpu(pstep->pos_new);
 6278 
 6279         if (pcinfo->req_fver != pstep->fver)
 6280                 return;
 6281 
 6282         /* store step info by using ring instead of FIFO*/
 6283         do {
 6284                 switch (state) {
 6285                 case 0:
 6286                         n_start = pos_old;
 6287                         if (pos_new >=  pos_old)
 6288                                 n_stop = pos_new;
 6289                         else
 6290                                 n_stop = btc->ctrl.trace_step - 1;
 6291 
 6292                         state = 1;
 6293                         break;
 6294                 case 1:
 6295                         for (i = n_start; i <= n_stop; i++) {
 6296                                 type = pstep->step[i].type;
 6297                                 val = pstep->step[i].val;
 6298                                 diff_t = le16_to_cpu(pstep->step[i].difft);
 6299 
 6300                                 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
 6301                                         continue;
 6302 
 6303                                 if (cnt % 10 == 0)
 6304                                         seq_printf(m, " %-15s : ", "[steps]");
 6305 
 6306                                 seq_printf(m, "-> %s(%02d)(%02d)",
 6307                                            (type == CXSTEP_SLOT ? "SLT" :
 6308                                             "EVT"), (u32)val, diff_t);
 6309                                 if (cnt % 10 == 9)
 6310                                         seq_puts(m, "\n");
 6311                                 cnt++;
 6312                         }
 6313 
 6314                         state = 2;
 6315                         break;
 6316                 case 2:
 6317                         if (pos_new <  pos_old && n_start != 0) {
 6318                                 n_start = 0;
 6319                                 n_stop = pos_new;
 6320                                 state = 1;
 6321                         } else {
 6322                                 outloop = true;
 6323                         }
 6324                         break;
 6325                 }
 6326         } while (!outloop);
 6327 }
 6328 
 6329 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
 6330 {
 6331         struct rtw89_btc *btc = &rtwdev->btc;
 6332 
 6333         if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
 6334                 return;
 6335 
 6336         _show_error(rtwdev, m);
 6337         _show_fbtc_tdma(rtwdev, m);
 6338         _show_fbtc_slots(rtwdev, m);
 6339         _show_fbtc_cysta(rtwdev, m);
 6340         _show_fbtc_nullsta(rtwdev, m);
 6341         _show_fbtc_step(rtwdev, m);
 6342 }
 6343 
 6344 static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
 6345 {
 6346         const struct rtw89_chip_info *chip = rtwdev->chip;
 6347         struct rtw89_btc *btc = &rtwdev->btc;
 6348         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6349         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6350         struct rtw89_btc_fbtc_mreg_val *pmreg = NULL;
 6351         struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
 6352         struct rtw89_btc_cx *cx = &btc->cx;
 6353         struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 6354         struct rtw89_btc_bt_info *bt = &btc->cx.bt;
 6355         struct rtw89_mac_ax_gnt gnt[2] = {0};
 6356         u8 i = 0, type = 0, cnt = 0;
 6357         u32 val, offset;
 6358 
 6359         if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
 6360                 return;
 6361 
 6362         seq_puts(m, "========== [HW Status] ==========\n");
 6363 
 6364         seq_printf(m,
 6365                    " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
 6366                    "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
 6367                    bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
 6368                    cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
 6369 
 6370         /* To avoid I/O if WL LPS or power-off  */
 6371         if (!wl->status.map.lps && !wl->status.map.rf_off) {
 6372                 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
 6373                 if (val & (B_AX_GNT_BT_RFC_S0_SW_VAL |
 6374                     B_AX_GNT_BT_BB_S0_SW_VAL))
 6375                         gnt[0].gnt_bt = true;
 6376                 if (val & (B_AX_GNT_BT_RFC_S0_SW_CTRL |
 6377                     B_AX_GNT_BT_BB_S0_SW_CTRL))
 6378                         gnt[0].gnt_bt_sw_en = true;
 6379                 if (val & (B_AX_GNT_WL_RFC_S0_SW_VAL |
 6380                     B_AX_GNT_WL_BB_S0_SW_VAL))
 6381                         gnt[0].gnt_wl = true;
 6382                 if (val & (B_AX_GNT_WL_RFC_S0_SW_CTRL |
 6383                     B_AX_GNT_WL_BB_S0_SW_CTRL))
 6384                         gnt[0].gnt_wl_sw_en = true;
 6385 
 6386                 if (val & (B_AX_GNT_BT_RFC_S1_SW_VAL |
 6387                     B_AX_GNT_BT_BB_S1_SW_VAL))
 6388                         gnt[1].gnt_bt = true;
 6389                 if (val & (B_AX_GNT_BT_RFC_S1_SW_CTRL |
 6390                     B_AX_GNT_BT_BB_S1_SW_CTRL))
 6391                         gnt[1].gnt_bt_sw_en = true;
 6392                 if (val & (B_AX_GNT_WL_RFC_S1_SW_VAL |
 6393                     B_AX_GNT_WL_BB_S1_SW_VAL))
 6394                         gnt[1].gnt_wl = true;
 6395                 if (val & (B_AX_GNT_WL_RFC_S1_SW_CTRL |
 6396                     B_AX_GNT_WL_BB_S1_SW_CTRL))
 6397                         gnt[1].gnt_wl_sw_en = true;
 6398 
 6399                 seq_printf(m,
 6400                            " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
 6401                            "[gnt_status]",
 6402                            (rtw89_mac_get_ctrl_path(rtwdev) ? "WL" : "BT"),
 6403                            (gnt[0].gnt_wl_sw_en ? "SW" : "HW"), gnt[0].gnt_wl,
 6404                            (gnt[0].gnt_bt_sw_en ? "SW" : "HW"), gnt[0].gnt_bt);
 6405 
 6406                 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
 6407                            (gnt[1].gnt_wl_sw_en ? "SW" : "HW"), gnt[1].gnt_wl,
 6408                            (gnt[1].gnt_bt_sw_en ? "SW" : "HW"), gnt[1].gnt_bt);
 6409         }
 6410 
 6411         pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
 6412         if (!pcinfo->valid) {
 6413                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 6414                             "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
 6415                             __func__);
 6416                 return;
 6417         }
 6418 
 6419         pmreg = &pfwinfo->rpt_fbtc_mregval.finfo;
 6420         rtw89_debug(rtwdev, RTW89_DBG_BTC,
 6421                     "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
 6422                     __func__, pmreg->reg_num);
 6423 
 6424         for (i = 0; i < pmreg->reg_num; i++) {
 6425                 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
 6426                 offset = le32_to_cpu(chip->mon_reg[i].offset);
 6427                 val = le32_to_cpu(pmreg->mreg_val[i]);
 6428 
 6429                 if (cnt % 6 == 0)
 6430                         seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
 6431                                    "[reg]", (u32)type, offset, val);
 6432                 else
 6433                         seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
 6434                                    offset, val);
 6435                 if (cnt % 6 == 5)
 6436                         seq_puts(m, "\n");
 6437                 cnt++;
 6438         }
 6439 
 6440         pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
 6441         if (!pcinfo->valid) {
 6442                 rtw89_debug(rtwdev, RTW89_DBG_BTC,
 6443                             "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
 6444                             __func__);
 6445                 return;
 6446         }
 6447 
 6448         gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
 6449         if (!gdbg->en_map)
 6450                 return;
 6451 
 6452         seq_printf(m, " %-15s : enable_map:0x%08x",
 6453                    "[gpio_dbg]", gdbg->en_map);
 6454 
 6455         for (i = 0; i < BTC_DBG_MAX1; i++) {
 6456                 if (!(gdbg->en_map & BIT(i)))
 6457                         continue;
 6458                 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]);
 6459         }
 6460         seq_puts(m, "\n");
 6461 }
 6462 
 6463 static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m)
 6464 {
 6465         struct rtw89_btc *btc = &rtwdev->btc;
 6466         struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
 6467         struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
 6468         struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL;
 6469         struct rtw89_btc_cx *cx = &btc->cx;
 6470         struct rtw89_btc_dm *dm = &btc->dm;
 6471         struct rtw89_btc_wl_info *wl = &cx->wl;
 6472         struct rtw89_btc_bt_info *bt = &cx->bt;
 6473         u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
 6474         u8 i;
 6475 
 6476         if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
 6477                 return;
 6478 
 6479         seq_puts(m, "========== [Statistics] ==========\n");
 6480 
 6481         pcinfo = &pfwinfo->rpt_ctrl.cinfo;
 6482         if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
 6483                 prptctrl = &pfwinfo->rpt_ctrl.finfo;
 6484 
 6485                 seq_printf(m,
 6486                            " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
 6487                            "[summary]", pfwinfo->cnt_h2c,
 6488                            pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
 6489                            pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
 6490 
 6491                 seq_printf(m,
 6492                            "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
 6493                            pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
 6494                            prptctrl->rpt_enable, dm->error.val);
 6495 
 6496                 if (dm->error.map.wl_fw_hang)
 6497                         seq_puts(m, " (WL FW Hang!!)");
 6498                 seq_puts(m, "\n");
 6499                 seq_printf(m,
 6500                            " %-15s : send_ok:%d, send_fail:%d, recv:%d",
 6501                            "[mailbox]", prptctrl->mb_send_ok_cnt,
 6502                            prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
 6503 
 6504                 seq_printf(m,
 6505                            "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
 6506                            prptctrl->mb_a2dp_empty_cnt,
 6507                            prptctrl->mb_a2dp_flct_cnt,
 6508                            prptctrl->mb_a2dp_full_cnt);
 6509 
 6510                 seq_printf(m,
 6511                            " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
 6512                            "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
 6513                            cx->cnt_wl[BTC_WCNT_RFK_GO],
 6514                            cx->cnt_wl[BTC_WCNT_RFK_REJECT],
 6515                            cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
 6516 
 6517                 seq_printf(m,
 6518                            ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
 6519                            prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
 6520                            prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
 6521                            prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
 6522                            prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
 6523                            prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
 6524 
 6525                 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
 6526                         bt->rfk_info.map.timeout = 1;
 6527                 else
 6528                         bt->rfk_info.map.timeout = 0;
 6529 
 6530                 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
 6531         } else {
 6532                 seq_printf(m,
 6533                            " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
 6534                            "[summary]", pfwinfo->cnt_h2c,
 6535                            pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
 6536                            pfwinfo->event[BTF_EVNT_RPT],
 6537                            btc->fwinfo.rpt_en_map);
 6538                 seq_puts(m, " (WL FW report invalid!!)\n");
 6539         }
 6540 
 6541         for (i = 0; i < BTC_NCNT_NUM; i++)
 6542                 cnt_sum += dm->cnt_notify[i];
 6543 
 6544         seq_printf(m,
 6545                    " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
 6546                    "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
 6547                    cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
 6548 
 6549         seq_printf(m,
 6550                    "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
 6551                    cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
 6552                    cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
 6553                    cnt[BTC_NCNT_WL_STA]);
 6554 
 6555         seq_printf(m,
 6556                    " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
 6557                    "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
 6558                    cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
 6559                    cnt[BTC_NCNT_SPECIAL_PACKET]);
 6560 
 6561         seq_printf(m,
 6562                    "timer=%d, control=%d, customerize=%d\n",
 6563                    cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
 6564                    cnt[BTC_NCNT_CUSTOMERIZE]);
 6565 }
 6566 
 6567 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 6568 {
 6569         struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
 6570         struct rtw89_btc *btc = &rtwdev->btc;
 6571         struct rtw89_btc_cx *cx = &btc->cx;
 6572         struct rtw89_btc_bt_info *bt = &cx->bt;
 6573 
 6574         seq_puts(m, "=========================================\n");
 6575         seq_printf(m, "WL FW / BT FW            %d.%d.%d.%d / NA\n",
 6576                    fw_suit->major_ver, fw_suit->minor_ver,
 6577                    fw_suit->sub_ver, fw_suit->sub_idex);
 6578         seq_printf(m, "manual                   %d\n", btc->ctrl.manual);
 6579 
 6580         seq_puts(m, "=========================================\n");
 6581 
 6582         seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
 6583                    "[bt_info]",
 6584                    bt->raw_info[2], bt->raw_info[3],
 6585                    bt->raw_info[4], bt->raw_info[5],
 6586                    bt->raw_info[6], bt->raw_info[7],
 6587                    bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
 6588                    cx->cnt_bt[BTC_BCNT_INFOUPDATE],
 6589                    cx->cnt_bt[BTC_BCNT_INFOSAME]);
 6590 
 6591         seq_puts(m, "\n=========================================\n");
 6592 
 6593         _show_cx_info(rtwdev, m);
 6594         _show_wl_info(rtwdev, m);
 6595         _show_bt_info(rtwdev, m);
 6596         _show_dm_info(rtwdev, m);
 6597         _show_fw_dm_msg(rtwdev, m);
 6598         _show_mreg(rtwdev, m);
 6599         _show_summary(rtwdev, m);
 6600 }

Cache object: bafaa4522fc3eeee1ff25debe91e4ed5


[ 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.