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 "phy.h" 10 #include "ps.h" 11 #include "reg.h" 12 13 #define RTW89_COEX_VERSION 0x07000113 14 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/ 15 16 enum btc_fbtc_tdma_template { 17 CXTD_OFF = 0x0, 18 CXTD_OFF_B2, 19 CXTD_OFF_EXT, 20 CXTD_FIX, 21 CXTD_PFIX, 22 CXTD_AUTO, 23 CXTD_PAUTO, 24 CXTD_AUTO2, 25 CXTD_PAUTO2, 26 CXTD_MAX, 27 }; 28 29 enum btc_fbtc_tdma_type { 30 CXTDMA_OFF = 0x0, 31 CXTDMA_FIX = 0x1, 32 CXTDMA_AUTO = 0x2, 33 CXTDMA_AUTO2 = 0x3, 34 CXTDMA_MAX 35 }; 36 37 enum btc_fbtc_tdma_rx_flow_ctrl { 38 CXFLC_OFF = 0x0, 39 CXFLC_NULLP = 0x1, 40 CXFLC_QOSNULL = 0x2, 41 CXFLC_CTS = 0x3, 42 CXFLC_MAX 43 }; 44 45 enum btc_fbtc_tdma_wlan_tx_pause { 46 CXTPS_OFF = 0x0, /* no wl tx pause*/ 47 CXTPS_ON = 0x1, 48 CXTPS_MAX 49 }; 50 51 enum btc_mlme_state { 52 MLME_NO_LINK, 53 MLME_LINKING, 54 MLME_LINKED, 55 }; 56 57 #define FCXONESLOT_VER 1 58 struct btc_fbtc_1slot { 59 u8 fver; 60 u8 sid; /* slot id */ 61 struct rtw89_btc_fbtc_slot slot; 62 } __packed; 63 64 static const struct rtw89_btc_fbtc_tdma t_def[] = { 65 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 66 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0}, 67 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0}, 68 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 69 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 70 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 71 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 72 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 73 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0} 74 }; 75 76 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \ 77 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \ 78 .cxtype = cpu_to_le16(__cxtype),} 79 80 static const struct rtw89_btc_fbtc_slot s_def[] = { 81 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX), 82 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO), 83 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO), 84 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 85 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 86 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX), 87 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX), 88 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 89 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX), 90 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO), 91 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX), 92 [CXST_E2G] = __DEF_FBTC_SLOT(0, 0xea5a5a5a, SLOT_MIX), 93 [CXST_E5G] = __DEF_FBTC_SLOT(0, 0xffffffff, SLOT_ISO), 94 [CXST_EBT] = __DEF_FBTC_SLOT(0, 0xe5555555, SLOT_MIX), 95 [CXST_ENULL] = __DEF_FBTC_SLOT(0, 0xaaaaaaaa, SLOT_ISO), 96 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), 97 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), 98 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), 99 }; 100 101 static const u32 cxtbl[] = { 102 0xffffffff, /* 0 */ 103 0xaaaaaaaa, /* 1 */ 104 0xe5555555, /* 2 */ 105 0xee555555, /* 3 */ 106 0xd5555555, /* 4 */ 107 0x5a5a5a5a, /* 5 */ 108 0xfa5a5a5a, /* 6 */ 109 0xda5a5a5a, /* 7 */ 110 0xea5a5a5a, /* 8 */ 111 0x6a5a5aaa, /* 9 */ 112 0x6a5a6a5a, /* 10 */ 113 0x6a5a6aaa, /* 11 */ 114 0x6afa5afa, /* 12 */ 115 0xaaaa5aaa, /* 13 */ 116 0xaaffffaa, /* 14 */ 117 0xaa5555aa, /* 15 */ 118 0xfafafafa, /* 16 */ 119 0xffffddff, /* 17 */ 120 0xdaffdaff, /* 18 */ 121 0xfafadafa, /* 19 */ 122 0xea6a6a6a, /* 20 */ 123 0xea55556a, /* 21 */ 124 0xaafafafa, /* 22 */ 125 0xfafaaafa, /* 23 */ 126 0xfafffaff, /* 24 */ 127 0xea6a5a5a, /* 25 */ 128 }; 129 130 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { 131 /* firmware version must be in decreasing order for each chip */ 132 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), 133 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 134 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 135 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 136 .fwlrole = 2, .frptmap = 7, .fcxctrl = 7, .fcxinit = 7, 137 .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, 138 }, 139 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), 140 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 141 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 142 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 143 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 144 .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, 145 }, 146 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), 147 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 148 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 149 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 150 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 151 .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, 152 }, 153 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), 154 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 155 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 156 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 157 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 158 .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, 159 }, 160 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), 161 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 162 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 163 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 164 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 165 .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, 166 }, 167 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), 168 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 169 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 170 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 171 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 172 .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, 173 }, 174 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), 175 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, 176 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 177 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 178 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 179 .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, 180 }, 181 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), 182 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 183 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 184 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 185 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, 186 .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, 187 }, 188 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), 189 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 190 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 191 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 192 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 193 .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, 194 }, 195 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), 196 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 197 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 198 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 199 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 200 .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, 201 }, 202 203 /* keep it to be the last as default entry */ 204 {0, RTW89_FW_VER_CODE(0, 0, 0, 0), 205 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 206 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 207 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 208 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 209 .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, 210 }, 211 }; 212 213 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1) 214 215 struct rtw89_btc_btf_tlv { 216 u8 type; 217 u8 len; 218 u8 val[]; 219 } __packed; 220 221 enum btc_btf_set_report_en { 222 RPT_EN_TDMA, 223 RPT_EN_CYCLE, 224 RPT_EN_MREG, 225 RPT_EN_BT_VER_INFO, 226 RPT_EN_BT_SCAN_INFO, 227 RPT_EN_BT_DEVICE_INFO, 228 RPT_EN_BT_AFH_MAP, 229 RPT_EN_BT_AFH_MAP_LE, 230 RPT_EN_FW_STEP_INFO, 231 RPT_EN_TEST, 232 RPT_EN_WL_ALL, 233 RPT_EN_BT_ALL, 234 RPT_EN_ALL, 235 RPT_EN_MONITER, 236 }; 237 238 #define BTF_SET_REPORT_VER 1 239 struct rtw89_btc_btf_set_report { 240 u8 fver; 241 __le32 enable; 242 __le32 para; 243 } __packed; 244 245 #define BTF_SET_SLOT_TABLE_VER 1 246 struct rtw89_btc_btf_set_slot_table { 247 u8 fver; 248 u8 tbl_num; 249 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num); 250 } __packed; 251 252 struct rtw89_btc_btf_set_mon_reg { 253 u8 fver; 254 u8 reg_num; 255 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num); 256 } __packed; 257 258 struct _wl_rinfo_now { 259 u8 link_mode; 260 u32 dbcc_2g_phy: 2; 261 }; 262 263 enum btc_btf_set_cx_policy { 264 CXPOLICY_TDMA = 0x0, 265 CXPOLICY_SLOT = 0x1, 266 CXPOLICY_TYPE = 0x2, 267 CXPOLICY_MAX, 268 }; 269 270 enum btc_b2w_scoreboard { 271 BTC_BSCB_ACT = BIT(0), 272 BTC_BSCB_ON = BIT(1), 273 BTC_BSCB_WHQL = BIT(2), 274 BTC_BSCB_BT_S1 = BIT(3), 275 BTC_BSCB_A2DP_ACT = BIT(4), 276 BTC_BSCB_RFK_RUN = BIT(5), 277 BTC_BSCB_RFK_REQ = BIT(6), 278 BTC_BSCB_LPS = BIT(7), 279 BTC_BSCB_BT_LNAB0 = BIT(8), 280 BTC_BSCB_BT_LNAB1 = BIT(10), 281 BTC_BSCB_WLRFK = BIT(11), 282 BTC_BSCB_BT_HILNA = BIT(13), 283 BTC_BSCB_BT_CONNECT = BIT(16), 284 BTC_BSCB_PATCH_CODE = BIT(30), 285 BTC_BSCB_ALL = GENMASK(30, 0), 286 }; 287 288 enum btc_phymap { 289 BTC_PHY_0 = BIT(0), 290 BTC_PHY_1 = BIT(1), 291 BTC_PHY_ALL = BIT(0) | BIT(1), 292 }; 293 294 enum btc_cx_state_map { 295 BTC_WIDLE = 0, 296 BTC_WBUSY_BNOSCAN, 297 BTC_WBUSY_BSCAN, 298 BTC_WSCAN_BNOSCAN, 299 BTC_WSCAN_BSCAN, 300 BTC_WLINKING 301 }; 302 303 enum btc_ant_phase { 304 BTC_ANT_WPOWERON = 0, 305 BTC_ANT_WINIT, 306 BTC_ANT_WONLY, 307 BTC_ANT_WOFF, 308 BTC_ANT_W2G, 309 BTC_ANT_W5G, 310 BTC_ANT_W25G, 311 BTC_ANT_FREERUN, 312 BTC_ANT_WRFK, 313 BTC_ANT_BRFK, 314 BTC_ANT_MAX 315 }; 316 317 enum btc_plt { 318 BTC_PLT_NONE = 0, 319 BTC_PLT_LTE_RX = BIT(0), 320 BTC_PLT_GNT_BT_TX = BIT(1), 321 BTC_PLT_GNT_BT_RX = BIT(2), 322 BTC_PLT_GNT_WL = BIT(3), 323 BTC_PLT_BT = BIT(1) | BIT(2), 324 BTC_PLT_ALL = 0xf 325 }; 326 327 enum btc_cx_poicy_main_type { 328 BTC_CXP_OFF = 0, 329 BTC_CXP_OFFB, 330 BTC_CXP_OFFE, 331 BTC_CXP_FIX, 332 BTC_CXP_PFIX, 333 BTC_CXP_AUTO, 334 BTC_CXP_PAUTO, 335 BTC_CXP_AUTO2, 336 BTC_CXP_PAUTO2, 337 BTC_CXP_MANUAL, 338 BTC_CXP_USERDEF0, 339 BTC_CXP_MAIN_MAX 340 }; 341 342 enum btc_cx_poicy_type { 343 /* TDMA off + pri: BT > WL */ 344 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0, 345 346 /* TDMA off + pri: WL > BT */ 347 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1, 348 349 /* TDMA off + pri: BT = WL */ 350 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2, 351 352 /* TDMA off + pri: BT = WL > BT_Lo */ 353 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3, 354 355 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */ 356 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4, 357 358 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 359 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5, 360 361 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 362 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6, 363 364 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 365 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7, 366 367 /* TDMA off + pri: BT_Hi > WL > BT_Lo */ 368 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8, 369 370 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 371 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9, 372 373 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 374 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10, 375 376 /* TDMA off + pri: WL_Hi-Tx = BT */ 377 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11, 378 379 /* TDMA off + pri: WL > BT, Block-BT*/ 380 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12, 381 382 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/ 383 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0, 384 385 /* TDMA off + Ext-Ctrl + pri: default */ 386 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0, 387 388 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 389 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1, 390 391 /* TDMA off + Ext-Ctrl + pri: default */ 392 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2, 393 394 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 395 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3, 396 397 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */ 398 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4, 399 400 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */ 401 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5, 402 403 /* TDMA off + Ext-Ctrl + pri: default */ 404 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6, 405 406 /* TDMA Fix slot-0: W1:B1 = 30:30 */ 407 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0, 408 409 /* TDMA Fix slot-1: W1:B1 = 50:50 */ 410 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1, 411 412 /* TDMA Fix slot-2: W1:B1 = 20:30 */ 413 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2, 414 415 /* TDMA Fix slot-3: W1:B1 = 40:10 */ 416 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3, 417 418 /* TDMA Fix slot-4: W1:B1 = 70:10 */ 419 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4, 420 421 /* TDMA Fix slot-5: W1:B1 = 20:60 */ 422 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5, 423 424 /* TDMA Fix slot-6: W1:B1 = 30:60 */ 425 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6, 426 427 /* TDMA Fix slot-7: W1:B1 = 20:80 */ 428 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7, 429 430 /* TDMA Fix slot-8: W1:B1 = user-define */ 431 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8, 432 433 /* TDMA Fix slot-9: W1:B1 = 40:10 */ 434 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9, 435 436 /* TDMA Fix slot-10: W1:B1 = 40:10 */ 437 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10, 438 439 /* TDMA Fix slot-11: W1:B1 = 40:10 */ 440 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11, 441 442 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */ 443 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0, 444 445 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */ 446 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1, 447 448 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */ 449 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2, 450 451 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */ 452 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3, 453 454 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */ 455 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4, 456 457 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */ 458 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5, 459 460 /* PS-TDMA Fix slot-6: W1:B1 = user-define */ 461 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6, 462 463 /* TDMA Auto slot-0: W1:B1 = 50:200 */ 464 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0, 465 466 /* TDMA Auto slot-1: W1:B1 = 60:200 */ 467 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1, 468 469 /* TDMA Auto slot-2: W1:B1 = 20:200 */ 470 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2, 471 472 /* TDMA Auto slot-3: W1:B1 = user-define */ 473 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3, 474 475 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */ 476 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0, 477 478 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */ 479 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1, 480 481 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */ 482 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2, 483 484 /* PS-TDMA Auto slot-3: W1:B1 = user-define */ 485 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3, 486 487 /* TDMA Auto slot2-0: W1:B4 = 30:50 */ 488 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0, 489 490 /* TDMA Auto slot2-1: W1:B4 = 30:70 */ 491 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1, 492 493 /* TDMA Auto slot2-2: W1:B4 = 50:50 */ 494 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2, 495 496 /* TDMA Auto slot2-3: W1:B4 = 60:60 */ 497 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3, 498 499 /* TDMA Auto slot2-4: W1:B4 = 20:80 */ 500 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4, 501 502 /* TDMA Auto slot2-5: W1:B4 = user-define */ 503 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5, 504 505 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */ 506 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0, 507 508 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */ 509 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1, 510 511 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */ 512 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2, 513 514 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */ 515 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3, 516 517 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */ 518 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4, 519 520 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */ 521 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5, 522 523 BTC_CXP_MAX = 0xffff 524 }; 525 526 enum btc_wl_rfk_result { 527 BTC_WRFK_REJECT = 0, 528 BTC_WRFK_ALLOW = 1, 529 }; 530 531 enum btc_coex_info_map_en { 532 BTC_COEX_INFO_CX = BIT(0), 533 BTC_COEX_INFO_WL = BIT(1), 534 BTC_COEX_INFO_BT = BIT(2), 535 BTC_COEX_INFO_DM = BIT(3), 536 BTC_COEX_INFO_MREG = BIT(4), 537 BTC_COEX_INFO_SUMMARY = BIT(5), 538 BTC_COEX_INFO_ALL = GENMASK(7, 0), 539 }; 540 541 #define BTC_CXP_MASK GENMASK(15, 8) 542 543 enum btc_w2b_scoreboard { 544 BTC_WSCB_ACTIVE = BIT(0), 545 BTC_WSCB_ON = BIT(1), 546 BTC_WSCB_SCAN = BIT(2), 547 BTC_WSCB_UNDERTEST = BIT(3), 548 BTC_WSCB_RXGAIN = BIT(4), 549 BTC_WSCB_WLBUSY = BIT(7), 550 BTC_WSCB_EXTFEM = BIT(8), 551 BTC_WSCB_TDMA = BIT(9), 552 BTC_WSCB_FIX2M = BIT(10), 553 BTC_WSCB_WLRFK = BIT(11), 554 BTC_WSCB_RXSCAN_PRI = BIT(12), 555 BTC_WSCB_BT_HILNA = BIT(13), 556 BTC_WSCB_BTLOG = BIT(14), 557 BTC_WSCB_ALL = GENMASK(23, 0), 558 }; 559 560 enum btc_wl_link_mode { 561 BTC_WLINK_NOLINK = 0x0, 562 BTC_WLINK_2G_STA, 563 BTC_WLINK_2G_AP, 564 BTC_WLINK_2G_GO, 565 BTC_WLINK_2G_GC, 566 BTC_WLINK_2G_SCC, 567 BTC_WLINK_2G_MCC, 568 BTC_WLINK_25G_MCC, 569 BTC_WLINK_25G_DBCC, 570 BTC_WLINK_5G, 571 BTC_WLINK_2G_NAN, 572 BTC_WLINK_OTHER, 573 BTC_WLINK_MAX 574 }; 575 576 enum btc_wl_mrole_type { 577 BTC_WLMROLE_NONE = 0x0, 578 BTC_WLMROLE_STA_GC, 579 BTC_WLMROLE_STA_GC_NOA, 580 BTC_WLMROLE_STA_GO, 581 BTC_WLMROLE_STA_GO_NOA, 582 BTC_WLMROLE_STA_STA, 583 BTC_WLMROLE_MAX 584 }; 585 586 enum btc_bt_hid_type { 587 BTC_HID_218 = BIT(0), 588 BTC_HID_418 = BIT(1), 589 BTC_HID_BLE = BIT(2), 590 BTC_HID_RCU = BIT(3), 591 BTC_HID_RCU_VOICE = BIT(4), 592 BTC_HID_OTHER_LEGACY = BIT(5) 593 }; 594 595 enum btc_reset_module { 596 BTC_RESET_CX = BIT(0), 597 BTC_RESET_DM = BIT(1), 598 BTC_RESET_CTRL = BIT(2), 599 BTC_RESET_CXDM = BIT(0) | BIT(1), 600 BTC_RESET_BTINFO = BIT(3), 601 BTC_RESET_MDINFO = BIT(4), 602 BTC_RESET_ALL = GENMASK(7, 0), 603 }; 604 605 enum btc_gnt_state { 606 BTC_GNT_HW = 0, 607 BTC_GNT_SW_LO, 608 BTC_GNT_SW_HI, 609 BTC_GNT_MAX 610 }; 611 612 enum btc_ctr_path { 613 BTC_CTRL_BY_BT = 0, 614 BTC_CTRL_BY_WL 615 }; 616 617 enum btc_wl_max_tx_time { 618 BTC_MAX_TX_TIME_L1 = 500, 619 BTC_MAX_TX_TIME_L2 = 1000, 620 BTC_MAX_TX_TIME_L3 = 2000, 621 BTC_MAX_TX_TIME_DEF = 5280 622 }; 623 624 enum btc_wl_max_tx_retry { 625 BTC_MAX_TX_RETRY_L1 = 7, 626 BTC_MAX_TX_RETRY_L2 = 15, 627 BTC_MAX_TX_RETRY_DEF = 31, 628 }; 629 630 enum btc_reason_and_action { 631 BTC_RSN_NONE, 632 BTC_RSN_NTFY_INIT, 633 BTC_RSN_NTFY_SWBAND, 634 BTC_RSN_NTFY_WL_STA, 635 BTC_RSN_NTFY_RADIO_STATE, 636 BTC_RSN_UPDATE_BT_SCBD, 637 BTC_RSN_NTFY_WL_RFK, 638 BTC_RSN_UPDATE_BT_INFO, 639 BTC_RSN_NTFY_SCAN_START, 640 BTC_RSN_NTFY_SCAN_FINISH, 641 BTC_RSN_NTFY_SPECIFIC_PACKET, 642 BTC_RSN_NTFY_POWEROFF, 643 BTC_RSN_NTFY_ROLE_INFO, 644 BTC_RSN_CMD_SET_COEX, 645 BTC_RSN_ACT1_WORK, 646 BTC_RSN_BT_DEVINFO_WORK, 647 BTC_RSN_RFK_CHK_WORK, 648 BTC_RSN_NUM, 649 BTC_ACT_NONE = 100, 650 BTC_ACT_WL_ONLY, 651 BTC_ACT_WL_5G, 652 BTC_ACT_WL_OTHER, 653 BTC_ACT_WL_IDLE, 654 BTC_ACT_WL_NC, 655 BTC_ACT_WL_RFK, 656 BTC_ACT_WL_INIT, 657 BTC_ACT_WL_OFF, 658 BTC_ACT_FREERUN, 659 BTC_ACT_BT_WHQL, 660 BTC_ACT_BT_RFK, 661 BTC_ACT_BT_OFF, 662 BTC_ACT_BT_IDLE, 663 BTC_ACT_BT_HFP, 664 BTC_ACT_BT_HID, 665 BTC_ACT_BT_A2DP, 666 BTC_ACT_BT_A2DPSINK, 667 BTC_ACT_BT_PAN, 668 BTC_ACT_BT_A2DP_HID, 669 BTC_ACT_BT_A2DP_PAN, 670 BTC_ACT_BT_PAN_HID, 671 BTC_ACT_BT_A2DP_PAN_HID, 672 BTC_ACT_WL_25G_MCC, 673 BTC_ACT_WL_2G_MCC, 674 BTC_ACT_WL_2G_SCC, 675 BTC_ACT_WL_2G_AP, 676 BTC_ACT_WL_2G_GO, 677 BTC_ACT_WL_2G_GC, 678 BTC_ACT_WL_2G_NAN, 679 BTC_ACT_LAST, 680 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE, 681 BTC_ACT_EXT_BIT = BIT(14), 682 BTC_POLICY_EXT_BIT = BIT(15), 683 }; 684 685 #define BTC_FREERUN_ANTISO_MIN 30 686 #define BTC_TDMA_BTHID_MAX 2 687 #define BTC_BLINK_NOCONNECT 0 688 #define BTC_B1_MAX 250 /* unit ms */ 689 690 static void _run_coex(struct rtw89_dev *rtwdev, 691 enum btc_reason_and_action reason); 692 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state); 693 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update); 694 695 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, 696 void *param, u16 len) 697 { 698 struct rtw89_btc *btc = &rtwdev->btc; 699 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 700 struct rtw89_btc_cx *cx = &btc->cx; 701 struct rtw89_btc_wl_info *wl = &cx->wl; 702 struct rtw89_btc_dm *dm = &btc->dm; 703 int ret; 704 705 if (len > BTC_H2C_MAXLEN || len == 0) { 706 btc->fwinfo.cnt_h2c_fail++; 707 dm->error.map.h2c_buffer_over = true; 708 return -EINVAL; 709 } else if (!wl->status.map.init_ok) { 710 rtw89_debug(rtwdev, RTW89_DBG_BTC, 711 "[BTC], %s(): return by btc not init!!\n", __func__); 712 pfwinfo->cnt_h2c_fail++; 713 return -EINVAL; 714 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF && 715 wl->status.map.rf_off == BTC_LPS_RF_OFF) || 716 (wl->status.map.lps_pre == BTC_LPS_RF_OFF && 717 wl->status.map.lps == BTC_LPS_RF_OFF)) { 718 rtw89_debug(rtwdev, RTW89_DBG_BTC, 719 "[BTC], %s(): return by wl off!!\n", __func__); 720 pfwinfo->cnt_h2c_fail++; 721 return -EINVAL; 722 } 723 724 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len, 725 false, true); 726 if (ret) 727 pfwinfo->cnt_h2c_fail++; 728 else 729 pfwinfo->cnt_h2c++; 730 731 return ret; 732 } 733 734 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) 735 { 736 struct rtw89_btc *btc = &rtwdev->btc; 737 const struct rtw89_btc_ver *ver = btc->ver; 738 struct rtw89_btc_cx *cx = &btc->cx; 739 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 740 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 741 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 742 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 743 u8 i; 744 745 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 746 747 if (type & BTC_RESET_CX) 748 memset(cx, 0, sizeof(*cx)); 749 750 if (type & BTC_RESET_BTINFO) /* only for BT enable */ 751 memset(bt, 0, sizeof(*bt)); 752 753 if (type & BTC_RESET_CTRL) { 754 memset(&btc->ctrl, 0, sizeof(btc->ctrl)); 755 btc->manual_ctrl = false; 756 if (ver->fcxctrl != 7) 757 btc->ctrl.ctrl.trace_step = FCXDEF_STEP; 758 } 759 760 /* Init Coex variables that are not zero */ 761 if (type & BTC_RESET_DM) { 762 memset(&btc->dm, 0, sizeof(btc->dm)); 763 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state)); 764 765 for (i = 0; i < RTW89_PORT_NUM; i++) 766 memset(wl_linfo[i].rssi_state, 0, 767 sizeof(wl_linfo[i].rssi_state)); 768 769 /* set the slot_now table to original */ 770 btc->dm.tdma_now = t_def[CXTD_OFF]; 771 btc->dm.tdma = t_def[CXTD_OFF]; 772 memcpy(&btc->dm.slot_now, s_def, sizeof(btc->dm.slot_now)); 773 memcpy(&btc->dm.slot, s_def, sizeof(btc->dm.slot)); 774 775 btc->policy_len = 0; 776 btc->bt_req_len = 0; 777 778 btc->dm.coex_info_map = BTC_COEX_INFO_ALL; 779 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF; 780 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF; 781 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND; 782 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND; 783 } 784 785 if (type & BTC_RESET_MDINFO) 786 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo)); 787 } 788 789 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target) 790 { 791 const struct rtw89_chip_info *chip = rtwdev->chip; 792 u8 i; 793 794 for (i = 0; i < mreg_num; i++) 795 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type && 796 le32_to_cpu(chip->mon_reg[i].offset) == target) { 797 return i; 798 } 799 return BTC_REG_NOTFOUND; 800 } 801 802 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val) 803 { 804 struct rtw89_btc *btc = &rtwdev->btc; 805 const struct rtw89_btc_ver *ver = btc->ver; 806 union rtw89_btc_module_info *md = &btc->mdinfo; 807 union rtw89_btc_fbtc_mreg_val *pmreg; 808 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1; 809 u32 reg_val; 810 u8 idx, switch_type; 811 812 if (ver->fcxinit == 7) 813 switch_type = md->md_v7.switch_type; 814 else 815 switch_type = md->md.switch_type; 816 817 if (btc->btg_pos == RF_PATH_A) 818 pre_agc_addr = R_BTC_BB_PRE_AGC_S0; 819 820 switch (type) { 821 case BTC_CSTATUS_TXDIV_POS: 822 if (switch_type == BTC_SWITCH_INTERNAL) 823 *val = BTC_ANT_DIV_MAIN; 824 break; 825 case BTC_CSTATUS_RXDIV_POS: 826 if (switch_type == BTC_SWITCH_INTERNAL) 827 *val = BTC_ANT_DIV_MAIN; 828 break; 829 case BTC_CSTATUS_BB_GNT_MUX: 830 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX); 831 *val = !(reg_val & B_BTC_BB_GNT_MUX); 832 break; 833 case BTC_CSTATUS_BB_GNT_MUX_MON: 834 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 835 return; 836 837 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 838 if (ver->fcxmreg == 1) { 839 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 840 REG_BB, R_BTC_BB_BTG_RX); 841 if (idx == BTC_REG_NOTFOUND) { 842 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 843 } else { 844 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]); 845 *val = !(reg_val & B_BTC_BB_GNT_MUX); 846 } 847 } else if (ver->fcxmreg == 2) { 848 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 849 REG_BB, R_BTC_BB_BTG_RX); 850 if (idx == BTC_REG_NOTFOUND) { 851 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 852 } else { 853 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]); 854 *val = !(reg_val & B_BTC_BB_GNT_MUX); 855 } 856 } 857 break; 858 case BTC_CSTATUS_BB_PRE_AGC: 859 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr); 860 reg_val &= B_BTC_BB_PRE_AGC_MASK; 861 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 862 break; 863 case BTC_CSTATUS_BB_PRE_AGC_MON: 864 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 865 return; 866 867 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 868 if (ver->fcxmreg == 1) { 869 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 870 REG_BB, pre_agc_addr); 871 if (idx == BTC_REG_NOTFOUND) { 872 *val = BTC_PREAGC_NOTFOUND; 873 } else { 874 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) & 875 B_BTC_BB_PRE_AGC_MASK; 876 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 877 } 878 } else if (ver->fcxmreg == 2) { 879 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 880 REG_BB, pre_agc_addr); 881 if (idx == BTC_REG_NOTFOUND) { 882 *val = BTC_PREAGC_NOTFOUND; 883 } else { 884 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) & 885 B_BTC_BB_PRE_AGC_MASK; 886 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 887 } 888 } 889 break; 890 default: 891 break; 892 } 893 } 894 895 #define BTC_RPT_HDR_SIZE 3 896 #define BTC_CHK_WLSLOT_DRIFT_MAX 15 897 #define BTC_CHK_BTSLOT_DRIFT_MAX 15 898 #define BTC_CHK_HANG_MAX 3 899 900 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt) 901 { 902 struct rtw89_btc *btc = &rtwdev->btc; 903 struct rtw89_btc_cx *cx = &btc->cx; 904 struct rtw89_btc_dm *dm = &btc->dm; 905 struct rtw89_btc_bt_info *bt = &cx->bt; 906 907 rtw89_debug(rtwdev, RTW89_DBG_BTC, 908 "[BTC], %s(): type:%d cnt:%d\n", 909 __func__, type, cnt); 910 911 switch (type) { 912 case BTC_DCNT_RPT_HANG: 913 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map) 914 dm->cnt_dm[BTC_DCNT_RPT_HANG]++; 915 else 916 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0; 917 918 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX) 919 dm->error.map.wl_fw_hang = true; 920 else 921 dm->error.map.wl_fw_hang = false; 922 923 dm->cnt_dm[BTC_DCNT_RPT] = cnt; 924 break; 925 case BTC_DCNT_CYCLE_HANG: 926 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt && 927 (dm->tdma_now.type != CXTDMA_OFF || 928 dm->tdma_now.ext_ctrl == CXECTL_EXT)) 929 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++; 930 else 931 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0; 932 933 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX) 934 dm->error.map.cycle_hang = true; 935 else 936 dm->error.map.cycle_hang = false; 937 938 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt; 939 break; 940 case BTC_DCNT_W1_HANG: 941 if (dm->cnt_dm[BTC_DCNT_W1] == cnt && 942 dm->tdma_now.type != CXTDMA_OFF) 943 dm->cnt_dm[BTC_DCNT_W1_HANG]++; 944 else 945 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0; 946 947 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX) 948 dm->error.map.w1_hang = true; 949 else 950 dm->error.map.w1_hang = false; 951 952 dm->cnt_dm[BTC_DCNT_W1] = cnt; 953 break; 954 case BTC_DCNT_B1_HANG: 955 if (dm->cnt_dm[BTC_DCNT_B1] == cnt && 956 dm->tdma_now.type != CXTDMA_OFF) 957 dm->cnt_dm[BTC_DCNT_B1_HANG]++; 958 else 959 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0; 960 961 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX) 962 dm->error.map.b1_hang = true; 963 else 964 dm->error.map.b1_hang = false; 965 966 dm->cnt_dm[BTC_DCNT_B1] = cnt; 967 break; 968 case BTC_DCNT_E2G_HANG: 969 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt && 970 dm->tdma_now.ext_ctrl == CXECTL_EXT) 971 dm->cnt_dm[BTC_DCNT_E2G_HANG]++; 972 else 973 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0; 974 975 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX) 976 dm->error.map.wl_e2g_hang = true; 977 else 978 dm->error.map.wl_e2g_hang = false; 979 980 dm->cnt_dm[BTC_DCNT_E2G] = cnt; 981 break; 982 case BTC_DCNT_TDMA_NONSYNC: 983 if (cnt != 0) /* if tdma not sync between drv/fw */ 984 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++; 985 else 986 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0; 987 988 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX) 989 dm->error.map.tdma_no_sync = true; 990 else 991 dm->error.map.tdma_no_sync = false; 992 break; 993 case BTC_DCNT_SLOT_NONSYNC: 994 if (cnt != 0) /* if slot not sync between drv/fw */ 995 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++; 996 else 997 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0; 998 999 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX) 1000 dm->error.map.slot_no_sync = true; 1001 else 1002 dm->error.map.slot_no_sync = false; 1003 break; 1004 case BTC_DCNT_BTCNT_HANG: 1005 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] + 1006 cx->cnt_bt[BTC_BCNT_HIPRI_TX] + 1007 cx->cnt_bt[BTC_BCNT_LOPRI_RX] + 1008 cx->cnt_bt[BTC_BCNT_LOPRI_TX]; 1009 1010 if (cnt == 0) 1011 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++; 1012 else 1013 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 1014 1015 if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX && 1016 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] && 1017 !bt->enable.now)) 1018 _update_bt_scbd(rtwdev, false); 1019 break; 1020 case BTC_DCNT_WL_SLOT_DRIFT: 1021 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX) 1022 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++; 1023 else 1024 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0; 1025 1026 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1027 dm->error.map.wl_slot_drift = true; 1028 else 1029 dm->error.map.wl_slot_drift = false; 1030 break; 1031 case BTC_DCNT_BT_SLOT_DRIFT: 1032 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX) 1033 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++; 1034 else 1035 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0; 1036 1037 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1038 dm->error.map.bt_slot_drift = true; 1039 else 1040 dm->error.map.bt_slot_drift = false; 1041 1042 break; 1043 } 1044 } 1045 1046 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) 1047 { 1048 struct rtw89_btc *btc = &rtwdev->btc; 1049 const struct rtw89_btc_ver *ver = btc->ver; 1050 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 1051 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 1052 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc; 1053 struct rtw89_btc_fbtc_btver *pver = NULL; 1054 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1; 1055 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2; 1056 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL; 1057 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL; 1058 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL; 1059 bool scan_update = true; 1060 int i; 1061 1062 pver = (struct rtw89_btc_fbtc_btver *)pfinfo; 1063 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo; 1064 1065 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1066 "[BTC], %s(): rpt_type:%d\n", 1067 __func__, rpt_type); 1068 1069 switch (rpt_type) { 1070 case BTC_RPT_TYPE_BT_VER: 1071 bt->ver_info.fw = le32_to_cpu(pver->fw_ver); 1072 bt->ver_info.fw_coex = le32_get_bits(pver->coex_ver, GENMASK(7, 0)); 1073 bt->feature = le32_to_cpu(pver->feature); 1074 break; 1075 case BTC_RPT_TYPE_BT_SCAN: 1076 if (ver->fcxbtscan == 1) { 1077 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo; 1078 for (i = 0; i < BTC_SCAN_MAX1; i++) { 1079 bt->scan_info_v1[i] = pscan_v1->scan[i]; 1080 if (bt->scan_info_v1[i].win == 0 && 1081 bt->scan_info_v1[i].intvl == 0) 1082 scan_update = false; 1083 } 1084 } else if (ver->fcxbtscan == 2) { 1085 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo; 1086 for (i = 0; i < CXSCAN_MAX; i++) { 1087 bt->scan_info_v2[i] = pscan_v2->para[i]; 1088 if ((pscan_v2->type & BIT(i)) && 1089 pscan_v2->para[i].win == 0 && 1090 pscan_v2->para[i].intvl == 0) 1091 scan_update = false; 1092 } 1093 } 1094 if (scan_update) 1095 bt->scan_info_update = 1; 1096 break; 1097 case BTC_RPT_TYPE_BT_AFH: 1098 if (ver->fcxbtafh == 2) { 1099 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo; 1100 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1101 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4); 1102 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4); 1103 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2); 1104 } 1105 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) { 1106 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4); 1107 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1); 1108 } 1109 } else if (ver->fcxbtafh == 1) { 1110 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo; 1111 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4); 1112 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4); 1113 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2); 1114 } 1115 break; 1116 case BTC_RPT_TYPE_BT_DEVICE: 1117 a2dp->device_name = le32_to_cpu(pdev->dev_name); 1118 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id); 1119 a2dp->flush_time = le32_to_cpu(pdev->flush_time); 1120 break; 1121 default: 1122 break; 1123 } 1124 } 1125 1126 #define BTC_LEAK_AP_TH 10 1127 #define BTC_CYSTA_CHK_PERIOD 100 1128 1129 struct rtw89_btc_prpt { 1130 u8 type; 1131 __le16 len; 1132 u8 content[]; 1133 } __packed; 1134 1135 static u32 _chk_btc_report(struct rtw89_dev *rtwdev, 1136 struct rtw89_btc_btf_fwinfo *pfwinfo, 1137 u8 *prptbuf, u32 index) 1138 { 1139 struct rtw89_btc *btc = &rtwdev->btc; 1140 const struct rtw89_btc_ver *ver = btc->ver; 1141 struct rtw89_btc_dm *dm = &btc->dm; 1142 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 1143 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1144 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 1145 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL; 1146 union rtw89_btc_fbtc_cysta_info *pcysta = NULL; 1147 struct rtw89_btc_prpt *btc_prpt = NULL; 1148 void *rpt_content = NULL, *pfinfo = NULL; 1149 u8 rpt_type = 0; 1150 u16 wl_slot_set = 0, wl_slot_real = 0; 1151 u32 trace_step = 0, rpt_len = 0, diff_t = 0; 1152 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr; 1153 u8 i, val = 0; 1154 1155 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1156 "[BTC], %s(): index:%d\n", 1157 __func__, index); 1158 1159 if (!prptbuf) { 1160 pfwinfo->err[BTFRE_INVALID_INPUT]++; 1161 return 0; 1162 } 1163 1164 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index]; 1165 rpt_type = btc_prpt->type; 1166 rpt_len = le16_to_cpu(btc_prpt->len); 1167 rpt_content = btc_prpt->content; 1168 1169 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1170 "[BTC], %s(): rpt_type:%d\n", 1171 __func__, rpt_type); 1172 1173 switch (rpt_type) { 1174 case BTC_RPT_TYPE_CTRL: 1175 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 1176 prpt = &pfwinfo->rpt_ctrl.finfo; 1177 if (ver->fcxbtcrpt == 1) { 1178 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1; 1179 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1); 1180 } else if (ver->fcxbtcrpt == 4) { 1181 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4; 1182 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4); 1183 } else if (ver->fcxbtcrpt == 5) { 1184 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5; 1185 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5); 1186 } else if (ver->fcxbtcrpt == 105) { 1187 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105; 1188 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105); 1189 pcinfo->req_fver = 5; 1190 break; 1191 } else { 1192 goto err; 1193 } 1194 pcinfo->req_fver = ver->fcxbtcrpt; 1195 break; 1196 case BTC_RPT_TYPE_TDMA: 1197 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 1198 if (ver->fcxtdma == 1) { 1199 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 1200 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); 1201 } else if (ver->fcxtdma == 3) { 1202 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; 1203 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); 1204 } else { 1205 goto err; 1206 } 1207 pcinfo->req_fver = ver->fcxtdma; 1208 break; 1209 case BTC_RPT_TYPE_SLOT: 1210 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 1211 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo; 1212 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo); 1213 pcinfo->req_fver = ver->fcxslots; 1214 break; 1215 case BTC_RPT_TYPE_CYSTA: 1216 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 1217 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 1218 if (ver->fcxcysta == 2) { 1219 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 1220 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 1221 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2); 1222 } else if (ver->fcxcysta == 3) { 1223 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 1224 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 1225 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3); 1226 } else if (ver->fcxcysta == 4) { 1227 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 1228 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 1229 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4); 1230 } else if (ver->fcxcysta == 5) { 1231 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 1232 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 1233 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5); 1234 } else { 1235 goto err; 1236 } 1237 pcinfo->req_fver = ver->fcxcysta; 1238 break; 1239 case BTC_RPT_TYPE_STEP: 1240 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 1241 if (ver->fcxctrl != 7) 1242 trace_step = btc->ctrl.ctrl.trace_step; 1243 1244 if (ver->fcxstep == 2) { 1245 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2; 1246 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) * 1247 trace_step + 1248 offsetof(struct rtw89_btc_fbtc_steps_v2, step); 1249 } else if (ver->fcxstep == 3) { 1250 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3; 1251 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) * 1252 trace_step + 1253 offsetof(struct rtw89_btc_fbtc_steps_v3, step); 1254 } else { 1255 goto err; 1256 } 1257 pcinfo->req_fver = ver->fcxstep; 1258 break; 1259 case BTC_RPT_TYPE_NULLSTA: 1260 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 1261 if (ver->fcxnullsta == 1) { 1262 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1; 1263 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1); 1264 } else if (ver->fcxnullsta == 2) { 1265 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2; 1266 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2); 1267 } else { 1268 goto err; 1269 } 1270 pcinfo->req_fver = ver->fcxnullsta; 1271 break; 1272 case BTC_RPT_TYPE_MREG: 1273 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 1274 if (ver->fcxmreg == 1) { 1275 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 1276 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1); 1277 } else if (ver->fcxmreg == 2) { 1278 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 1279 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2); 1280 } else { 1281 goto err; 1282 } 1283 pcinfo->req_fver = ver->fcxmreg; 1284 break; 1285 case BTC_RPT_TYPE_GPIO_DBG: 1286 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 1287 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 1288 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo); 1289 pcinfo->req_fver = ver->fcxgpiodbg; 1290 break; 1291 case BTC_RPT_TYPE_BT_VER: 1292 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo; 1293 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo; 1294 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo); 1295 pcinfo->req_fver = ver->fcxbtver; 1296 break; 1297 case BTC_RPT_TYPE_BT_SCAN: 1298 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo; 1299 if (ver->fcxbtscan == 1) { 1300 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1; 1301 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1); 1302 } else if (ver->fcxbtscan == 2) { 1303 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2; 1304 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2); 1305 } 1306 pcinfo->req_fver = ver->fcxbtscan; 1307 break; 1308 case BTC_RPT_TYPE_BT_AFH: 1309 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo; 1310 if (ver->fcxbtafh == 1) { 1311 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1; 1312 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1); 1313 } else if (ver->fcxbtafh == 2) { 1314 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2; 1315 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2); 1316 } else { 1317 goto err; 1318 } 1319 pcinfo->req_fver = ver->fcxbtafh; 1320 break; 1321 case BTC_RPT_TYPE_BT_DEVICE: 1322 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo; 1323 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo; 1324 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo); 1325 pcinfo->req_fver = ver->fcxbtdevinfo; 1326 break; 1327 default: 1328 pfwinfo->err[BTFRE_UNDEF_TYPE]++; 1329 return 0; 1330 } 1331 1332 pcinfo->rx_len = rpt_len; 1333 pcinfo->rx_cnt++; 1334 1335 if (rpt_len != pcinfo->req_len) { 1336 if (rpt_type < BTC_RPT_TYPE_MAX) 1337 pfwinfo->len_mismch |= (0x1 << rpt_type); 1338 else 1339 pfwinfo->len_mismch |= BIT(31); 1340 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1341 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n", 1342 __func__, rpt_type, rpt_len, pcinfo->req_len); 1343 1344 pcinfo->valid = 0; 1345 return 0; 1346 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) { 1347 pfwinfo->err[BTFRE_EXCEPTION]++; 1348 pcinfo->valid = 0; 1349 return 0; 1350 } 1351 1352 memcpy(pfinfo, rpt_content, pcinfo->req_len); 1353 pcinfo->valid = 1; 1354 1355 switch (rpt_type) { 1356 case BTC_RPT_TYPE_CTRL: 1357 if (ver->fcxbtcrpt == 1) { 1358 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1; 1359 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable; 1360 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver; 1361 wl->ver_info.fw = prpt->v1.wl_fw_ver; 1362 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload; 1363 1364 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1365 pfwinfo->event[BTF_EVNT_RPT]); 1366 1367 /* To avoid I/O if WL LPS or power-off */ 1368 if (wl->status.map.lps != BTC_LPS_RF_OFF && 1369 !wl->status.map.rf_off) { 1370 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev); 1371 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1372 1373 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1374 rtw89_mac_get_plt_cnt(rtwdev, 1375 RTW89_MAC_0); 1376 } 1377 } else if (ver->fcxbtcrpt == 4) { 1378 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4; 1379 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en); 1380 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver); 1381 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver); 1382 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload); 1383 1384 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++) 1385 memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i], 1386 sizeof(dm->gnt.band[i])); 1387 1388 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1389 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]); 1390 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1391 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]); 1392 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1393 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]); 1394 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1395 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]); 1396 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1397 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]); 1398 1399 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1400 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1401 pfwinfo->event[BTF_EVNT_RPT]); 1402 1403 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 1404 bt->rfk_info.map.timeout = 1; 1405 else 1406 bt->rfk_info.map.timeout = 0; 1407 1408 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1409 } else if (ver->fcxbtcrpt == 5) { 1410 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5; 1411 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en); 1412 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver); 1413 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver); 1414 dm->wl_fw_cx_offload = 0; 1415 1416 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++) 1417 memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0], 1418 sizeof(dm->gnt.band[i])); 1419 1420 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1421 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]); 1422 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1423 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]); 1424 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1425 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]); 1426 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1427 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]); 1428 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1429 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]); 1430 1431 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1432 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1433 pfwinfo->event[BTF_EVNT_RPT]); 1434 1435 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1436 } else if (ver->fcxbtcrpt == 105) { 1437 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105; 1438 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en); 1439 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver); 1440 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver); 1441 dm->wl_fw_cx_offload = 0; 1442 1443 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++) 1444 memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0], 1445 sizeof(dm->gnt.band[i])); 1446 1447 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1448 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]); 1449 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1450 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]); 1451 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1452 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]); 1453 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1454 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]); 1455 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1456 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1457 1458 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1459 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1460 pfwinfo->event[BTF_EVNT_RPT]); 1461 1462 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1463 } else { 1464 goto err; 1465 } 1466 break; 1467 case BTC_RPT_TYPE_TDMA: 1468 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1469 "[BTC], %s(): check %d %zu\n", __func__, 1470 BTC_DCNT_TDMA_NONSYNC, 1471 sizeof(dm->tdma_now)); 1472 if (ver->fcxtdma == 1) 1473 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 1474 memcmp(&dm->tdma_now, 1475 &pfwinfo->rpt_fbtc_tdma.finfo.v1, 1476 sizeof(dm->tdma_now))); 1477 else if (ver->fcxtdma == 3) 1478 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 1479 memcmp(&dm->tdma_now, 1480 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma, 1481 sizeof(dm->tdma_now))); 1482 else 1483 goto err; 1484 break; 1485 case BTC_RPT_TYPE_SLOT: 1486 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1487 "[BTC], %s(): check %d %zu\n", 1488 __func__, BTC_DCNT_SLOT_NONSYNC, 1489 sizeof(dm->slot_now)); 1490 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 1491 memcmp(dm->slot_now, 1492 pfwinfo->rpt_fbtc_slots.finfo.slot, 1493 sizeof(dm->slot_now))); 1494 break; 1495 case BTC_RPT_TYPE_CYSTA: 1496 if (ver->fcxcysta == 2) { 1497 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD) 1498 break; 1499 /* Check Leak-AP */ 1500 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 && 1501 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) { 1502 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) < 1503 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt)) 1504 dm->leak_ap = 1; 1505 } 1506 1507 /* Check diff time between WL slot and W1/E2G slot */ 1508 if (dm->tdma_now.type == CXTDMA_OFF && 1509 dm->tdma_now.ext_ctrl == CXECTL_EXT) 1510 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur); 1511 else 1512 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1513 1514 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) { 1515 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set; 1516 _chk_btc_err(rtwdev, 1517 BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1518 } 1519 1520 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1521 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1])); 1522 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1523 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1])); 1524 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1525 le16_to_cpu(pcysta->v2.cycles)); 1526 } else if (ver->fcxcysta == 3) { 1527 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD) 1528 break; 1529 1530 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]); 1531 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr); 1532 1533 /* Check Leak-AP */ 1534 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1535 dm->tdma_now.rxflctrl) { 1536 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1537 dm->leak_ap = 1; 1538 } 1539 1540 /* Check diff time between real WL slot and W1 slot */ 1541 if (dm->tdma_now.type == CXTDMA_OFF) { 1542 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1543 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]); 1544 if (wl_slot_real > wl_slot_set) { 1545 diff_t = wl_slot_real - wl_slot_set; 1546 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1547 } 1548 } 1549 1550 /* Check diff time between real BT slot and EBT/E5G slot */ 1551 if (dm->tdma_now.type == CXTDMA_OFF && 1552 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1553 btc->bt_req_len != 0) { 1554 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]); 1555 if (btc->bt_req_len > bt_slot_real) { 1556 diff_t = btc->bt_req_len - bt_slot_real; 1557 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 1558 } 1559 } 1560 1561 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1562 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1])); 1563 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 1564 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1])); 1565 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1566 le16_to_cpu(pcysta->v3.cycles)); 1567 } else if (ver->fcxcysta == 4) { 1568 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD) 1569 break; 1570 1571 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]); 1572 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr); 1573 1574 /* Check Leak-AP */ 1575 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1576 dm->tdma_now.rxflctrl) { 1577 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1578 dm->leak_ap = 1; 1579 } 1580 1581 /* Check diff time between real WL slot and W1 slot */ 1582 if (dm->tdma_now.type == CXTDMA_OFF) { 1583 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1584 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]); 1585 if (wl_slot_real > wl_slot_set) { 1586 diff_t = wl_slot_real - wl_slot_set; 1587 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1588 } 1589 } 1590 1591 /* Check diff time between real BT slot and EBT/E5G slot */ 1592 if (dm->tdma_now.type == CXTDMA_OFF && 1593 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1594 btc->bt_req_len != 0) { 1595 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]); 1596 1597 if (btc->bt_req_len > bt_slot_real) { 1598 diff_t = btc->bt_req_len - bt_slot_real; 1599 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 1600 } 1601 } 1602 1603 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1604 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1])); 1605 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 1606 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1])); 1607 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1608 le16_to_cpu(pcysta->v4.cycles)); 1609 } else if (ver->fcxcysta == 5) { 1610 if (dm->fddt_train == BTC_FDDT_ENABLE) 1611 break; 1612 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]); 1613 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr); 1614 1615 /* Check Leak-AP */ 1616 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1617 dm->tdma_now.rxflctrl) { 1618 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 1619 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1620 dm->leak_ap = 1; 1621 } 1622 1623 /* Check diff time between real WL slot and W1 slot */ 1624 if (dm->tdma_now.type == CXTDMA_OFF) { 1625 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1626 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]); 1627 1628 if (wl_slot_real > wl_slot_set) 1629 diff_t = wl_slot_real - wl_slot_set; 1630 else 1631 diff_t = wl_slot_set - wl_slot_real; 1632 } 1633 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1634 1635 /* Check diff time between real BT slot and EBT/E5G slot */ 1636 bt_slot_set = btc->bt_req_len; 1637 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]); 1638 diff_t = 0; 1639 if (dm->tdma_now.type == CXTDMA_OFF && 1640 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1641 bt_slot_set != 0) { 1642 if (bt_slot_set > bt_slot_real) 1643 diff_t = bt_slot_set - bt_slot_real; 1644 else 1645 diff_t = bt_slot_real - bt_slot_set; 1646 } 1647 1648 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 1649 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 1650 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G])); 1651 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1652 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1])); 1653 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 1654 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1])); 1655 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1656 le16_to_cpu(pcysta->v5.cycles)); 1657 } else { 1658 goto err; 1659 } 1660 break; 1661 case BTC_RPT_TYPE_MREG: 1662 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val); 1663 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL) 1664 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL; 1665 else 1666 dm->wl_btg_rx_rb = val; 1667 1668 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val); 1669 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL) 1670 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL; 1671 else 1672 dm->wl_pre_agc_rb = val; 1673 break; 1674 case BTC_RPT_TYPE_BT_VER: 1675 case BTC_RPT_TYPE_BT_SCAN: 1676 case BTC_RPT_TYPE_BT_AFH: 1677 case BTC_RPT_TYPE_BT_DEVICE: 1678 _update_bt_report(rtwdev, rpt_type, pfinfo); 1679 break; 1680 } 1681 return (rpt_len + BTC_RPT_HDR_SIZE); 1682 1683 err: 1684 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1685 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type); 1686 return 0; 1687 } 1688 1689 static void _parse_btc_report(struct rtw89_dev *rtwdev, 1690 struct rtw89_btc_btf_fwinfo *pfwinfo, 1691 u8 *pbuf, u32 buf_len) 1692 { 1693 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 1694 struct rtw89_btc_prpt *btc_prpt = NULL; 1695 u32 index = 0, rpt_len = 0; 1696 1697 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1698 "[BTC], %s(): buf_len:%d\n", 1699 __func__, buf_len); 1700 1701 while (pbuf) { 1702 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index]; 1703 if (index + 2 >= ver->info_buf) 1704 break; 1705 /* At least 3 bytes: type(1) & len(2) */ 1706 rpt_len = le16_to_cpu(btc_prpt->len); 1707 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len) 1708 break; 1709 1710 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index); 1711 if (!rpt_len) 1712 break; 1713 index += rpt_len; 1714 } 1715 } 1716 1717 #define BTC_TLV_HDR_LEN 2 1718 1719 static void _append_tdma(struct rtw89_dev *rtwdev) 1720 { 1721 struct rtw89_btc *btc = &rtwdev->btc; 1722 const struct rtw89_btc_ver *ver = btc->ver; 1723 struct rtw89_btc_dm *dm = &btc->dm; 1724 struct rtw89_btc_btf_tlv *tlv; 1725 struct rtw89_btc_fbtc_tdma *v; 1726 struct rtw89_btc_fbtc_tdma_v3 *v3; 1727 u16 len = btc->policy_len; 1728 1729 if (!btc->update_policy_force && 1730 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) { 1731 rtw89_debug(rtwdev, 1732 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n", 1733 __func__); 1734 return; 1735 } 1736 1737 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 1738 tlv->type = CXPOLICY_TDMA; 1739 if (ver->fcxtdma == 1) { 1740 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0]; 1741 tlv->len = sizeof(*v); 1742 *v = dm->tdma; 1743 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 1744 } else { 1745 tlv->len = sizeof(*v3); 1746 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0]; 1747 v3->fver = ver->fcxtdma; 1748 v3->tdma = dm->tdma; 1749 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3); 1750 } 1751 1752 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1753 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n", 1754 __func__, dm->tdma.type, dm->tdma.rxflctrl, 1755 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n, 1756 dm->tdma.ext_ctrl); 1757 } 1758 1759 static void _append_slot(struct rtw89_dev *rtwdev) 1760 { 1761 struct rtw89_btc *btc = &rtwdev->btc; 1762 struct rtw89_btc_dm *dm = &btc->dm; 1763 struct rtw89_btc_btf_tlv *tlv = NULL; 1764 struct btc_fbtc_1slot *v = NULL; 1765 u16 len = 0; 1766 u8 i, cnt = 0; 1767 1768 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1769 "[BTC], %s(): A:btc->policy_len = %d\n", 1770 __func__, btc->policy_len); 1771 1772 for (i = 0; i < CXST_MAX; i++) { 1773 if (!btc->update_policy_force && 1774 !memcmp(&dm->slot[i], &dm->slot_now[i], 1775 sizeof(dm->slot[i]))) 1776 continue; 1777 1778 len = btc->policy_len; 1779 1780 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 1781 v = (struct btc_fbtc_1slot *)&tlv->val[0]; 1782 tlv->type = CXPOLICY_SLOT; 1783 tlv->len = sizeof(*v); 1784 1785 v->fver = FCXONESLOT_VER; 1786 v->sid = i; 1787 v->slot = dm->slot[i]; 1788 1789 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1790 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n", 1791 __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl, 1792 dm->slot[i].cxtype); 1793 cnt++; 1794 1795 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 1796 } 1797 1798 if (cnt > 0) 1799 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1800 "[BTC], %s(): slot update (cnt=%d)!!\n", 1801 __func__, cnt); 1802 } 1803 1804 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) 1805 { 1806 struct rtw89_btc *btc = &rtwdev->btc; 1807 const struct rtw89_btc_ver *ver = btc->ver; 1808 u32 bit_map = 0; 1809 1810 switch (rpt_map) { 1811 case RPT_EN_TDMA: 1812 bit_map = BIT(0); 1813 break; 1814 case RPT_EN_CYCLE: 1815 bit_map = BIT(1); 1816 break; 1817 case RPT_EN_MREG: 1818 bit_map = BIT(2); 1819 break; 1820 case RPT_EN_BT_VER_INFO: 1821 bit_map = BIT(3); 1822 break; 1823 case RPT_EN_BT_SCAN_INFO: 1824 bit_map = BIT(4); 1825 break; 1826 case RPT_EN_BT_DEVICE_INFO: 1827 switch (ver->frptmap) { 1828 case 0: 1829 case 1: 1830 case 2: 1831 bit_map = BIT(6); 1832 break; 1833 case 3: 1834 bit_map = BIT(5); 1835 break; 1836 default: 1837 break; 1838 } 1839 break; 1840 case RPT_EN_BT_AFH_MAP: 1841 switch (ver->frptmap) { 1842 case 0: 1843 case 1: 1844 case 2: 1845 bit_map = BIT(5); 1846 break; 1847 case 3: 1848 bit_map = BIT(6); 1849 break; 1850 default: 1851 break; 1852 } 1853 break; 1854 case RPT_EN_BT_AFH_MAP_LE: 1855 switch (ver->frptmap) { 1856 case 2: 1857 bit_map = BIT(8); 1858 break; 1859 case 3: 1860 bit_map = BIT(7); 1861 break; 1862 default: 1863 break; 1864 } 1865 break; 1866 case RPT_EN_FW_STEP_INFO: 1867 switch (ver->frptmap) { 1868 case 1: 1869 case 2: 1870 bit_map = BIT(7); 1871 break; 1872 case 3: 1873 bit_map = BIT(8); 1874 break; 1875 default: 1876 break; 1877 } 1878 break; 1879 case RPT_EN_TEST: 1880 bit_map = BIT(31); 1881 break; 1882 case RPT_EN_WL_ALL: 1883 switch (ver->frptmap) { 1884 case 0: 1885 case 1: 1886 case 2: 1887 bit_map = GENMASK(2, 0); 1888 break; 1889 case 3: 1890 bit_map = GENMASK(2, 0) | BIT(8); 1891 break; 1892 default: 1893 break; 1894 } 1895 break; 1896 case RPT_EN_BT_ALL: 1897 switch (ver->frptmap) { 1898 case 0: 1899 case 1: 1900 bit_map = GENMASK(6, 3); 1901 break; 1902 case 2: 1903 bit_map = GENMASK(6, 3) | BIT(8); 1904 break; 1905 case 3: 1906 bit_map = GENMASK(7, 3); 1907 break; 1908 default: 1909 break; 1910 } 1911 break; 1912 case RPT_EN_ALL: 1913 switch (ver->frptmap) { 1914 case 0: 1915 bit_map = GENMASK(6, 0); 1916 break; 1917 case 1: 1918 bit_map = GENMASK(7, 0); 1919 break; 1920 case 2: 1921 case 3: 1922 bit_map = GENMASK(8, 0); 1923 break; 1924 default: 1925 break; 1926 } 1927 break; 1928 case RPT_EN_MONITER: 1929 switch (ver->frptmap) { 1930 case 0: 1931 case 1: 1932 bit_map = GENMASK(6, 2); 1933 break; 1934 case 2: 1935 bit_map = GENMASK(6, 2) | BIT(8); 1936 break; 1937 case 3: 1938 bit_map = GENMASK(8, 2); 1939 break; 1940 default: 1941 break; 1942 } 1943 break; 1944 } 1945 1946 return bit_map; 1947 } 1948 1949 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev, 1950 u32 rpt_map, bool rpt_state) 1951 { 1952 struct rtw89_btc *btc = &rtwdev->btc; 1953 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map; 1954 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo; 1955 struct rtw89_btc_btf_set_report r = {0}; 1956 u32 val, bit_map; 1957 int ret; 1958 1959 if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0) 1960 return; 1961 1962 bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map); 1963 1964 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1965 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n", 1966 __func__, rpt_map, rpt_state); 1967 1968 if (rpt_state) 1969 val = fwinfo->rpt_en_map | bit_map; 1970 else 1971 val = fwinfo->rpt_en_map & ~bit_map; 1972 1973 if (val == fwinfo->rpt_en_map) 1974 return; 1975 1976 r.fver = BTF_SET_REPORT_VER; 1977 r.enable = cpu_to_le32(val); 1978 r.para = cpu_to_le32(rpt_state); 1979 1980 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r, sizeof(r)); 1981 if (!ret) 1982 fwinfo->rpt_en_map = val; 1983 } 1984 1985 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num, 1986 struct rtw89_btc_fbtc_slot *s) 1987 { 1988 struct rtw89_btc_btf_set_slot_table *tbl; 1989 u16 n; 1990 1991 n = struct_size(tbl, tbls, num); 1992 tbl = kmalloc(n, GFP_KERNEL); 1993 if (!tbl) 1994 return; 1995 1996 tbl->fver = BTF_SET_SLOT_TABLE_VER; 1997 tbl->tbl_num = num; 1998 memcpy(tbl->tbls, s, flex_array_size(tbl, tbls, num)); 1999 2000 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n); 2001 2002 kfree(tbl); 2003 } 2004 2005 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) 2006 { 2007 const struct rtw89_chip_info *chip = rtwdev->chip; 2008 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 2009 struct rtw89_btc_btf_set_mon_reg *monreg = NULL; 2010 u8 n, ulen, cxmreg_max; 2011 u16 sz = 0; 2012 2013 n = chip->mon_reg_num; 2014 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2015 "[BTC], %s(): mon_reg_num=%d\n", __func__, n); 2016 2017 if (ver->fcxmreg == 1) 2018 cxmreg_max = CXMREG_MAX; 2019 else if (ver->fcxmreg == 2) 2020 cxmreg_max = CXMREG_MAX_V2; 2021 else 2022 return; 2023 2024 if (n > cxmreg_max) { 2025 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2026 "[BTC], %s(): mon reg count %d > %d\n", 2027 __func__, n, cxmreg_max); 2028 return; 2029 } 2030 2031 ulen = sizeof(monreg->regs[0]); 2032 sz = struct_size(monreg, regs, n); 2033 monreg = kmalloc(sz, GFP_KERNEL); 2034 if (!monreg) 2035 return; 2036 2037 monreg->fver = ver->fcxmreg; 2038 monreg->reg_num = n; 2039 memcpy(monreg->regs, chip->mon_reg, flex_array_size(monreg, regs, n)); 2040 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2041 "[BTC], %s(): sz=%d ulen=%d n=%d\n", 2042 __func__, sz, ulen, n); 2043 2044 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, (u8 *)monreg, sz); 2045 kfree(monreg); 2046 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1); 2047 } 2048 2049 static void _update_dm_step(struct rtw89_dev *rtwdev, 2050 enum btc_reason_and_action reason_or_action) 2051 { 2052 struct rtw89_btc *btc = &rtwdev->btc; 2053 struct rtw89_btc_dm *dm = &btc->dm; 2054 2055 /* use ring-structure to store dm step */ 2056 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action; 2057 dm->dm_step.step_pos++; 2058 2059 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) { 2060 dm->dm_step.step_pos = 0; 2061 dm->dm_step.step_ov = true; 2062 } 2063 } 2064 2065 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 2066 enum btc_reason_and_action action) 2067 { 2068 struct rtw89_btc *btc = &rtwdev->btc; 2069 struct rtw89_btc_dm *dm = &btc->dm; 2070 int ret; 2071 2072 dm->run_action = action; 2073 2074 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT); 2075 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT); 2076 2077 btc->policy_len = 0; 2078 btc->policy_type = policy_type; 2079 2080 _append_tdma(rtwdev); 2081 _append_slot(rtwdev); 2082 2083 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN) 2084 return; 2085 2086 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2087 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n", 2088 __func__, action, policy_type, btc->policy_len); 2089 2090 if (dm->tdma.rxflctrl == CXFLC_NULLP || 2091 dm->tdma.rxflctrl == CXFLC_QOSNULL) 2092 btc->lps = 1; 2093 else 2094 btc->lps = 0; 2095 2096 if (btc->lps == 1) 2097 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps); 2098 2099 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY, 2100 btc->policy, btc->policy_len); 2101 if (!ret) { 2102 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now)); 2103 memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now)); 2104 } 2105 2106 if (btc->update_policy_force) 2107 btc->update_policy_force = false; 2108 2109 if (btc->lps == 0) 2110 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps); 2111 } 2112 2113 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type) 2114 { 2115 struct rtw89_btc *btc = &rtwdev->btc; 2116 const struct rtw89_btc_ver *ver = btc->ver; 2117 struct rtw89_btc_dm *dm = &btc->dm; 2118 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2119 struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para; 2120 2121 switch (type) { 2122 case CXDRVINFO_INIT: 2123 if (ver->fcxinit == 7) 2124 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type); 2125 else 2126 rtw89_fw_h2c_cxdrv_init(rtwdev, type); 2127 break; 2128 case CXDRVINFO_ROLE: 2129 if (ver->fwlrole == 0) 2130 rtw89_fw_h2c_cxdrv_role(rtwdev, type); 2131 else if (ver->fwlrole == 1) 2132 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type); 2133 else if (ver->fwlrole == 2) 2134 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type); 2135 break; 2136 case CXDRVINFO_CTRL: 2137 if (ver->drvinfo_type == 1) 2138 type = 2; 2139 2140 if (ver->fcxctrl == 7) 2141 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type); 2142 else 2143 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type); 2144 break; 2145 case CXDRVINFO_TRX: 2146 if (ver->drvinfo_type == 1) 2147 type = 3; 2148 2149 dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power, 2150 RTW89_BTC_WL_DEF_TX_PWR); 2151 dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain, 2152 RTW89_BTC_WL_DEF_TX_PWR); 2153 dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power, 2154 RTW89_BTC_WL_DEF_TX_PWR); 2155 dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain, 2156 RTW89_BTC_WL_DEF_TX_PWR); 2157 dm->trx_info.cn = wl->cn_report; 2158 dm->trx_info.nhm = wl->nhm.pwr; 2159 rtw89_fw_h2c_cxdrv_trx(rtwdev, type); 2160 break; 2161 case CXDRVINFO_RFK: 2162 if (ver->drvinfo_type == 1) 2163 return; 2164 2165 rtw89_fw_h2c_cxdrv_rfk(rtwdev, type); 2166 break; 2167 case CXDRVINFO_TXPWR: 2168 case CXDRVINFO_FDDT: 2169 case CXDRVINFO_MLO: 2170 case CXDRVINFO_OSI: 2171 default: 2172 break; 2173 } 2174 } 2175 2176 static 2177 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len) 2178 { 2179 struct rtw89_btc *btc = &rtwdev->btc; 2180 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 2181 2182 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2183 "[BTC], %s(): evt_id:%d len:%d\n", 2184 __func__, evt_id, len); 2185 2186 if (!len || !data) 2187 return; 2188 2189 switch (evt_id) { 2190 case BTF_EVNT_RPT: 2191 _parse_btc_report(rtwdev, pfwinfo, data, len); 2192 break; 2193 default: 2194 break; 2195 } 2196 } 2197 2198 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state) 2199 { 2200 struct rtw89_btc *btc = &rtwdev->btc; 2201 struct rtw89_btc_dm *dm = &btc->dm; 2202 struct rtw89_mac_ax_gnt *g = dm->gnt.band; 2203 u8 i; 2204 2205 if (phy_map > BTC_PHY_ALL) 2206 return; 2207 2208 for (i = 0; i < RTW89_PHY_MAX; i++) { 2209 if (!(phy_map & BIT(i))) 2210 continue; 2211 2212 switch (wl_state) { 2213 case BTC_GNT_HW: 2214 g[i].gnt_wl_sw_en = 0; 2215 g[i].gnt_wl = 0; 2216 break; 2217 case BTC_GNT_SW_LO: 2218 g[i].gnt_wl_sw_en = 1; 2219 g[i].gnt_wl = 0; 2220 break; 2221 case BTC_GNT_SW_HI: 2222 g[i].gnt_wl_sw_en = 1; 2223 g[i].gnt_wl = 1; 2224 break; 2225 } 2226 2227 switch (bt_state) { 2228 case BTC_GNT_HW: 2229 g[i].gnt_bt_sw_en = 0; 2230 g[i].gnt_bt = 0; 2231 break; 2232 case BTC_GNT_SW_LO: 2233 g[i].gnt_bt_sw_en = 1; 2234 g[i].gnt_bt = 0; 2235 break; 2236 case BTC_GNT_SW_HI: 2237 g[i].gnt_bt_sw_en = 1; 2238 g[i].gnt_bt = 1; 2239 break; 2240 } 2241 } 2242 2243 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt); 2244 } 2245 2246 #define BTC_TDMA_WLROLE_MAX 2 2247 2248 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable) 2249 { 2250 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2251 "[BTC], %s(): set bt %s wlan_act\n", __func__, 2252 enable ? "ignore" : "do not ignore"); 2253 2254 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1); 2255 } 2256 2257 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0) 2258 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0) 2259 #define WL_TX_POWER_WITH_BT GENMASK(31, 16) 2260 #define WL_TX_POWER_INT_PART GENMASK(8, 2) 2261 #define WL_TX_POWER_FRA_PART GENMASK(1, 0) 2262 #define B_BTC_WL_TX_POWER_SIGN BIT(7) 2263 #define B_TSSI_WL_TX_POWER_SIGN BIT(8) 2264 2265 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level) 2266 { 2267 const struct rtw89_chip_info *chip = rtwdev->chip; 2268 struct rtw89_btc *btc = &rtwdev->btc; 2269 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2270 u32 pwr_val; 2271 2272 if (wl->rf_para.tx_pwr_freerun == level) 2273 return; 2274 2275 wl->rf_para.tx_pwr_freerun = level; 2276 btc->dm.rf_trx_para.wl_tx_power = level; 2277 2278 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2279 "[BTC], %s(): level = %d\n", 2280 __func__, level); 2281 2282 if (level == RTW89_BTC_WL_DEF_TX_PWR) { 2283 pwr_val = WL_TX_POWER_NO_BTC_CTRL; 2284 } else { /* only apply "force tx power" */ 2285 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level); 2286 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR) 2287 pwr_val = RTW89_BTC_WL_DEF_TX_PWR; 2288 2289 if (level & B_BTC_WL_TX_POWER_SIGN) 2290 pwr_val |= B_TSSI_WL_TX_POWER_SIGN; 2291 pwr_val |= WL_TX_POWER_WITH_BT; 2292 } 2293 2294 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val); 2295 } 2296 2297 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) 2298 { 2299 const struct rtw89_chip_info *chip = rtwdev->chip; 2300 struct rtw89_btc *btc = &rtwdev->btc; 2301 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2302 2303 if (wl->rf_para.rx_gain_freerun == level) 2304 return; 2305 2306 wl->rf_para.rx_gain_freerun = level; 2307 btc->dm.rf_trx_para.wl_rx_gain = level; 2308 2309 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2310 "[BTC], %s(): level = %d\n", 2311 __func__, level); 2312 2313 chip->ops->btc_set_wl_rx_gain(rtwdev, level); 2314 } 2315 2316 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level) 2317 { 2318 struct rtw89_btc *btc = &rtwdev->btc; 2319 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2320 int ret; 2321 u8 buf; 2322 2323 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0) 2324 return; 2325 2326 if (bt->rf_para.tx_pwr_freerun == level) 2327 return; 2328 2329 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2330 "[BTC], %s(): level = %d\n", 2331 __func__, level); 2332 2333 buf = (s8)(-level); 2334 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1); 2335 if (!ret) { 2336 bt->rf_para.tx_pwr_freerun = level; 2337 btc->dm.rf_trx_para.bt_tx_power = level; 2338 } 2339 } 2340 2341 #define BTC_BT_RX_NORMAL_LVL 7 2342 2343 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level) 2344 { 2345 struct rtw89_btc *btc = &rtwdev->btc; 2346 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2347 2348 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0) 2349 return; 2350 2351 if ((bt->rf_para.rx_gain_freerun == level || 2352 level > BTC_BT_RX_NORMAL_LVL) && 2353 (!rtwdev->chip->scbd || bt->lna_constrain == level)) 2354 return; 2355 2356 bt->rf_para.rx_gain_freerun = level; 2357 btc->dm.rf_trx_para.bt_rx_gain = level; 2358 2359 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2360 "[BTC], %s(): level = %d\n", 2361 __func__, level); 2362 2363 if (level == BTC_BT_RX_NORMAL_LVL) 2364 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false); 2365 else 2366 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true); 2367 2368 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level)); 2369 } 2370 2371 static void _set_rf_trx_para(struct rtw89_dev *rtwdev) 2372 { 2373 const struct rtw89_chip_info *chip = rtwdev->chip; 2374 struct rtw89_btc *btc = &rtwdev->btc; 2375 const struct rtw89_btc_ver *ver = btc->ver; 2376 struct rtw89_btc_dm *dm = &btc->dm; 2377 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2378 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2379 struct rtw89_btc_bt_link_info *b = &bt->link_info; 2380 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; 2381 struct rtw89_btc_rf_trx_para para; 2382 u32 wl_stb_chg = 0; 2383 u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0; 2384 2385 if (ver->fwlrole == 0) { 2386 link_mode = wl->role_info.link_mode; 2387 for (i = 0; i < RTW89_PHY_MAX; i++) { 2388 if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G) 2389 dbcc_2g_phy = i; 2390 } 2391 } else if (ver->fwlrole == 1) { 2392 link_mode = wl->role_info_v1.link_mode; 2393 dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy; 2394 } else if (ver->fwlrole == 2) { 2395 link_mode = wl->role_info_v2.link_mode; 2396 dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy; 2397 } 2398 2399 /* decide trx_para_level */ 2400 if (btc->ant_type == BTC_ANT_SHARED) { 2401 /* fix LNA2 + TIA gain not change by GNT_BT */ 2402 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) || 2403 dm->bt_only == 1) 2404 dm->trx_para_level = 1; /* for better BT ACI issue */ 2405 else 2406 dm->trx_para_level = 0; 2407 } else { /* non-shared antenna */ 2408 dm->trx_para_level = 5; 2409 /* modify trx_para if WK 2.4G-STA-DL + bt link */ 2410 if (b->profile_cnt.now != 0 && 2411 link_mode == BTC_WLINK_2G_STA && 2412 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */ 2413 if (wl->rssi_level == 4 && bt->rssi_level > 2) 2414 dm->trx_para_level = 6; 2415 else if (wl->rssi_level == 3 && bt->rssi_level > 3) 2416 dm->trx_para_level = 7; 2417 } 2418 } 2419 2420 level_id = dm->trx_para_level; 2421 if (level_id >= chip->rf_para_dlink_num || 2422 level_id >= chip->rf_para_ulink_num) { 2423 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2424 "[BTC], %s(): invalid level_id: %d\n", 2425 __func__, level_id); 2426 return; 2427 } 2428 2429 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 2430 para = chip->rf_para_ulink[level_id]; 2431 else 2432 para = chip->rf_para_dlink[level_id]; 2433 2434 if (dm->fddt_train) { 2435 _set_wl_rx_gain(rtwdev, 1); 2436 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true); 2437 } else { 2438 _set_wl_tx_power(rtwdev, para.wl_tx_power); 2439 _set_wl_rx_gain(rtwdev, para.wl_rx_gain); 2440 _set_bt_tx_power(rtwdev, para.bt_tx_power); 2441 _set_bt_rx_gain(rtwdev, para.bt_rx_gain); 2442 } 2443 2444 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off || 2445 wl_smap->lps == BTC_LPS_RF_OFF || 2446 link_mode == BTC_WLINK_5G || 2447 link_mode == BTC_WLINK_NOLINK || 2448 (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1)) 2449 wl_stb_chg = 0; 2450 else 2451 wl_stb_chg = 1; 2452 2453 if (wl_stb_chg != dm->wl_stb_chg) { 2454 dm->wl_stb_chg = wl_stb_chg; 2455 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 2456 } 2457 } 2458 2459 static void _update_btc_state_map(struct rtw89_dev *rtwdev) 2460 { 2461 struct rtw89_btc *btc = &rtwdev->btc; 2462 struct rtw89_btc_cx *cx = &btc->cx; 2463 struct rtw89_btc_wl_info *wl = &cx->wl; 2464 struct rtw89_btc_bt_info *bt = &cx->bt; 2465 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 2466 2467 if (wl->status.map.connecting || wl->status.map._4way || 2468 wl->status.map.roaming) { 2469 cx->state_map = BTC_WLINKING; 2470 } else if (wl->status.map.scan) { /* wl scan */ 2471 if (bt_linfo->status.map.inq_pag) 2472 cx->state_map = BTC_WSCAN_BSCAN; 2473 else 2474 cx->state_map = BTC_WSCAN_BNOSCAN; 2475 } else if (wl->status.map.busy) { /* only busy */ 2476 if (bt_linfo->status.map.inq_pag) 2477 cx->state_map = BTC_WBUSY_BSCAN; 2478 else 2479 cx->state_map = BTC_WBUSY_BNOSCAN; 2480 } else { /* wl idle */ 2481 cx->state_map = BTC_WIDLE; 2482 } 2483 } 2484 2485 static void _set_bt_afh_info(struct rtw89_dev *rtwdev) 2486 { 2487 const struct rtw89_chip_info *chip = rtwdev->chip; 2488 struct rtw89_btc *btc = &rtwdev->btc; 2489 const struct rtw89_btc_ver *ver = btc->ver; 2490 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2491 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2492 struct rtw89_btc_bt_link_info *b = &bt->link_info; 2493 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 2494 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 2495 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 2496 struct rtw89_btc_wl_active_role *r; 2497 struct rtw89_btc_wl_active_role_v1 *r1; 2498 struct rtw89_btc_wl_active_role_v2 *r2; 2499 u8 en = 0, i, ch = 0, bw = 0; 2500 u8 mode, connect_cnt; 2501 2502 if (btc->manual_ctrl || wl->status.map.scan) 2503 return; 2504 2505 if (ver->fwlrole == 0) { 2506 mode = wl_rinfo->link_mode; 2507 connect_cnt = wl_rinfo->connect_cnt; 2508 } else if (ver->fwlrole == 1) { 2509 mode = wl_rinfo_v1->link_mode; 2510 connect_cnt = wl_rinfo_v1->connect_cnt; 2511 } else if (ver->fwlrole == 2) { 2512 mode = wl_rinfo_v2->link_mode; 2513 connect_cnt = wl_rinfo_v2->connect_cnt; 2514 } else { 2515 return; 2516 } 2517 2518 if (wl->status.map.rf_off || bt->whql_test || 2519 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G || 2520 connect_cnt > BTC_TDMA_WLROLE_MAX) { 2521 en = false; 2522 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) { 2523 en = true; 2524 /* get p2p channel */ 2525 for (i = 0; i < RTW89_PORT_NUM; i++) { 2526 r = &wl_rinfo->active_role[i]; 2527 r1 = &wl_rinfo_v1->active_role_v1[i]; 2528 r2 = &wl_rinfo_v2->active_role_v2[i]; 2529 2530 if (ver->fwlrole == 0 && 2531 (r->role == RTW89_WIFI_ROLE_P2P_GO || 2532 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 2533 ch = r->ch; 2534 bw = r->bw; 2535 break; 2536 } else if (ver->fwlrole == 1 && 2537 (r1->role == RTW89_WIFI_ROLE_P2P_GO || 2538 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 2539 ch = r1->ch; 2540 bw = r1->bw; 2541 break; 2542 } else if (ver->fwlrole == 2 && 2543 (r2->role == RTW89_WIFI_ROLE_P2P_GO || 2544 r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 2545 ch = r2->ch; 2546 bw = r2->bw; 2547 break; 2548 } 2549 } 2550 } else { 2551 en = true; 2552 /* get 2g channel */ 2553 for (i = 0; i < RTW89_PORT_NUM; i++) { 2554 r = &wl_rinfo->active_role[i]; 2555 r1 = &wl_rinfo_v1->active_role_v1[i]; 2556 r2 = &wl_rinfo_v2->active_role_v2[i]; 2557 2558 if (ver->fwlrole == 0 && 2559 r->connected && r->band == RTW89_BAND_2G) { 2560 ch = r->ch; 2561 bw = r->bw; 2562 break; 2563 } else if (ver->fwlrole == 1 && 2564 r1->connected && r1->band == RTW89_BAND_2G) { 2565 ch = r1->ch; 2566 bw = r1->bw; 2567 break; 2568 } else if (ver->fwlrole == 2 && 2569 r2->connected && r2->band == RTW89_BAND_2G) { 2570 ch = r2->ch; 2571 bw = r2->bw; 2572 break; 2573 } 2574 } 2575 } 2576 2577 switch (bw) { 2578 case RTW89_CHANNEL_WIDTH_20: 2579 bw = 20 + chip->afh_guard_ch * 2; 2580 break; 2581 case RTW89_CHANNEL_WIDTH_40: 2582 bw = 40 + chip->afh_guard_ch * 2; 2583 break; 2584 case RTW89_CHANNEL_WIDTH_5: 2585 bw = 5 + chip->afh_guard_ch * 2; 2586 break; 2587 case RTW89_CHANNEL_WIDTH_10: 2588 bw = 10 + chip->afh_guard_ch * 2; 2589 break; 2590 default: 2591 bw = 0; 2592 en = false; /* turn off AFH info if BW > 40 */ 2593 break; 2594 } 2595 2596 if (wl->afh_info.en == en && 2597 wl->afh_info.ch == ch && 2598 wl->afh_info.bw == bw && 2599 b->profile_cnt.last == b->profile_cnt.now) { 2600 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2601 "[BTC], %s(): return because no change!\n", 2602 __func__); 2603 return; 2604 } 2605 2606 wl->afh_info.en = en; 2607 wl->afh_info.ch = ch; 2608 wl->afh_info.bw = bw; 2609 2610 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3); 2611 2612 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2613 "[BTC], %s(): en=%d, ch=%d, bw=%d\n", 2614 __func__, en, ch, bw); 2615 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; 2616 } 2617 2618 static bool _check_freerun(struct rtw89_dev *rtwdev) 2619 { 2620 struct rtw89_btc *btc = &rtwdev->btc; 2621 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2622 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2623 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 2624 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 2625 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 2626 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc; 2627 union rtw89_btc_module_info *md = &btc->mdinfo; 2628 const struct rtw89_btc_ver *ver = btc->ver; 2629 u8 isolation; 2630 2631 if (ver->fcxinit == 7) 2632 isolation = md->md_v7.ant.isolation; 2633 else 2634 isolation = md->md.ant.isolation; 2635 2636 if (btc->ant_type == BTC_ANT_SHARED) { 2637 btc->dm.trx_para_level = 0; 2638 return false; 2639 } 2640 2641 /* The below is dedicated antenna case */ 2642 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX || 2643 wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) { 2644 btc->dm.trx_para_level = 5; 2645 return true; 2646 } 2647 2648 if (bt_linfo->profile_cnt.now == 0) { 2649 btc->dm.trx_para_level = 5; 2650 return true; 2651 } 2652 2653 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) { 2654 btc->dm.trx_para_level = 5; 2655 return true; 2656 } 2657 2658 /* TODO get isolation by BT psd */ 2659 if (isolation >= BTC_FREERUN_ANTISO_MIN) { 2660 btc->dm.trx_para_level = 5; 2661 return true; 2662 } 2663 2664 if (!wl->status.map.busy) {/* wl idle -> freerun */ 2665 btc->dm.trx_para_level = 5; 2666 return true; 2667 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */ 2668 btc->dm.trx_para_level = 0; 2669 return false; 2670 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 2671 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) { 2672 btc->dm.trx_para_level = 6; 2673 return true; 2674 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) { 2675 btc->dm.trx_para_level = 7; 2676 return true; 2677 } 2678 btc->dm.trx_para_level = 0; 2679 return false; 2680 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) { 2681 if (bt_linfo->rssi > 28) { 2682 btc->dm.trx_para_level = 6; 2683 return true; 2684 } 2685 } 2686 2687 btc->dm.trx_para_level = 0; 2688 return false; 2689 } 2690 2691 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; }) 2692 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; }) 2693 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; }) 2694 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; }) 2695 2696 #define _slot_set(btc, sid, dura, tbl, type) \ 2697 do { \ 2698 typeof(sid) _sid = (sid); \ 2699 typeof(btc) _btc = (btc); \ 2700 _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\ 2701 _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \ 2702 _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \ 2703 } while (0) 2704 2705 #define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura) 2706 #define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl) 2707 #define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type) 2708 2709 struct btc_btinfo_lb2 { 2710 u8 connect: 1; 2711 u8 sco_busy: 1; 2712 u8 inq_pag: 1; 2713 u8 acl_busy: 1; 2714 u8 hfp: 1; 2715 u8 hid: 1; 2716 u8 a2dp: 1; 2717 u8 pan: 1; 2718 }; 2719 2720 struct btc_btinfo_lb3 { 2721 u8 retry: 4; 2722 u8 cqddr: 1; 2723 u8 inq: 1; 2724 u8 mesh_busy: 1; 2725 u8 pag: 1; 2726 }; 2727 2728 struct btc_btinfo_hb0 { 2729 s8 rssi; 2730 }; 2731 2732 struct btc_btinfo_hb1 { 2733 u8 ble_connect: 1; 2734 u8 reinit: 1; 2735 u8 relink: 1; 2736 u8 igno_wl: 1; 2737 u8 voice: 1; 2738 u8 ble_scan: 1; 2739 u8 role_sw: 1; 2740 u8 multi_link: 1; 2741 }; 2742 2743 struct btc_btinfo_hb2 { 2744 u8 pan_active: 1; 2745 u8 afh_update: 1; 2746 u8 a2dp_active: 1; 2747 u8 slave: 1; 2748 u8 hid_slot: 2; 2749 u8 hid_cnt: 2; 2750 }; 2751 2752 struct btc_btinfo_hb3 { 2753 u8 a2dp_bitpool: 6; 2754 u8 tx_3m: 1; 2755 u8 a2dp_sink: 1; 2756 }; 2757 2758 union btc_btinfo { 2759 u8 val; 2760 struct btc_btinfo_lb2 lb2; 2761 struct btc_btinfo_lb3 lb3; 2762 struct btc_btinfo_hb0 hb0; 2763 struct btc_btinfo_hb1 hb1; 2764 struct btc_btinfo_hb2 hb2; 2765 struct btc_btinfo_hb3 hb3; 2766 }; 2767 2768 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 2769 enum btc_reason_and_action action) 2770 { 2771 const struct rtw89_chip_info *chip = rtwdev->chip; 2772 2773 chip->ops->btc_set_policy(rtwdev, policy_type); 2774 _fw_set_policy(rtwdev, policy_type, action); 2775 } 2776 2777 #define BTC_B1_MAX 250 /* unit ms */ 2778 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type) 2779 { 2780 struct rtw89_btc *btc = &rtwdev->btc; 2781 struct rtw89_btc_dm *dm = &btc->dm; 2782 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 2783 struct rtw89_btc_fbtc_slot *s = dm->slot; 2784 u8 type; 2785 u32 tbl_w1, tbl_b1, tbl_b4; 2786 2787 if (btc->ant_type == BTC_ANT_SHARED) { 2788 if (btc->cx.wl.status.map._4way) 2789 tbl_w1 = cxtbl[1]; 2790 else 2791 tbl_w1 = cxtbl[8]; 2792 tbl_b1 = cxtbl[3]; 2793 tbl_b4 = cxtbl[3]; 2794 } else { 2795 tbl_w1 = cxtbl[16]; 2796 tbl_b1 = cxtbl[17]; 2797 tbl_b4 = cxtbl[17]; 2798 } 2799 2800 type = (u8)((policy_type & BTC_CXP_MASK) >> 8); 2801 btc->bt_req_en = false; 2802 2803 switch (type) { 2804 case BTC_CXP_USERDEF0: 2805 *t = t_def[CXTD_OFF]; 2806 s[CXST_OFF] = s_def[CXST_OFF]; 2807 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2808 btc->update_policy_force = true; 2809 break; 2810 case BTC_CXP_OFF: /* TDMA off */ 2811 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2812 *t = t_def[CXTD_OFF]; 2813 s[CXST_OFF] = s_def[CXST_OFF]; 2814 2815 switch (policy_type) { 2816 case BTC_CXP_OFF_BT: 2817 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2818 break; 2819 case BTC_CXP_OFF_WL: 2820 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 2821 break; 2822 case BTC_CXP_OFF_EQ0: 2823 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 2824 break; 2825 case BTC_CXP_OFF_EQ1: 2826 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 2827 break; 2828 case BTC_CXP_OFF_EQ2: 2829 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 2830 break; 2831 case BTC_CXP_OFF_EQ3: 2832 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 2833 break; 2834 case BTC_CXP_OFF_BWB0: 2835 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 2836 break; 2837 case BTC_CXP_OFF_BWB1: 2838 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2839 break; 2840 case BTC_CXP_OFF_BWB3: 2841 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 2842 break; 2843 } 2844 break; 2845 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 2846 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2847 *t = t_def[CXTD_OFF_B2]; 2848 s[CXST_OFF] = s_def[CXST_OFF]; 2849 switch (policy_type) { 2850 case BTC_CXP_OFFB_BWB0: 2851 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2852 break; 2853 } 2854 break; 2855 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 2856 btc->bt_req_en = true; 2857 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2858 *t = t_def[CXTD_OFF_EXT]; 2859 switch (policy_type) { 2860 case BTC_CXP_OFFE_DEF: 2861 s[CXST_E2G] = s_def[CXST_E2G]; 2862 s[CXST_E5G] = s_def[CXST_E5G]; 2863 s[CXST_EBT] = s_def[CXST_EBT]; 2864 s[CXST_ENULL] = s_def[CXST_ENULL]; 2865 break; 2866 case BTC_CXP_OFFE_DEF2: 2867 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 2868 s[CXST_E5G] = s_def[CXST_E5G]; 2869 s[CXST_EBT] = s_def[CXST_EBT]; 2870 s[CXST_ENULL] = s_def[CXST_ENULL]; 2871 break; 2872 } 2873 break; 2874 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 2875 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2876 *t = t_def[CXTD_FIX]; 2877 switch (policy_type) { 2878 case BTC_CXP_FIX_TD3030: 2879 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2880 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2881 break; 2882 case BTC_CXP_FIX_TD5050: 2883 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2884 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2885 break; 2886 case BTC_CXP_FIX_TD2030: 2887 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2888 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2889 break; 2890 case BTC_CXP_FIX_TD4010: 2891 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 2892 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2893 break; 2894 case BTC_CXP_FIX_TD4010ISO: 2895 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 2896 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2897 break; 2898 case BTC_CXP_FIX_TD4010ISO_DL: 2899 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 2900 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 2901 break; 2902 case BTC_CXP_FIX_TD4010ISO_UL: 2903 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 2904 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 2905 break; 2906 case BTC_CXP_FIX_TD7010: 2907 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 2908 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2909 break; 2910 case BTC_CXP_FIX_TD2060: 2911 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2912 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2913 break; 2914 case BTC_CXP_FIX_TD3060: 2915 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2916 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2917 break; 2918 case BTC_CXP_FIX_TD2080: 2919 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2920 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2921 break; 2922 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 2923 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2924 tbl_w1, SLOT_ISO); 2925 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2926 tbl_b1, SLOT_MIX); 2927 break; 2928 } 2929 break; 2930 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 2931 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2932 *t = t_def[CXTD_PFIX]; 2933 if (btc->cx.wl.role_info.role_map.role.ap) 2934 _tdma_set_flctrl(btc, CXFLC_QOSNULL); 2935 2936 switch (policy_type) { 2937 case BTC_CXP_PFIX_TD3030: 2938 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2939 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2940 break; 2941 case BTC_CXP_PFIX_TD5050: 2942 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2943 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2944 break; 2945 case BTC_CXP_PFIX_TD2030: 2946 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2947 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2948 break; 2949 case BTC_CXP_PFIX_TD2060: 2950 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2951 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2952 break; 2953 case BTC_CXP_PFIX_TD3070: 2954 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2955 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2956 break; 2957 case BTC_CXP_PFIX_TD2080: 2958 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2959 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2960 break; 2961 } 2962 break; 2963 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 2964 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2965 *t = t_def[CXTD_AUTO]; 2966 switch (policy_type) { 2967 case BTC_CXP_AUTO_TD50B1: 2968 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2969 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2970 break; 2971 case BTC_CXP_AUTO_TD60B1: 2972 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2973 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2974 break; 2975 case BTC_CXP_AUTO_TD20B1: 2976 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2977 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2978 break; 2979 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 2980 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2981 tbl_w1, SLOT_ISO); 2982 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2983 tbl_b1, SLOT_MIX); 2984 break; 2985 } 2986 break; 2987 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 2988 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2989 *t = t_def[CXTD_PAUTO]; 2990 switch (policy_type) { 2991 case BTC_CXP_PAUTO_TD50B1: 2992 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2993 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2994 break; 2995 case BTC_CXP_PAUTO_TD60B1: 2996 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2997 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2998 break; 2999 case BTC_CXP_PAUTO_TD20B1: 3000 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3001 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3002 break; 3003 case BTC_CXP_PAUTO_TDW1B1: 3004 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3005 tbl_w1, SLOT_ISO); 3006 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3007 tbl_b1, SLOT_MIX); 3008 break; 3009 } 3010 break; 3011 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 3012 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3013 *t = t_def[CXTD_AUTO2]; 3014 switch (policy_type) { 3015 case BTC_CXP_AUTO2_TD3050: 3016 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3017 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3018 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3019 break; 3020 case BTC_CXP_AUTO2_TD3070: 3021 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3022 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3023 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3024 break; 3025 case BTC_CXP_AUTO2_TD5050: 3026 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3027 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3028 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3029 break; 3030 case BTC_CXP_AUTO2_TD6060: 3031 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3032 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3033 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3034 break; 3035 case BTC_CXP_AUTO2_TD2080: 3036 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3037 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3038 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3039 break; 3040 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 3041 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3042 tbl_w1, SLOT_ISO); 3043 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3044 tbl_b4, SLOT_MIX); 3045 break; 3046 } 3047 break; 3048 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 3049 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3050 *t = t_def[CXTD_PAUTO2]; 3051 switch (policy_type) { 3052 case BTC_CXP_PAUTO2_TD3050: 3053 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3054 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3055 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3056 break; 3057 case BTC_CXP_PAUTO2_TD3070: 3058 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3059 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3060 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3061 break; 3062 case BTC_CXP_PAUTO2_TD5050: 3063 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3064 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3065 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3066 break; 3067 case BTC_CXP_PAUTO2_TD6060: 3068 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3069 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3070 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3071 break; 3072 case BTC_CXP_PAUTO2_TD2080: 3073 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3074 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3075 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3076 break; 3077 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 3078 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3079 tbl_w1, SLOT_ISO); 3080 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3081 tbl_b4, SLOT_MIX); 3082 break; 3083 } 3084 break; 3085 } 3086 } 3087 EXPORT_SYMBOL(rtw89_btc_set_policy); 3088 3089 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) 3090 { 3091 struct rtw89_btc *btc = &rtwdev->btc; 3092 struct rtw89_btc_dm *dm = &btc->dm; 3093 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 3094 struct rtw89_btc_fbtc_slot *s = dm->slot; 3095 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1; 3096 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc; 3097 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc; 3098 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3099 u8 type, null_role; 3100 u32 tbl_w1, tbl_b1, tbl_b4; 3101 3102 type = FIELD_GET(BTC_CXP_MASK, policy_type); 3103 3104 if (btc->ant_type == BTC_ANT_SHARED) { 3105 if (btc->cx.wl.status.map._4way) 3106 tbl_w1 = cxtbl[1]; 3107 else if (hid->exist && hid->type == BTC_HID_218) 3108 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */ 3109 else 3110 tbl_w1 = cxtbl[8]; 3111 3112 if (dm->leak_ap && 3113 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) { 3114 tbl_b1 = cxtbl[3]; 3115 tbl_b4 = cxtbl[3]; 3116 } else if (hid->exist && hid->type == BTC_HID_218) { 3117 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */ 3118 tbl_b4 = cxtbl[4]; 3119 } else { 3120 tbl_b1 = cxtbl[2]; 3121 tbl_b4 = cxtbl[2]; 3122 } 3123 } else { 3124 tbl_b1 = cxtbl[17]; 3125 tbl_b4 = cxtbl[17]; 3126 3127 if (wl->bg_mode) 3128 tbl_w1 = cxtbl[8]; 3129 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) && 3130 hid->exist) 3131 tbl_w1 = cxtbl[19]; 3132 else 3133 tbl_w1 = cxtbl[16]; 3134 } 3135 3136 btc->bt_req_en = false; 3137 3138 switch (type) { 3139 case BTC_CXP_USERDEF0: 3140 btc->update_policy_force = true; 3141 *t = t_def[CXTD_OFF]; 3142 s[CXST_OFF] = s_def[CXST_OFF]; 3143 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 3144 break; 3145 case BTC_CXP_OFF: /* TDMA off */ 3146 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 3147 *t = t_def[CXTD_OFF]; 3148 s[CXST_OFF] = s_def[CXST_OFF]; 3149 3150 switch (policy_type) { 3151 case BTC_CXP_OFF_BT: 3152 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 3153 break; 3154 case BTC_CXP_OFF_WL: 3155 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 3156 break; 3157 case BTC_CXP_OFF_EQ0: 3158 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 3159 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 3160 break; 3161 case BTC_CXP_OFF_EQ1: 3162 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 3163 break; 3164 case BTC_CXP_OFF_EQ2: 3165 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 3166 break; 3167 case BTC_CXP_OFF_EQ3: 3168 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); 3169 break; 3170 case BTC_CXP_OFF_BWB0: 3171 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 3172 break; 3173 case BTC_CXP_OFF_BWB1: 3174 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 3175 break; 3176 case BTC_CXP_OFF_BWB2: 3177 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 3178 break; 3179 case BTC_CXP_OFF_BWB3: 3180 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 3181 break; 3182 default: 3183 break; 3184 } 3185 break; 3186 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 3187 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 3188 *t = t_def[CXTD_OFF_B2]; 3189 s[CXST_OFF] = s_def[CXST_OFF]; 3190 3191 switch (policy_type) { 3192 case BTC_CXP_OFFB_BWB0: 3193 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 3194 break; 3195 default: 3196 break; 3197 } 3198 break; 3199 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 3200 btc->bt_req_en = true; 3201 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3202 *t = t_def[CXTD_OFF_EXT]; 3203 3204 /* To avoid wl-s0 tx break by hid/hfp tx */ 3205 if (hid->exist || hfp->exist) 3206 tbl_w1 = cxtbl[16]; 3207 3208 switch (policy_type) { 3209 case BTC_CXP_OFFE_DEF: 3210 s[CXST_E2G] = s_def[CXST_E2G]; 3211 s[CXST_E5G] = s_def[CXST_E5G]; 3212 s[CXST_EBT] = s_def[CXST_EBT]; 3213 s[CXST_ENULL] = s_def[CXST_ENULL]; 3214 break; 3215 case BTC_CXP_OFFE_DEF2: 3216 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 3217 s[CXST_E5G] = s_def[CXST_E5G]; 3218 s[CXST_EBT] = s_def[CXST_EBT]; 3219 s[CXST_ENULL] = s_def[CXST_ENULL]; 3220 break; 3221 default: 3222 break; 3223 } 3224 s[CXST_OFF] = s_def[CXST_OFF]; 3225 break; 3226 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 3227 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3228 *t = t_def[CXTD_FIX]; 3229 3230 switch (policy_type) { 3231 case BTC_CXP_FIX_TD3030: 3232 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3233 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3234 break; 3235 case BTC_CXP_FIX_TD5050: 3236 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3237 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 3238 break; 3239 case BTC_CXP_FIX_TD2030: 3240 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3241 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3242 break; 3243 case BTC_CXP_FIX_TD4010: 3244 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 3245 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3246 break; 3247 case BTC_CXP_FIX_TD4010ISO: 3248 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 3249 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3250 break; 3251 case BTC_CXP_FIX_TD4010ISO_DL: 3252 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 3253 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 3254 break; 3255 case BTC_CXP_FIX_TD4010ISO_UL: 3256 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 3257 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 3258 break; 3259 case BTC_CXP_FIX_TD7010: 3260 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 3261 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3262 break; 3263 case BTC_CXP_FIX_TD2060: 3264 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3265 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3266 break; 3267 case BTC_CXP_FIX_TD3060: 3268 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3269 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3270 break; 3271 case BTC_CXP_FIX_TD2080: 3272 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3273 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 3274 break; 3275 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 3276 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3277 tbl_w1, SLOT_ISO); 3278 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3279 tbl_b1, SLOT_MIX); 3280 break; 3281 default: 3282 break; 3283 } 3284 break; 3285 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 3286 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3287 *t = t_def[CXTD_PFIX]; 3288 3289 switch (policy_type) { 3290 case BTC_CXP_PFIX_TD3030: 3291 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3292 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3293 break; 3294 case BTC_CXP_PFIX_TD5050: 3295 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3296 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 3297 break; 3298 case BTC_CXP_PFIX_TD2030: 3299 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3300 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3301 break; 3302 case BTC_CXP_PFIX_TD2060: 3303 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3304 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3305 break; 3306 case BTC_CXP_PFIX_TD3070: 3307 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3308 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3309 break; 3310 case BTC_CXP_PFIX_TD2080: 3311 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3312 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 3313 break; 3314 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */ 3315 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3316 tbl_w1, SLOT_ISO); 3317 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3318 tbl_b1, SLOT_MIX); 3319 break; 3320 default: 3321 break; 3322 } 3323 break; 3324 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 3325 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3326 *t = t_def[CXTD_AUTO]; 3327 3328 switch (policy_type) { 3329 case BTC_CXP_AUTO_TD50B1: 3330 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3331 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3332 break; 3333 case BTC_CXP_AUTO_TD60B1: 3334 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3335 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3336 break; 3337 case BTC_CXP_AUTO_TD20B1: 3338 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3339 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3340 break; 3341 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 3342 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3343 tbl_w1, SLOT_ISO); 3344 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3345 tbl_b1, SLOT_MIX); 3346 break; 3347 default: 3348 break; 3349 } 3350 break; 3351 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 3352 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3353 *t = t_def[CXTD_PAUTO]; 3354 3355 switch (policy_type) { 3356 case BTC_CXP_PAUTO_TD50B1: 3357 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3358 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3359 break; 3360 case BTC_CXP_PAUTO_TD60B1: 3361 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3362 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3363 break; 3364 case BTC_CXP_PAUTO_TD20B1: 3365 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3366 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3367 break; 3368 case BTC_CXP_PAUTO_TDW1B1: 3369 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3370 tbl_w1, SLOT_ISO); 3371 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3372 tbl_b1, SLOT_MIX); 3373 break; 3374 default: 3375 break; 3376 } 3377 break; 3378 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 3379 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3380 *t = t_def[CXTD_AUTO2]; 3381 3382 switch (policy_type) { 3383 case BTC_CXP_AUTO2_TD3050: 3384 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3385 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3386 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3387 break; 3388 case BTC_CXP_AUTO2_TD3070: 3389 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3390 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3391 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3392 break; 3393 case BTC_CXP_AUTO2_TD5050: 3394 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3395 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3396 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3397 break; 3398 case BTC_CXP_AUTO2_TD6060: 3399 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3400 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3401 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3402 break; 3403 case BTC_CXP_AUTO2_TD2080: 3404 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3405 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3406 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3407 break; 3408 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 3409 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3410 tbl_w1, SLOT_ISO); 3411 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3412 tbl_b1, SLOT_MIX); 3413 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3414 tbl_b4, SLOT_MIX); 3415 break; 3416 default: 3417 break; 3418 } 3419 break; 3420 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 3421 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3422 *t = t_def[CXTD_PAUTO2]; 3423 3424 switch (policy_type) { 3425 case BTC_CXP_PAUTO2_TD3050: 3426 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3427 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3428 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3429 break; 3430 case BTC_CXP_PAUTO2_TD3070: 3431 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3432 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3433 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3434 break; 3435 case BTC_CXP_PAUTO2_TD5050: 3436 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3437 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3438 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3439 break; 3440 case BTC_CXP_PAUTO2_TD6060: 3441 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3442 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3443 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3444 break; 3445 case BTC_CXP_PAUTO2_TD2080: 3446 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3447 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3448 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3449 break; 3450 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 3451 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3452 tbl_w1, SLOT_ISO); 3453 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3454 tbl_b1, SLOT_MIX); 3455 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3456 tbl_b4, SLOT_MIX); 3457 break; 3458 default: 3459 break; 3460 } 3461 break; 3462 } 3463 3464 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) { 3465 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) | 3466 FIELD_PREP(0xf0, dm->wl_scc.null_role2); 3467 _tdma_set_flctrl_role(btc, null_role); 3468 } 3469 3470 /* enter leak_slot after each null-1 */ 3471 if (dm->leak_ap && dm->tdma.leak_n > 1) 3472 _tdma_set_lek(btc, 1); 3473 3474 if (dm->tdma_instant_excute) { 3475 btc->dm.tdma.option_ctrl |= BIT(0); 3476 btc->update_policy_force = true; 3477 } 3478 } 3479 EXPORT_SYMBOL(rtw89_btc_set_policy_v1); 3480 3481 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map, 3482 u8 tx_val, u8 rx_val) 3483 { 3484 struct rtw89_mac_ax_plt plt; 3485 3486 plt.band = RTW89_MAC_0; 3487 plt.tx = tx_val; 3488 plt.rx = rx_val; 3489 3490 if (phy_map & BTC_PHY_0) 3491 rtw89_mac_cfg_plt(rtwdev, &plt); 3492 3493 if (!rtwdev->dbcc_en) 3494 return; 3495 3496 plt.band = RTW89_MAC_1; 3497 if (phy_map & BTC_PHY_1) 3498 rtw89_mac_cfg_plt(rtwdev, &plt); 3499 } 3500 3501 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec, 3502 u8 phy_map, u8 type) 3503 { 3504 struct rtw89_btc *btc = &rtwdev->btc; 3505 struct rtw89_btc_dm *dm = &btc->dm; 3506 struct rtw89_btc_cx *cx = &btc->cx; 3507 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3508 struct rtw89_btc_bt_info *bt = &cx->bt; 3509 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 3510 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0; 3511 u32 ant_path_type; 3512 3513 ant_path_type = ((phy_map << 8) + type); 3514 3515 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF || 3516 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE || 3517 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX) 3518 force_exec = FC_EXEC; 3519 3520 if (!force_exec && ant_path_type == dm->set_ant_path) { 3521 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3522 "[BTC], %s(): return by no change!!\n", 3523 __func__); 3524 return; 3525 } else if (bt->rfk_info.map.run) { 3526 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3527 "[BTC], %s(): return by bt rfk!!\n", __func__); 3528 return; 3529 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 3530 wl->rfk_info.state != BTC_WRFK_STOP) { 3531 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3532 "[BTC], %s(): return by wl rfk!!\n", __func__); 3533 return; 3534 } 3535 3536 dm->set_ant_path = ant_path_type; 3537 3538 rtw89_debug(rtwdev, 3539 RTW89_DBG_BTC, 3540 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 3541 __func__, phy_map, dm->set_ant_path & 0xff); 3542 3543 switch (type) { 3544 case BTC_ANT_WPOWERON: 3545 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 3546 break; 3547 case BTC_ANT_WINIT: 3548 if (bt->enable.now) 3549 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 3550 else 3551 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 3552 3553 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3554 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT); 3555 break; 3556 case BTC_ANT_WONLY: 3557 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 3558 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3559 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3560 break; 3561 case BTC_ANT_WOFF: 3562 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 3563 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3564 break; 3565 case BTC_ANT_W2G: 3566 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3567 if (rtwdev->dbcc_en) { 3568 for (i = 0; i < RTW89_PHY_MAX; i++) { 3569 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G); 3570 3571 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 3572 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 3573 /* BT should control by GNT_BT if WL_2G at S0 */ 3574 if (i == 1 && 3575 wl_dinfo->real_band[0] == RTW89_BAND_2G && 3576 wl_dinfo->real_band[1] == RTW89_BAND_5G) 3577 gnt_bt_ctrl = BTC_GNT_HW; 3578 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl); 3579 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE; 3580 _set_bt_plut(rtwdev, BIT(i), 3581 plt_ctrl, plt_ctrl); 3582 } 3583 } else { 3584 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 3585 _set_bt_plut(rtwdev, BTC_PHY_ALL, 3586 BTC_PLT_BT, BTC_PLT_BT); 3587 } 3588 break; 3589 case BTC_ANT_W5G: 3590 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3591 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW); 3592 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3593 break; 3594 case BTC_ANT_W25G: 3595 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3596 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 3597 _set_bt_plut(rtwdev, BTC_PHY_ALL, 3598 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 3599 break; 3600 case BTC_ANT_FREERUN: 3601 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3602 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI); 3603 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3604 break; 3605 case BTC_ANT_WRFK: 3606 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3607 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 3608 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 3609 break; 3610 case BTC_ANT_BRFK: 3611 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 3612 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 3613 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 3614 break; 3615 default: 3616 break; 3617 } 3618 } 3619 3620 static void _action_wl_only(struct rtw89_dev *rtwdev) 3621 { 3622 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 3623 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY); 3624 } 3625 3626 static void _action_wl_init(struct rtw89_dev *rtwdev) 3627 { 3628 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3629 3630 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT); 3631 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT); 3632 } 3633 3634 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode) 3635 { 3636 struct rtw89_btc *btc = &rtwdev->btc; 3637 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3638 3639 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3640 3641 if (wl->status.map.rf_off || btc->dm.bt_only) { 3642 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF); 3643 } else if (wl->status.map.lps == BTC_LPS_RF_ON) { 3644 if (wl->role_info.link_mode == BTC_WLINK_5G) 3645 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 3646 else 3647 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3648 } 3649 3650 if (mode == BTC_WLINK_5G) { 3651 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF); 3652 } else if (wl->status.map.lps == BTC_LPS_RF_ON) { 3653 if (btc->cx.bt.link_info.a2dp_desc.active) 3654 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 3655 else 3656 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF); 3657 } else { 3658 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 3659 } 3660 } 3661 3662 static void _action_freerun(struct rtw89_dev *rtwdev) 3663 { 3664 struct rtw89_btc *btc = &rtwdev->btc; 3665 3666 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3667 3668 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN); 3669 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN); 3670 3671 btc->dm.freerun = true; 3672 } 3673 3674 static void _action_bt_whql(struct rtw89_dev *rtwdev) 3675 { 3676 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3677 3678 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3679 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL); 3680 } 3681 3682 static void _action_bt_off(struct rtw89_dev *rtwdev) 3683 { 3684 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3685 3686 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 3687 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF); 3688 } 3689 3690 static void _action_bt_idle(struct rtw89_dev *rtwdev) 3691 { 3692 struct rtw89_btc *btc = &rtwdev->btc; 3693 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info; 3694 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3695 3696 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3697 3698 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 3699 switch (btc->cx.state_map) { 3700 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/ 3701 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */ 3702 if (b->status.map.connect) 3703 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE); 3704 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 3705 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE); 3706 else 3707 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE); 3708 break; 3709 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */ 3710 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, 3711 BTC_ACT_BT_IDLE); 3712 break; 3713 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */ 3714 _set_policy(rtwdev, BTC_CXP_FIX_TD5050, 3715 BTC_ACT_BT_IDLE); 3716 break; 3717 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */ 3718 _set_policy(rtwdev, BTC_CXP_FIX_TD7010, 3719 BTC_ACT_BT_IDLE); 3720 break; 3721 case BTC_WIDLE: /* wl-idle + bt-idle */ 3722 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE); 3723 break; 3724 } 3725 } else { /* dedicated-antenna */ 3726 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE); 3727 } 3728 } 3729 3730 static void _action_bt_hfp(struct rtw89_dev *rtwdev) 3731 { 3732 struct rtw89_btc *btc = &rtwdev->btc; 3733 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3734 3735 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3736 3737 if (btc->ant_type == BTC_ANT_SHARED) { 3738 if (btc->cx.wl.status.map._4way) { 3739 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP); 3740 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3741 btc->cx.bt.scan_rx_low_pri = true; 3742 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP); 3743 } else { 3744 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 3745 } 3746 } else { 3747 if (wl->bg_mode) 3748 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 3749 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 3750 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP); 3751 else 3752 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP); 3753 } 3754 } 3755 3756 static void _action_bt_hid(struct rtw89_dev *rtwdev) 3757 { 3758 const struct rtw89_chip_info *chip = rtwdev->chip; 3759 struct rtw89_btc *btc = &rtwdev->btc; 3760 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3761 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3762 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc; 3763 u16 policy_type = BTC_CXP_OFF_BT; 3764 3765 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3766 3767 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 3768 if (wl->status.map._4way) { 3769 policy_type = BTC_CXP_OFF_WL; 3770 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3771 btc->cx.bt.scan_rx_low_pri = true; 3772 if (hid->type & BTC_HID_BLE) 3773 policy_type = BTC_CXP_OFF_BWB0; 3774 else 3775 policy_type = BTC_CXP_OFF_BWB2; 3776 } else if (hid->type == BTC_HID_218) { 3777 bt->scan_rx_low_pri = true; 3778 policy_type = BTC_CXP_OFF_BWB2; 3779 } else if (chip->para_ver == 0x1) { 3780 policy_type = BTC_CXP_OFF_BWB3; 3781 } else { 3782 policy_type = BTC_CXP_OFF_BWB1; 3783 } 3784 } else { /* dedicated-antenna */ 3785 if (wl->bg_mode) 3786 policy_type = BTC_CXP_OFF_BWB1; 3787 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 3788 policy_type = BTC_CXP_OFF_EQ4; 3789 else 3790 policy_type = BTC_CXP_OFF_EQ3; 3791 } 3792 3793 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID); 3794 } 3795 3796 static void _action_bt_a2dp(struct rtw89_dev *rtwdev) 3797 { 3798 struct rtw89_btc *btc = &rtwdev->btc; 3799 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 3800 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3801 struct rtw89_btc_dm *dm = &btc->dm; 3802 3803 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3804 3805 switch (btc->cx.state_map) { 3806 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 3807 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3808 dm->slot_dur[CXST_W1] = 40; 3809 dm->slot_dur[CXST_B1] = 200; 3810 _set_policy(rtwdev, 3811 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 3812 } else { 3813 _set_policy(rtwdev, 3814 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP); 3815 } 3816 break; 3817 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 3818 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 3819 break; 3820 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 3821 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 3822 break; 3823 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 3824 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 3825 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3826 dm->slot_dur[CXST_W1] = 40; 3827 dm->slot_dur[CXST_B1] = 200; 3828 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, 3829 BTC_ACT_BT_A2DP); 3830 } else { 3831 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, 3832 BTC_ACT_BT_A2DP); 3833 } 3834 break; 3835 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 3836 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 3837 break; 3838 } 3839 } 3840 3841 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 3842 { 3843 struct rtw89_btc *btc = &rtwdev->btc; 3844 3845 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3846 3847 switch (btc->cx.state_map) { 3848 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 3849 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 3850 break; 3851 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 3852 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 3853 break; 3854 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 3855 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 3856 break; 3857 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 3858 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 3859 break; 3860 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 3861 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 3862 break; 3863 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 3864 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 3865 break; 3866 } 3867 } 3868 3869 static void _action_bt_pan(struct rtw89_dev *rtwdev) 3870 { 3871 struct rtw89_btc *btc = &rtwdev->btc; 3872 3873 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3874 3875 switch (btc->cx.state_map) { 3876 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 3877 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 3878 break; 3879 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 3880 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 3881 break; 3882 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 3883 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 3884 break; 3885 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 3886 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 3887 break; 3888 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 3889 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN); 3890 break; 3891 case BTC_WIDLE: /* wl-idle + bt-pan */ 3892 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 3893 break; 3894 } 3895 } 3896 3897 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 3898 { 3899 struct rtw89_btc *btc = &rtwdev->btc; 3900 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 3901 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3902 struct rtw89_btc_dm *dm = &btc->dm; 3903 3904 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3905 3906 switch (btc->cx.state_map) { 3907 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 3908 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 3909 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3910 dm->slot_dur[CXST_W1] = 40; 3911 dm->slot_dur[CXST_B1] = 200; 3912 _set_policy(rtwdev, 3913 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 3914 } else { 3915 _set_policy(rtwdev, 3916 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID); 3917 } 3918 break; 3919 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 3920 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 3921 break; 3922 3923 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 3924 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 3925 break; 3926 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 3927 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 3928 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3929 dm->slot_dur[CXST_W1] = 40; 3930 dm->slot_dur[CXST_B1] = 200; 3931 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, 3932 BTC_ACT_BT_A2DP_HID); 3933 } else { 3934 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, 3935 BTC_ACT_BT_A2DP_HID); 3936 } 3937 break; 3938 } 3939 } 3940 3941 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 3942 { 3943 struct rtw89_btc *btc = &rtwdev->btc; 3944 3945 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3946 3947 switch (btc->cx.state_map) { 3948 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 3949 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3950 break; 3951 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 3952 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3953 break; 3954 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 3955 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 3956 break; 3957 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 3958 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3959 break; 3960 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 3961 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 3962 break; 3963 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 3964 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 3965 break; 3966 } 3967 } 3968 3969 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 3970 { 3971 struct rtw89_btc *btc = &rtwdev->btc; 3972 3973 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3974 3975 switch (btc->cx.state_map) { 3976 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 3977 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 3978 break; 3979 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 3980 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 3981 break; 3982 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 3983 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 3984 break; 3985 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 3986 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 3987 break; 3988 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 3989 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 3990 break; 3991 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 3992 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 3993 break; 3994 } 3995 } 3996 3997 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 3998 { 3999 struct rtw89_btc *btc = &rtwdev->btc; 4000 4001 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4002 4003 switch (btc->cx.state_map) { 4004 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 4005 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 4006 BTC_ACT_BT_A2DP_PAN_HID); 4007 break; 4008 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 4009 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 4010 BTC_ACT_BT_A2DP_PAN_HID); 4011 break; 4012 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 4013 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 4014 BTC_ACT_BT_A2DP_PAN_HID); 4015 break; 4016 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 4017 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 4018 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 4019 BTC_ACT_BT_A2DP_PAN_HID); 4020 break; 4021 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 4022 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 4023 BTC_ACT_BT_A2DP_PAN_HID); 4024 break; 4025 } 4026 } 4027 4028 static void _action_wl_5g(struct rtw89_dev *rtwdev) 4029 { 4030 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 4031 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 4032 } 4033 4034 static void _action_wl_other(struct rtw89_dev *rtwdev) 4035 { 4036 struct rtw89_btc *btc = &rtwdev->btc; 4037 4038 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4039 4040 if (btc->ant_type == BTC_ANT_SHARED) 4041 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 4042 else 4043 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 4044 } 4045 4046 static void _action_wl_nc(struct rtw89_dev *rtwdev) 4047 { 4048 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4049 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 4050 } 4051 4052 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 4053 { 4054 struct rtw89_btc *btc = &rtwdev->btc; 4055 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 4056 4057 if (rfk.state != BTC_WRFK_START) 4058 return; 4059 4060 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 4061 __func__, rfk.band); 4062 4063 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 4064 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 4065 } 4066 4067 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 4068 { 4069 struct rtw89_btc *btc = &rtwdev->btc; 4070 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4071 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 4072 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 4073 struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info; 4074 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4075 const struct rtw89_chip_info *chip = rtwdev->chip; 4076 const struct rtw89_btc_ver *ver = btc->ver; 4077 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4078 struct rtw89_btc_dm *dm = &btc->dm; 4079 struct _wl_rinfo_now wl_rinfo; 4080 u32 run_reason = btc->dm.run_reason; 4081 u32 is_btg; 4082 u8 i, val; 4083 4084 if (btc->manual_ctrl) 4085 return; 4086 4087 if (ver->fwlrole == 0) 4088 wl_rinfo.link_mode = wl_rinfo_v0->link_mode; 4089 else if (ver->fwlrole == 1) 4090 wl_rinfo.link_mode = wl_rinfo_v1->link_mode; 4091 else if (ver->fwlrole == 2) 4092 wl_rinfo.link_mode = wl_rinfo_v2->link_mode; 4093 else 4094 return; 4095 4096 if (rtwdev->dbcc_en) { 4097 if (ver->fwlrole == 0) { 4098 for (i = 0; i < RTW89_PHY_MAX; i++) { 4099 if (wl_dinfo->real_band[i] == RTW89_BAND_2G) 4100 wl_rinfo.dbcc_2g_phy = i; 4101 } 4102 } else if (ver->fwlrole == 1) { 4103 wl_rinfo.dbcc_2g_phy = wl_rinfo_v1->dbcc_2g_phy; 4104 } else if (ver->fwlrole == 2) { 4105 wl_rinfo.dbcc_2g_phy = wl_rinfo_v2->dbcc_2g_phy; 4106 } else { 4107 return; 4108 } 4109 } 4110 4111 if (wl_rinfo.link_mode == BTC_WLINK_25G_MCC) 4112 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; 4113 else if (!(bt->run_patch_code && bt->enable.now)) 4114 is_btg = BTC_BTGCTRL_DISABLE; 4115 else if (wl_rinfo.link_mode == BTC_WLINK_5G) 4116 is_btg = BTC_BTGCTRL_DISABLE; 4117 else if (dm->freerun) 4118 is_btg = BTC_BTGCTRL_DISABLE; 4119 else if (rtwdev->dbcc_en && wl_rinfo.dbcc_2g_phy != RTW89_PHY_1) 4120 is_btg = BTC_BTGCTRL_DISABLE; 4121 else 4122 is_btg = BTC_BTGCTRL_ENABLE; 4123 4124 if (dm->wl_btg_rx_rb != dm->wl_btg_rx && 4125 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) { 4126 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX, &val); 4127 dm->wl_btg_rx_rb = val; 4128 } 4129 4130 if (run_reason == BTC_RSN_NTFY_INIT || 4131 run_reason == BTC_RSN_NTFY_SWBAND || 4132 dm->wl_btg_rx_rb != dm->wl_btg_rx || 4133 is_btg != dm->wl_btg_rx) { 4134 4135 dm->wl_btg_rx = is_btg; 4136 4137 if (is_btg > BTC_BTGCTRL_ENABLE) 4138 return; 4139 4140 chip->ops->ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0); 4141 } 4142 } 4143 4144 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) 4145 { 4146 struct rtw89_btc *btc = &rtwdev->btc; 4147 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 4148 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4149 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 4150 const struct rtw89_chip_info *chip = rtwdev->chip; 4151 const struct rtw89_btc_ver *ver = btc->ver; 4152 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4153 struct rtw89_btc_dm *dm = &btc->dm; 4154 u8 is_preagc, val; 4155 4156 if (btc->manual_ctrl) 4157 return; 4158 4159 if (wl_rinfo->link_mode == BTC_WLINK_25G_MCC) 4160 is_preagc = BTC_PREAGC_BB_FWCTRL; 4161 else if (!(bt->run_patch_code && bt->enable.now)) 4162 is_preagc = BTC_PREAGC_DISABLE; 4163 else if (wl_rinfo->link_mode == BTC_WLINK_5G) 4164 is_preagc = BTC_PREAGC_DISABLE; 4165 else if (wl_rinfo->link_mode == BTC_WLINK_NOLINK || 4166 btc->cx.bt.link_info.profile_cnt.now == 0) 4167 is_preagc = BTC_PREAGC_DISABLE; 4168 else if (dm->tdma_now.type != CXTDMA_OFF && 4169 !bt_linfo->hfp_desc.exist && 4170 !bt_linfo->hid_desc.exist && 4171 dm->fddt_train == BTC_FDDT_DISABLE) 4172 is_preagc = BTC_PREAGC_DISABLE; 4173 else if (ver->fwlrole == 2 && wl_rinfo->dbcc_en && 4174 wl_rinfo->dbcc_2g_phy != RTW89_PHY_1) 4175 is_preagc = BTC_PREAGC_DISABLE; 4176 else if (btc->ant_type == BTC_ANT_SHARED) 4177 is_preagc = BTC_PREAGC_DISABLE; 4178 else 4179 is_preagc = BTC_PREAGC_ENABLE; 4180 4181 if (dm->wl_pre_agc_rb != dm->wl_pre_agc && 4182 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) { 4183 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val); 4184 dm->wl_pre_agc_rb = val; 4185 } 4186 4187 if ((wl->coex_mode == BTC_MODE_NORMAL && 4188 (dm->run_reason == BTC_RSN_NTFY_INIT || 4189 dm->run_reason == BTC_RSN_NTFY_SWBAND || 4190 dm->wl_pre_agc_rb != dm->wl_pre_agc)) || 4191 is_preagc != dm->wl_pre_agc) { 4192 dm->wl_pre_agc = is_preagc; 4193 4194 if (is_preagc > BTC_PREAGC_ENABLE) 4195 return; 4196 chip->ops->ctrl_nbtg_bt_tx(rtwdev, dm->wl_pre_agc, RTW89_PHY_0); 4197 } 4198 } 4199 4200 struct rtw89_txtime_data { 4201 struct rtw89_dev *rtwdev; 4202 int type; 4203 u32 tx_time; 4204 u8 tx_retry; 4205 u16 enable; 4206 bool reenable; 4207 }; 4208 4209 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 4210 { 4211 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 4212 struct rtw89_txtime_data *iter_data = 4213 (struct rtw89_txtime_data *)data; 4214 struct rtw89_dev *rtwdev = iter_data->rtwdev; 4215 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 4216 struct rtw89_btc *btc = &rtwdev->btc; 4217 struct rtw89_btc_cx *cx = &btc->cx; 4218 struct rtw89_btc_wl_info *wl = &cx->wl; 4219 struct rtw89_btc_wl_link_info *plink = NULL; 4220 u8 port = rtwvif->port; 4221 u32 tx_time = iter_data->tx_time; 4222 u8 tx_retry = iter_data->tx_retry; 4223 u16 enable = iter_data->enable; 4224 bool reenable = iter_data->reenable; 4225 4226 plink = &wl->link_info[port]; 4227 4228 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4229 "[BTC], %s(): port = %d\n", __func__, port); 4230 4231 if (!plink->connected) { 4232 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4233 "[BTC], %s(): connected = %d\n", 4234 __func__, plink->connected); 4235 return; 4236 } 4237 4238 /* backup the original tx time before tx-limit on */ 4239 if (reenable) { 4240 rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); 4241 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); 4242 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4243 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 4244 __func__, plink->tx_time, plink->tx_retry); 4245 } 4246 4247 /* restore the original tx time if no tx-limit */ 4248 if (!enable) { 4249 rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); 4250 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, 4251 plink->tx_retry); 4252 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4253 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 4254 __func__, plink->tx_time, plink->tx_retry); 4255 4256 } else { 4257 rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); 4258 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); 4259 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4260 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 4261 __func__, tx_time, tx_retry); 4262 } 4263 } 4264 4265 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 4266 { 4267 struct rtw89_btc *btc = &rtwdev->btc; 4268 const struct rtw89_btc_ver *ver = btc->ver; 4269 struct rtw89_btc_cx *cx = &btc->cx; 4270 struct rtw89_btc_dm *dm = &btc->dm; 4271 struct rtw89_btc_wl_info *wl = &cx->wl; 4272 struct rtw89_btc_bt_info *bt = &cx->bt; 4273 struct rtw89_btc_bt_link_info *b = &bt->link_info; 4274 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 4275 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 4276 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4277 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 4278 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 4279 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 4280 u8 mode, igno_bt, tx_retry; 4281 u32 tx_time; 4282 u16 enable; 4283 bool reenable = false; 4284 4285 if (btc->manual_ctrl) 4286 return; 4287 4288 if (ver->fwlrole == 0) 4289 mode = wl_rinfo->link_mode; 4290 else if (ver->fwlrole == 1) 4291 mode = wl_rinfo_v1->link_mode; 4292 else if (ver->fwlrole == 2) 4293 mode = wl_rinfo_v2->link_mode; 4294 else 4295 return; 4296 4297 if (ver->fcxctrl == 7) 4298 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 4299 else 4300 igno_bt = btc->ctrl.ctrl.igno_bt; 4301 4302 if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 || 4303 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) { 4304 enable = 0; 4305 tx_time = BTC_MAX_TX_TIME_DEF; 4306 tx_retry = BTC_MAX_TX_RETRY_DEF; 4307 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 4308 enable = 1; 4309 tx_time = BTC_MAX_TX_TIME_L2; 4310 tx_retry = BTC_MAX_TX_RETRY_L1; 4311 } else if (hfp->exist || hid->exist) { 4312 enable = 1; 4313 tx_time = BTC_MAX_TX_TIME_L3; 4314 tx_retry = BTC_MAX_TX_RETRY_L1; 4315 } else { 4316 enable = 0; 4317 tx_time = BTC_MAX_TX_TIME_DEF; 4318 tx_retry = BTC_MAX_TX_RETRY_DEF; 4319 } 4320 4321 if (dm->wl_tx_limit.enable == enable && 4322 dm->wl_tx_limit.tx_time == tx_time && 4323 dm->wl_tx_limit.tx_retry == tx_retry) 4324 return; 4325 4326 if (!dm->wl_tx_limit.enable && enable) 4327 reenable = true; 4328 4329 dm->wl_tx_limit.enable = enable; 4330 dm->wl_tx_limit.tx_time = tx_time; 4331 dm->wl_tx_limit.tx_retry = tx_retry; 4332 4333 data.enable = enable; 4334 data.tx_time = tx_time; 4335 data.tx_retry = tx_retry; 4336 data.reenable = reenable; 4337 4338 ieee80211_iterate_stations_atomic(rtwdev->hw, 4339 rtw89_tx_time_iter, 4340 &data); 4341 } 4342 4343 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 4344 { 4345 struct rtw89_btc *btc = &rtwdev->btc; 4346 const struct rtw89_btc_ver *ver = btc->ver; 4347 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4348 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4349 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 4350 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 4351 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4352 bool bt_hi_lna_rx = false; 4353 u8 mode; 4354 4355 if (ver->fwlrole == 0) 4356 mode = wl_rinfo->link_mode; 4357 else if (ver->fwlrole == 1) 4358 mode = wl_rinfo_v1->link_mode; 4359 else if (ver->fwlrole == 2) 4360 mode = wl_rinfo_v2->link_mode; 4361 else 4362 return; 4363 4364 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 4365 bt_hi_lna_rx = true; 4366 4367 if (bt_hi_lna_rx == bt->hi_lna_rx) 4368 return; 4369 4370 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 4371 } 4372 4373 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 4374 { 4375 struct rtw89_btc *btc = &rtwdev->btc; 4376 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4377 4378 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri)); 4379 } 4380 4381 /* TODO add these functions */ 4382 static void _action_common(struct rtw89_dev *rtwdev) 4383 { 4384 struct rtw89_btc *btc = &rtwdev->btc; 4385 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4386 4387 _set_btg_ctrl(rtwdev); 4388 _set_wl_preagc_ctrl(rtwdev); 4389 _set_wl_tx_limit(rtwdev); 4390 _set_bt_afh_info(rtwdev); 4391 _set_bt_rx_agc(rtwdev); 4392 _set_rf_trx_para(rtwdev); 4393 _set_bt_rx_scan_pri(rtwdev); 4394 4395 if (wl->scbd_change) { 4396 rtw89_mac_cfg_sb(rtwdev, wl->scbd); 4397 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n", 4398 wl->scbd); 4399 wl->scbd_change = false; 4400 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++; 4401 } 4402 btc->dm.tdma_instant_excute = 0; 4403 } 4404 4405 static void _action_by_bt(struct rtw89_dev *rtwdev) 4406 { 4407 struct rtw89_btc *btc = &rtwdev->btc; 4408 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4409 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 4410 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 4411 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 4412 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 4413 u8 profile_map = 0; 4414 4415 if (bt_linfo->hfp_desc.exist) 4416 profile_map |= BTC_BT_HFP; 4417 4418 if (bt_linfo->hid_desc.exist) 4419 profile_map |= BTC_BT_HID; 4420 4421 if (bt_linfo->a2dp_desc.exist) 4422 profile_map |= BTC_BT_A2DP; 4423 4424 if (bt_linfo->pan_desc.exist) 4425 profile_map |= BTC_BT_PAN; 4426 4427 switch (profile_map) { 4428 case BTC_BT_NOPROFILE: 4429 if (_check_freerun(rtwdev)) 4430 _action_freerun(rtwdev); 4431 else if (pan.active) 4432 _action_bt_pan(rtwdev); 4433 else 4434 _action_bt_idle(rtwdev); 4435 break; 4436 case BTC_BT_HFP: 4437 if (_check_freerun(rtwdev)) 4438 _action_freerun(rtwdev); 4439 else 4440 _action_bt_hfp(rtwdev); 4441 break; 4442 case BTC_BT_HFP | BTC_BT_HID: 4443 case BTC_BT_HID: 4444 if (_check_freerun(rtwdev)) 4445 _action_freerun(rtwdev); 4446 else 4447 _action_bt_hid(rtwdev); 4448 break; 4449 case BTC_BT_A2DP: 4450 if (_check_freerun(rtwdev)) 4451 _action_freerun(rtwdev); 4452 else if (a2dp.sink) 4453 _action_bt_a2dpsink(rtwdev); 4454 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 4455 _action_bt_a2dp_pan(rtwdev); 4456 else 4457 _action_bt_a2dp(rtwdev); 4458 break; 4459 case BTC_BT_PAN: 4460 _action_bt_pan(rtwdev); 4461 break; 4462 case BTC_BT_A2DP | BTC_BT_HFP: 4463 case BTC_BT_A2DP | BTC_BT_HID: 4464 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 4465 if (_check_freerun(rtwdev)) 4466 _action_freerun(rtwdev); 4467 else 4468 _action_bt_a2dp_hid(rtwdev); 4469 break; 4470 case BTC_BT_A2DP | BTC_BT_PAN: 4471 _action_bt_a2dp_pan(rtwdev); 4472 break; 4473 case BTC_BT_PAN | BTC_BT_HFP: 4474 case BTC_BT_PAN | BTC_BT_HID: 4475 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 4476 _action_bt_pan_hid(rtwdev); 4477 break; 4478 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 4479 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 4480 default: 4481 _action_bt_a2dp_pan_hid(rtwdev); 4482 break; 4483 } 4484 } 4485 4486 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 4487 { 4488 _action_by_bt(rtwdev); 4489 } 4490 4491 static void _action_wl_scan(struct rtw89_dev *rtwdev) 4492 { 4493 struct rtw89_btc *btc = &rtwdev->btc; 4494 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4495 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4496 4497 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { 4498 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 4499 if (btc->ant_type == BTC_ANT_SHARED) 4500 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 4501 BTC_RSN_NTFY_SCAN_START); 4502 else 4503 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, 4504 BTC_RSN_NTFY_SCAN_START); 4505 4506 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 4507 } else if (rtwdev->dbcc_en) { 4508 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 4509 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 4510 _action_wl_5g(rtwdev); 4511 else 4512 _action_by_bt(rtwdev); 4513 } else { 4514 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 4515 _action_wl_5g(rtwdev); 4516 else 4517 _action_by_bt(rtwdev); 4518 } 4519 } 4520 4521 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 4522 { 4523 struct rtw89_btc *btc = &rtwdev->btc; 4524 4525 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 4526 4527 if (btc->ant_type == BTC_ANT_SHARED) { 4528 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4529 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 4530 BTC_ACT_WL_25G_MCC); 4531 else 4532 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 4533 BTC_ACT_WL_25G_MCC); 4534 } else { /* dedicated-antenna */ 4535 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC); 4536 } 4537 } 4538 4539 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 4540 { struct rtw89_btc *btc = &rtwdev->btc; 4541 4542 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4543 4544 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4545 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4546 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 4547 BTC_ACT_WL_2G_MCC); 4548 else 4549 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 4550 BTC_ACT_WL_2G_MCC); 4551 } else { /* dedicated-antenna */ 4552 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 4553 } 4554 } 4555 4556 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 4557 { 4558 struct rtw89_btc *btc = &rtwdev->btc; 4559 4560 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4561 4562 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4563 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4564 _set_policy(rtwdev, 4565 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC); 4566 else 4567 _set_policy(rtwdev, 4568 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC); 4569 } else { /* dedicated-antenna */ 4570 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC); 4571 } 4572 } 4573 4574 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev) 4575 { 4576 struct rtw89_btc *btc = &rtwdev->btc; 4577 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4578 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4579 struct rtw89_btc_dm *dm = &btc->dm; 4580 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 4581 u16 policy_type = BTC_CXP_OFF_BT; 4582 u32 dur; 4583 4584 if (btc->ant_type == BTC_ANT_DEDICATED) { 4585 policy_type = BTC_CXP_OFF_EQ0; 4586 } else { 4587 /* shared-antenna */ 4588 switch (wl_rinfo->mrole_type) { 4589 case BTC_WLMROLE_STA_GC: 4590 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4591 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 4592 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4593 _action_by_bt(rtwdev); 4594 return; 4595 case BTC_WLMROLE_STA_STA: 4596 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4597 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 4598 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4599 _action_by_bt(rtwdev); 4600 return; 4601 case BTC_WLMROLE_STA_GC_NOA: 4602 case BTC_WLMROLE_STA_GO: 4603 case BTC_WLMROLE_STA_GO_NOA: 4604 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4605 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 4606 dur = wl_rinfo->mrole_noa_duration; 4607 4608 if (wl->status.map._4way) { 4609 dm->wl_scc.ebt_null = 0; 4610 policy_type = BTC_CXP_OFFE_WL; 4611 } else if (bt->link_info.status.map.connect == 0) { 4612 dm->wl_scc.ebt_null = 0; 4613 policy_type = BTC_CXP_OFFE_2GISOB; 4614 } else if (bt->link_info.a2dp_desc.exist && 4615 dur < btc->bt_req_len) { 4616 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4617 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 4618 } else if (bt->link_info.a2dp_desc.exist || 4619 bt->link_info.pan_desc.exist) { 4620 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4621 policy_type = BTC_CXP_OFFE_2GBWISOB; 4622 } else { 4623 dm->wl_scc.ebt_null = 0; 4624 policy_type = BTC_CXP_OFFE_2GBWISOB; 4625 } 4626 break; 4627 default: 4628 break; 4629 } 4630 } 4631 4632 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4633 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 4634 } 4635 4636 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev) 4637 { 4638 struct rtw89_btc *btc = &rtwdev->btc; 4639 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4640 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4641 struct rtw89_btc_dm *dm = &btc->dm; 4642 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 4643 u16 policy_type = BTC_CXP_OFF_BT; 4644 u32 dur; 4645 4646 if (btc->ant_type == BTC_ANT_DEDICATED) { 4647 policy_type = BTC_CXP_OFF_EQ0; 4648 } else { 4649 /* shared-antenna */ 4650 switch (wl_rinfo->mrole_type) { 4651 case BTC_WLMROLE_STA_GC: 4652 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4653 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 4654 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4655 _action_by_bt(rtwdev); 4656 return; 4657 case BTC_WLMROLE_STA_STA: 4658 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4659 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 4660 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4661 _action_by_bt(rtwdev); 4662 return; 4663 case BTC_WLMROLE_STA_GC_NOA: 4664 case BTC_WLMROLE_STA_GO: 4665 case BTC_WLMROLE_STA_GO_NOA: 4666 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4667 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 4668 dur = wl_rinfo->mrole_noa_duration; 4669 4670 if (wl->status.map._4way) { 4671 dm->wl_scc.ebt_null = 0; 4672 policy_type = BTC_CXP_OFFE_WL; 4673 } else if (bt->link_info.status.map.connect == 0) { 4674 dm->wl_scc.ebt_null = 0; 4675 policy_type = BTC_CXP_OFFE_2GISOB; 4676 } else if (bt->link_info.a2dp_desc.exist && 4677 dur < btc->bt_req_len) { 4678 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4679 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 4680 } else if (bt->link_info.a2dp_desc.exist || 4681 bt->link_info.pan_desc.exist) { 4682 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4683 policy_type = BTC_CXP_OFFE_2GBWISOB; 4684 } else { 4685 dm->wl_scc.ebt_null = 0; 4686 policy_type = BTC_CXP_OFFE_2GBWISOB; 4687 } 4688 break; 4689 default: 4690 break; 4691 } 4692 } 4693 4694 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4695 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 4696 } 4697 4698 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 4699 { 4700 struct rtw89_btc *btc = &rtwdev->btc; 4701 4702 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4703 4704 if (btc->ant_type == BTC_ANT_SHARED) { 4705 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4706 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 4707 BTC_ACT_WL_2G_AP); 4708 else 4709 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 4710 } else {/* dedicated-antenna */ 4711 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 4712 } 4713 } 4714 4715 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 4716 { 4717 struct rtw89_btc *btc = &rtwdev->btc; 4718 4719 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4720 4721 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4722 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4723 _set_policy(rtwdev, 4724 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 4725 else 4726 _set_policy(rtwdev, 4727 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 4728 } else { /* dedicated-antenna */ 4729 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 4730 } 4731 } 4732 4733 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 4734 { 4735 struct rtw89_btc *btc = &rtwdev->btc; 4736 4737 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4738 4739 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4740 _action_by_bt(rtwdev); 4741 } else {/* dedicated-antenna */ 4742 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 4743 } 4744 } 4745 4746 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 4747 { 4748 struct rtw89_btc *btc = &rtwdev->btc; 4749 4750 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4751 4752 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4753 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4754 _set_policy(rtwdev, 4755 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 4756 else 4757 _set_policy(rtwdev, 4758 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 4759 } else { /* dedicated-antenna */ 4760 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 4761 } 4762 } 4763 4764 static u32 _read_scbd(struct rtw89_dev *rtwdev) 4765 { 4766 const struct rtw89_chip_info *chip = rtwdev->chip; 4767 struct rtw89_btc *btc = &rtwdev->btc; 4768 u32 scbd_val = 0; 4769 4770 if (!chip->scbd) 4771 return 0; 4772 4773 scbd_val = rtw89_mac_get_sb(rtwdev); 4774 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n", 4775 scbd_val); 4776 4777 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++; 4778 return scbd_val; 4779 } 4780 4781 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state) 4782 { 4783 const struct rtw89_chip_info *chip = rtwdev->chip; 4784 struct rtw89_btc *btc = &rtwdev->btc; 4785 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4786 u32 scbd_val = 0; 4787 u8 force_exec = false; 4788 4789 if (!chip->scbd) 4790 return; 4791 4792 scbd_val = state ? wl->scbd | val : wl->scbd & ~val; 4793 4794 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON) 4795 force_exec = true; 4796 4797 if (scbd_val != wl->scbd || force_exec) { 4798 wl->scbd = scbd_val; 4799 wl->scbd_change = true; 4800 } 4801 } 4802 4803 static u8 4804 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 4805 { 4806 const struct rtw89_chip_info *chip = rtwdev->chip; 4807 u8 next_state, tol = chip->rssi_tol; 4808 4809 if (pre_state == BTC_RSSI_ST_LOW || 4810 pre_state == BTC_RSSI_ST_STAY_LOW) { 4811 if (rssi >= (thresh + tol)) 4812 next_state = BTC_RSSI_ST_HIGH; 4813 else 4814 next_state = BTC_RSSI_ST_STAY_LOW; 4815 } else { 4816 if (rssi < thresh) 4817 next_state = BTC_RSSI_ST_LOW; 4818 else 4819 next_state = BTC_RSSI_ST_STAY_HIGH; 4820 } 4821 4822 return next_state; 4823 } 4824 4825 static 4826 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 4827 { 4828 struct rtw89_btc *btc = &rtwdev->btc; 4829 4830 btc->cx.wl.dbcc_info.real_band[phy_idx] = 4831 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 4832 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 4833 btc->cx.wl.dbcc_info.op_band[phy_idx]; 4834 } 4835 4836 static void _update_wl_info(struct rtw89_dev *rtwdev) 4837 { 4838 struct rtw89_btc *btc = &rtwdev->btc; 4839 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4840 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4841 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4842 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4843 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4844 u8 cnt_2g = 0, cnt_5g = 0, phy; 4845 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0}; 4846 bool b2g = false, b5g = false, client_joined = false; 4847 4848 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4849 4850 for (i = 0; i < RTW89_PORT_NUM; i++) { 4851 /* check if role active? */ 4852 if (!wl_linfo[i].active) 4853 continue; 4854 4855 cnt_active++; 4856 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role; 4857 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid; 4858 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy; 4859 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band; 4860 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4861 wl_rinfo->active_role[cnt_active - 1].connected = 0; 4862 4863 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4864 4865 phy = wl_linfo[i].phy; 4866 4867 /* check dbcc role */ 4868 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4869 wl_dinfo->role[phy] = wl_linfo[i].role; 4870 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4871 _update_dbcc_band(rtwdev, phy); 4872 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4873 } 4874 4875 if (wl_linfo[i].connected == MLME_NO_LINK) { 4876 continue; 4877 } else if (wl_linfo[i].connected == MLME_LINKING) { 4878 cnt_connecting++; 4879 } else { 4880 cnt_connect++; 4881 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4882 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4883 wl_linfo[i].client_cnt > 1) 4884 client_joined = true; 4885 } 4886 4887 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4888 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch; 4889 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw; 4890 wl_rinfo->active_role[cnt_active - 1].connected = 1; 4891 4892 /* only care 2 roles + BT coex */ 4893 if (wl_linfo[i].band != RTW89_BAND_2G) { 4894 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4895 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4896 cnt_5g++; 4897 b5g = true; 4898 } else { 4899 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4900 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4901 cnt_2g++; 4902 b2g = true; 4903 } 4904 } 4905 4906 wl_rinfo->connect_cnt = cnt_connect; 4907 4908 /* Be careful to change the following sequence!! */ 4909 if (cnt_connect == 0) { 4910 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4911 wl_rinfo->role_map.role.none = 1; 4912 } else if (!b2g && b5g) { 4913 wl_rinfo->link_mode = BTC_WLINK_5G; 4914 } else if (wl_rinfo->role_map.role.nan) { 4915 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4916 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4917 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4918 } else if (b2g && b5g && cnt_connect == 2) { 4919 if (rtwdev->dbcc_en) { 4920 switch (wl_dinfo->role[RTW89_PHY_0]) { 4921 case RTW89_WIFI_ROLE_STATION: 4922 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4923 break; 4924 case RTW89_WIFI_ROLE_P2P_GO: 4925 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4926 break; 4927 case RTW89_WIFI_ROLE_P2P_CLIENT: 4928 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4929 break; 4930 case RTW89_WIFI_ROLE_AP: 4931 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4932 break; 4933 default: 4934 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4935 break; 4936 } 4937 } else { 4938 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4939 } 4940 } else if (!b5g && cnt_connect == 2) { 4941 if (wl_rinfo->role_map.role.station && 4942 (wl_rinfo->role_map.role.p2p_go || 4943 wl_rinfo->role_map.role.p2p_gc || 4944 wl_rinfo->role_map.role.ap)) { 4945 if (wl_2g_ch[0] == wl_2g_ch[1]) 4946 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4947 else 4948 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4949 } else { 4950 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4951 } 4952 } else if (!b5g && cnt_connect == 1) { 4953 if (wl_rinfo->role_map.role.station) 4954 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4955 else if (wl_rinfo->role_map.role.ap) 4956 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4957 else if (wl_rinfo->role_map.role.p2p_go) 4958 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4959 else if (wl_rinfo->role_map.role.p2p_gc) 4960 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4961 else 4962 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4963 } 4964 4965 /* if no client_joined, don't care P2P-GO/AP role */ 4966 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4967 if (!client_joined) { 4968 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4969 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4970 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4971 wl_rinfo->connect_cnt = 1; 4972 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4973 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4974 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4975 wl_rinfo->connect_cnt = 0; 4976 } 4977 } 4978 } 4979 4980 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4981 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4982 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4983 4984 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4985 } 4986 4987 static void _update_wl_info_v1(struct rtw89_dev *rtwdev) 4988 { 4989 struct rtw89_btc *btc = &rtwdev->btc; 4990 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4991 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4992 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 4993 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4994 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4995 u8 cnt_2g = 0, cnt_5g = 0, phy; 4996 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 4997 bool b2g = false, b5g = false, client_joined = false; 4998 u8 i; 4999 5000 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 5001 5002 for (i = 0; i < RTW89_PORT_NUM; i++) { 5003 if (!wl_linfo[i].active) 5004 continue; 5005 5006 cnt_active++; 5007 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role; 5008 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid; 5009 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy; 5010 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band; 5011 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 5012 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0; 5013 5014 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 5015 5016 phy = wl_linfo[i].phy; 5017 5018 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 5019 wl_dinfo->role[phy] = wl_linfo[i].role; 5020 wl_dinfo->op_band[phy] = wl_linfo[i].band; 5021 _update_dbcc_band(rtwdev, phy); 5022 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5023 } 5024 5025 if (wl_linfo[i].connected == MLME_NO_LINK) { 5026 continue; 5027 } else if (wl_linfo[i].connected == MLME_LINKING) { 5028 cnt_connecting++; 5029 } else { 5030 cnt_connect++; 5031 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 5032 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 5033 wl_linfo[i].client_cnt > 1) 5034 client_joined = true; 5035 } 5036 5037 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 5038 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch; 5039 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw; 5040 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1; 5041 5042 /* only care 2 roles + BT coex */ 5043 if (wl_linfo[i].band != RTW89_BAND_2G) { 5044 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 5045 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 5046 cnt_5g++; 5047 b5g = true; 5048 } else { 5049 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 5050 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 5051 cnt_2g++; 5052 b2g = true; 5053 } 5054 } 5055 5056 wl_rinfo->connect_cnt = cnt_connect; 5057 5058 /* Be careful to change the following sequence!! */ 5059 if (cnt_connect == 0) { 5060 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5061 wl_rinfo->role_map.role.none = 1; 5062 } else if (!b2g && b5g) { 5063 wl_rinfo->link_mode = BTC_WLINK_5G; 5064 } else if (wl_rinfo->role_map.role.nan) { 5065 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 5066 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 5067 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5068 } else if (b2g && b5g && cnt_connect == 2) { 5069 if (rtwdev->dbcc_en) { 5070 switch (wl_dinfo->role[RTW89_PHY_0]) { 5071 case RTW89_WIFI_ROLE_STATION: 5072 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5073 break; 5074 case RTW89_WIFI_ROLE_P2P_GO: 5075 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5076 break; 5077 case RTW89_WIFI_ROLE_P2P_CLIENT: 5078 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5079 break; 5080 case RTW89_WIFI_ROLE_AP: 5081 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5082 break; 5083 default: 5084 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5085 break; 5086 } 5087 } else { 5088 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 5089 } 5090 } else if (!b5g && cnt_connect == 2) { 5091 if (wl_rinfo->role_map.role.station && 5092 (wl_rinfo->role_map.role.p2p_go || 5093 wl_rinfo->role_map.role.p2p_gc || 5094 wl_rinfo->role_map.role.ap)) { 5095 if (wl_2g_ch[0] == wl_2g_ch[1]) 5096 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 5097 else 5098 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 5099 } else { 5100 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 5101 } 5102 } else if (!b5g && cnt_connect == 1) { 5103 if (wl_rinfo->role_map.role.station) 5104 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5105 else if (wl_rinfo->role_map.role.ap) 5106 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5107 else if (wl_rinfo->role_map.role.p2p_go) 5108 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5109 else if (wl_rinfo->role_map.role.p2p_gc) 5110 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5111 else 5112 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5113 } 5114 5115 /* if no client_joined, don't care P2P-GO/AP role */ 5116 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 5117 if (!client_joined) { 5118 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 5119 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 5120 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5121 wl_rinfo->connect_cnt = 1; 5122 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 5123 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 5124 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5125 wl_rinfo->connect_cnt = 0; 5126 } 5127 } 5128 } 5129 5130 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5131 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 5132 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 5133 5134 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5135 } 5136 5137 static void _update_wl_info_v2(struct rtw89_dev *rtwdev) 5138 { 5139 struct rtw89_btc *btc = &rtwdev->btc; 5140 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5141 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 5142 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 5143 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5144 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 5145 u8 cnt_2g = 0, cnt_5g = 0, phy; 5146 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 5147 bool b2g = false, b5g = false, client_joined = false; 5148 u8 i; 5149 5150 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 5151 5152 for (i = 0; i < RTW89_PORT_NUM; i++) { 5153 if (!wl_linfo[i].active) 5154 continue; 5155 5156 cnt_active++; 5157 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role; 5158 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid; 5159 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy; 5160 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band; 5161 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 5162 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0; 5163 5164 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 5165 5166 phy = wl_linfo[i].phy; 5167 5168 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 5169 wl_dinfo->role[phy] = wl_linfo[i].role; 5170 wl_dinfo->op_band[phy] = wl_linfo[i].band; 5171 _update_dbcc_band(rtwdev, phy); 5172 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5173 } 5174 5175 if (wl_linfo[i].connected == MLME_NO_LINK) { 5176 continue; 5177 } else if (wl_linfo[i].connected == MLME_LINKING) { 5178 cnt_connecting++; 5179 } else { 5180 cnt_connect++; 5181 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 5182 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 5183 wl_linfo[i].client_cnt > 1) 5184 client_joined = true; 5185 } 5186 5187 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 5188 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch; 5189 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw; 5190 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1; 5191 5192 /* only care 2 roles + BT coex */ 5193 if (wl_linfo[i].band != RTW89_BAND_2G) { 5194 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 5195 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 5196 cnt_5g++; 5197 b5g = true; 5198 } else { 5199 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 5200 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 5201 cnt_2g++; 5202 b2g = true; 5203 } 5204 } 5205 5206 wl_rinfo->connect_cnt = cnt_connect; 5207 5208 /* Be careful to change the following sequence!! */ 5209 if (cnt_connect == 0) { 5210 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5211 wl_rinfo->role_map.role.none = 1; 5212 } else if (!b2g && b5g) { 5213 wl_rinfo->link_mode = BTC_WLINK_5G; 5214 } else if (wl_rinfo->role_map.role.nan) { 5215 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 5216 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 5217 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5218 } else if (b2g && b5g && cnt_connect == 2) { 5219 if (rtwdev->dbcc_en) { 5220 switch (wl_dinfo->role[RTW89_PHY_0]) { 5221 case RTW89_WIFI_ROLE_STATION: 5222 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5223 break; 5224 case RTW89_WIFI_ROLE_P2P_GO: 5225 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5226 break; 5227 case RTW89_WIFI_ROLE_P2P_CLIENT: 5228 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5229 break; 5230 case RTW89_WIFI_ROLE_AP: 5231 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5232 break; 5233 default: 5234 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5235 break; 5236 } 5237 } else { 5238 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 5239 } 5240 } else if (!b5g && cnt_connect == 2) { 5241 if (wl_rinfo->role_map.role.station && 5242 (wl_rinfo->role_map.role.p2p_go || 5243 wl_rinfo->role_map.role.p2p_gc || 5244 wl_rinfo->role_map.role.ap)) { 5245 if (wl_2g_ch[0] == wl_2g_ch[1]) 5246 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 5247 else 5248 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 5249 } else { 5250 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 5251 } 5252 } else if (!b5g && cnt_connect == 1) { 5253 if (wl_rinfo->role_map.role.station) 5254 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5255 else if (wl_rinfo->role_map.role.ap) 5256 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5257 else if (wl_rinfo->role_map.role.p2p_go) 5258 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5259 else if (wl_rinfo->role_map.role.p2p_gc) 5260 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5261 else 5262 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5263 } 5264 5265 /* if no client_joined, don't care P2P-GO/AP role */ 5266 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 5267 if (!client_joined) { 5268 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 5269 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 5270 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5271 wl_rinfo->connect_cnt = 1; 5272 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 5273 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 5274 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5275 wl_rinfo->connect_cnt = 0; 5276 } 5277 } 5278 } 5279 5280 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5281 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 5282 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 5283 5284 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5285 } 5286 5287 #define BTC_CHK_HANG_MAX 3 5288 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 5289 5290 void rtw89_coex_act1_work(struct work_struct *work) 5291 { 5292 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5293 coex_act1_work.work); 5294 struct rtw89_btc *btc = &rtwdev->btc; 5295 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5296 struct rtw89_btc_cx *cx = &btc->cx; 5297 struct rtw89_btc_wl_info *wl = &cx->wl; 5298 5299 mutex_lock(&rtwdev->mutex); 5300 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 5301 dm->cnt_notify[BTC_NCNT_TIMER]++; 5302 if (wl->status.map._4way) 5303 wl->status.map._4way = false; 5304 if (wl->status.map.connecting) 5305 wl->status.map.connecting = false; 5306 5307 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 5308 mutex_unlock(&rtwdev->mutex); 5309 } 5310 5311 void rtw89_coex_bt_devinfo_work(struct work_struct *work) 5312 { 5313 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5314 coex_bt_devinfo_work.work); 5315 struct rtw89_btc *btc = &rtwdev->btc; 5316 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5317 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 5318 5319 mutex_lock(&rtwdev->mutex); 5320 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 5321 dm->cnt_notify[BTC_NCNT_TIMER]++; 5322 a2dp->play_latency = 0; 5323 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 5324 mutex_unlock(&rtwdev->mutex); 5325 } 5326 5327 void rtw89_coex_rfk_chk_work(struct work_struct *work) 5328 { 5329 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5330 coex_rfk_chk_work.work); 5331 struct rtw89_btc *btc = &rtwdev->btc; 5332 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5333 struct rtw89_btc_cx *cx = &btc->cx; 5334 struct rtw89_btc_wl_info *wl = &cx->wl; 5335 5336 mutex_lock(&rtwdev->mutex); 5337 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 5338 dm->cnt_notify[BTC_NCNT_TIMER]++; 5339 if (wl->rfk_info.state != BTC_WRFK_STOP) { 5340 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5341 "[BTC], %s(): RFK timeout\n", __func__); 5342 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++; 5343 dm->error.map.wl_rfk_timeout = true; 5344 wl->rfk_info.state = BTC_WRFK_STOP; 5345 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 5346 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 5347 } 5348 mutex_unlock(&rtwdev->mutex); 5349 } 5350 5351 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) 5352 { 5353 const struct rtw89_chip_info *chip = rtwdev->chip; 5354 struct rtw89_btc *btc = &rtwdev->btc; 5355 struct rtw89_btc_cx *cx = &btc->cx; 5356 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5357 u32 val; 5358 bool status_change = false; 5359 5360 if (!chip->scbd) 5361 return; 5362 5363 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 5364 5365 val = _read_scbd(rtwdev); 5366 if (val == BTC_SCB_INV_VALUE) { 5367 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5368 "[BTC], %s(): return by invalid scbd value\n", 5369 __func__); 5370 return; 5371 } 5372 5373 if (!(val & BTC_BSCB_ON)) 5374 bt->enable.now = 0; 5375 else 5376 bt->enable.now = 1; 5377 5378 if (bt->enable.now != bt->enable.last) 5379 status_change = true; 5380 5381 /* reset bt info if bt re-enable */ 5382 if (bt->enable.now && !bt->enable.last) { 5383 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 5384 cx->cnt_bt[BTC_BCNT_REENABLE]++; 5385 bt->enable.now = 1; 5386 } 5387 5388 bt->enable.last = bt->enable.now; 5389 bt->scbd = val; 5390 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 5391 5392 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 5393 status_change = true; 5394 5395 bt->whql_test = !!(val & BTC_BSCB_WHQL); 5396 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE; 5397 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT); 5398 5399 bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) + 5400 !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4; 5401 5402 /* if rfk run 1->0 */ 5403 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN)) 5404 status_change = true; 5405 5406 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN); 5407 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); 5408 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 5409 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); 5410 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 5411 5412 if (!only_update && status_change) 5413 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 5414 } 5415 5416 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) 5417 { 5418 struct rtw89_btc *btc = &rtwdev->btc; 5419 struct rtw89_btc_cx *cx = &btc->cx; 5420 struct rtw89_btc_bt_info *bt = &cx->bt; 5421 5422 _update_bt_scbd(rtwdev, true); 5423 5424 cx->cnt_wl[BTC_WCNT_RFK_REQ]++; 5425 5426 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) && 5427 !bt->rfk_info.map.timeout) { 5428 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++; 5429 } else { 5430 cx->cnt_wl[BTC_WCNT_RFK_GO]++; 5431 return true; 5432 } 5433 return false; 5434 } 5435 5436 static 5437 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 5438 { 5439 struct rtw89_btc *btc = &rtwdev->btc; 5440 const struct rtw89_btc_ver *ver = btc->ver; 5441 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5442 struct rtw89_btc_cx *cx = &btc->cx; 5443 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5444 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5445 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5446 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5447 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5448 u8 mode, igno_bt, always_freerun; 5449 5450 lockdep_assert_held(&rtwdev->mutex); 5451 5452 dm->run_reason = reason; 5453 _update_dm_step(rtwdev, reason); 5454 _update_btc_state_map(rtwdev); 5455 5456 if (ver->fwlrole == 0) 5457 mode = wl_rinfo->link_mode; 5458 else if (ver->fwlrole == 1) 5459 mode = wl_rinfo_v1->link_mode; 5460 else if (ver->fwlrole == 2) 5461 mode = wl_rinfo_v2->link_mode; 5462 else 5463 return; 5464 5465 if (ver->fcxctrl == 7) { 5466 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 5467 always_freerun = btc->ctrl.ctrl_v7.always_freerun; 5468 } else { 5469 igno_bt = btc->ctrl.ctrl.igno_bt; 5470 always_freerun = btc->ctrl.ctrl.always_freerun; 5471 } 5472 5473 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 5474 __func__, reason, mode); 5475 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 5476 __func__, dm->wl_only, dm->bt_only); 5477 5478 /* Be careful to change the following function sequence!! */ 5479 if (btc->manual_ctrl) { 5480 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5481 "[BTC], %s(): return for Manual CTRL!!\n", 5482 __func__); 5483 return; 5484 } 5485 5486 if (igno_bt && 5487 (reason == BTC_RSN_UPDATE_BT_INFO || 5488 reason == BTC_RSN_UPDATE_BT_SCBD)) { 5489 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5490 "[BTC], %s(): return for Stop Coex DM!!\n", 5491 __func__); 5492 return; 5493 } 5494 5495 if (!wl->status.map.init_ok) { 5496 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5497 "[BTC], %s(): return for WL init fail!!\n", 5498 __func__); 5499 return; 5500 } 5501 5502 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 5503 wl->status.map.lps_pre == wl->status.map.lps) { 5504 if (reason == BTC_RSN_NTFY_POWEROFF || 5505 reason == BTC_RSN_NTFY_RADIO_STATE) { 5506 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5507 "[BTC], %s(): return for WL rf off state no change!!\n", 5508 __func__); 5509 return; 5510 } 5511 if (wl->status.map.rf_off == 1 || 5512 wl->status.map.lps == BTC_LPS_RF_OFF) { 5513 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5514 "[BTC], %s(): return for WL rf off state!!\n", 5515 __func__); 5516 return; 5517 } 5518 } 5519 5520 dm->freerun = false; 5521 dm->cnt_dm[BTC_DCNT_RUN]++; 5522 dm->fddt_train = BTC_FDDT_DISABLE; 5523 bt->scan_rx_low_pri = false; 5524 igno_bt = false; 5525 5526 if (always_freerun) { 5527 _action_freerun(rtwdev); 5528 igno_bt = true; 5529 goto exit; 5530 } 5531 5532 if (dm->wl_only) { 5533 _action_wl_only(rtwdev); 5534 igno_bt = true; 5535 goto exit; 5536 } 5537 5538 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) { 5539 _action_wl_off(rtwdev, mode); 5540 igno_bt = true; 5541 goto exit; 5542 } 5543 5544 if (reason == BTC_RSN_NTFY_INIT) { 5545 _action_wl_init(rtwdev); 5546 goto exit; 5547 } 5548 5549 if (!cx->bt.enable.now && !cx->other.type) { 5550 _action_bt_off(rtwdev); 5551 goto exit; 5552 } 5553 5554 if (cx->bt.whql_test) { 5555 _action_bt_whql(rtwdev); 5556 goto exit; 5557 } 5558 5559 if (wl->rfk_info.state != BTC_WRFK_STOP) { 5560 _action_wl_rfk(rtwdev); 5561 goto exit; 5562 } 5563 5564 if (cx->state_map == BTC_WLINKING) { 5565 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || 5566 mode == BTC_WLINK_5G) { 5567 _action_wl_scan(rtwdev); 5568 bt->scan_rx_low_pri = false; 5569 goto exit; 5570 } 5571 } 5572 5573 if (wl->status.map.scan) { 5574 _action_wl_scan(rtwdev); 5575 bt->scan_rx_low_pri = false; 5576 goto exit; 5577 } 5578 5579 switch (mode) { 5580 case BTC_WLINK_NOLINK: 5581 _action_wl_nc(rtwdev); 5582 break; 5583 case BTC_WLINK_2G_STA: 5584 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 5585 bt->scan_rx_low_pri = true; 5586 _action_wl_2g_sta(rtwdev); 5587 break; 5588 case BTC_WLINK_2G_AP: 5589 bt->scan_rx_low_pri = true; 5590 _action_wl_2g_ap(rtwdev); 5591 break; 5592 case BTC_WLINK_2G_GO: 5593 bt->scan_rx_low_pri = true; 5594 _action_wl_2g_go(rtwdev); 5595 break; 5596 case BTC_WLINK_2G_GC: 5597 bt->scan_rx_low_pri = true; 5598 _action_wl_2g_gc(rtwdev); 5599 break; 5600 case BTC_WLINK_2G_SCC: 5601 bt->scan_rx_low_pri = true; 5602 if (ver->fwlrole == 0) 5603 _action_wl_2g_scc(rtwdev); 5604 else if (ver->fwlrole == 1) 5605 _action_wl_2g_scc_v1(rtwdev); 5606 else if (ver->fwlrole == 2) 5607 _action_wl_2g_scc_v2(rtwdev); 5608 break; 5609 case BTC_WLINK_2G_MCC: 5610 bt->scan_rx_low_pri = true; 5611 _action_wl_2g_mcc(rtwdev); 5612 break; 5613 case BTC_WLINK_25G_MCC: 5614 bt->scan_rx_low_pri = true; 5615 _action_wl_25g_mcc(rtwdev); 5616 break; 5617 case BTC_WLINK_5G: 5618 _action_wl_5g(rtwdev); 5619 break; 5620 case BTC_WLINK_2G_NAN: 5621 _action_wl_2g_nan(rtwdev); 5622 break; 5623 default: 5624 _action_wl_other(rtwdev); 5625 break; 5626 } 5627 5628 exit: 5629 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 5630 if (ver->fcxctrl == 7) 5631 btc->ctrl.ctrl_v7.igno_bt = igno_bt; 5632 else 5633 btc->ctrl.ctrl.igno_bt = igno_bt; 5634 _action_common(rtwdev); 5635 } 5636 5637 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 5638 { 5639 struct rtw89_btc *btc = &rtwdev->btc; 5640 5641 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5642 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 5643 } 5644 5645 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 5646 { 5647 struct rtw89_btc *btc = &rtwdev->btc; 5648 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5649 5650 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5651 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 5652 5653 btc->cx.wl.status.map.rf_off = 1; 5654 btc->cx.wl.status.map.busy = 0; 5655 wl->status.map.lps = BTC_LPS_OFF; 5656 5657 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 5658 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 5659 5660 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 5661 5662 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 5663 } 5664 5665 static void _set_init_info(struct rtw89_dev *rtwdev) 5666 { 5667 const struct rtw89_chip_info *chip = rtwdev->chip; 5668 struct rtw89_btc *btc = &rtwdev->btc; 5669 const struct rtw89_btc_ver *ver = btc->ver; 5670 struct rtw89_btc_dm *dm = &btc->dm; 5671 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5672 5673 if (ver->fcxinit == 7) { 5674 dm->init_info.init_v7.wl_only = (u8)dm->wl_only; 5675 dm->init_info.init_v7.bt_only = (u8)dm->bt_only; 5676 dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok; 5677 dm->init_info.init_v7.cx_other = btc->cx.other.type; 5678 dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch; 5679 dm->init_info.init_v7.module = btc->mdinfo.md_v7; 5680 } else { 5681 dm->init_info.init.wl_only = (u8)dm->wl_only; 5682 dm->init_info.init.bt_only = (u8)dm->bt_only; 5683 dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok; 5684 dm->init_info.init.dbcc_en = rtwdev->dbcc_en; 5685 dm->init_info.init.cx_other = btc->cx.other.type; 5686 dm->init_info.init.wl_guard_ch = chip->afh_guard_ch; 5687 dm->init_info.init.module = btc->mdinfo.md; 5688 } 5689 } 5690 5691 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 5692 { 5693 struct rtw89_btc *btc = &rtwdev->btc; 5694 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5695 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5696 const struct rtw89_chip_info *chip = rtwdev->chip; 5697 const struct rtw89_btc_ver *ver = btc->ver; 5698 5699 _reset_btc_var(rtwdev, BTC_RESET_ALL); 5700 btc->dm.run_reason = BTC_RSN_NONE; 5701 btc->dm.run_action = BTC_ACT_NONE; 5702 if (ver->fcxctrl == 7) 5703 btc->ctrl.ctrl_v7.igno_bt = true; 5704 else 5705 btc->ctrl.ctrl.igno_bt = true; 5706 5707 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5708 "[BTC], %s(): mode=%d\n", __func__, mode); 5709 5710 wl->coex_mode = mode; 5711 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 5712 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 5713 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 5714 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 5715 5716 chip->ops->btc_set_rfe(rtwdev); 5717 chip->ops->btc_init_cfg(rtwdev); 5718 5719 if (!wl->status.map.init_ok) { 5720 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5721 "[BTC], %s(): return for WL init fail!!\n", 5722 __func__); 5723 dm->error.map.init = true; 5724 return; 5725 } 5726 5727 _write_scbd(rtwdev, 5728 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 5729 _update_bt_scbd(rtwdev, true); 5730 if (rtw89_mac_get_ctrl_path(rtwdev)) { 5731 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5732 "[BTC], %s(): PTA owner warning!!\n", 5733 __func__); 5734 dm->error.map.pta_owner = true; 5735 } 5736 5737 _set_init_info(rtwdev); 5738 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR); 5739 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot); 5740 btc_fw_set_monreg(rtwdev); 5741 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 5742 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 5743 5744 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 5745 } 5746 5747 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 5748 { 5749 struct rtw89_btc *btc = &rtwdev->btc; 5750 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5751 5752 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5753 "[BTC], %s(): phy_idx=%d, band=%d\n", 5754 __func__, phy_idx, band); 5755 5756 if (phy_idx >= RTW89_PHY_MAX) 5757 return; 5758 5759 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 5760 wl->status.map.scan = true; 5761 wl->scan_info.band[phy_idx] = band; 5762 wl->scan_info.phy_map |= BIT(phy_idx); 5763 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 5764 5765 if (rtwdev->dbcc_en) { 5766 wl->dbcc_info.scan_band[phy_idx] = band; 5767 _update_dbcc_band(rtwdev, phy_idx); 5768 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5769 } 5770 5771 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 5772 } 5773 5774 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 5775 { 5776 struct rtw89_btc *btc = &rtwdev->btc; 5777 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5778 5779 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5780 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 5781 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 5782 5783 wl->status.map.scan = false; 5784 wl->scan_info.phy_map &= ~BIT(phy_idx); 5785 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 5786 5787 if (rtwdev->dbcc_en) { 5788 _update_dbcc_band(rtwdev, phy_idx); 5789 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5790 } 5791 5792 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 5793 } 5794 5795 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 5796 { 5797 struct rtw89_btc *btc = &rtwdev->btc; 5798 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5799 5800 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5801 "[BTC], %s(): phy_idx=%d, band=%d\n", 5802 __func__, phy_idx, band); 5803 5804 if (phy_idx >= RTW89_PHY_MAX) 5805 return; 5806 5807 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 5808 5809 wl->scan_info.band[phy_idx] = band; 5810 wl->scan_info.phy_map |= BIT(phy_idx); 5811 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 5812 5813 if (rtwdev->dbcc_en) { 5814 wl->dbcc_info.scan_band[phy_idx] = band; 5815 _update_dbcc_band(rtwdev, phy_idx); 5816 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5817 } 5818 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 5819 } 5820 5821 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 5822 enum btc_pkt_type pkt_type) 5823 { 5824 struct rtw89_btc *btc = &rtwdev->btc; 5825 struct rtw89_btc_cx *cx = &btc->cx; 5826 struct rtw89_btc_wl_info *wl = &cx->wl; 5827 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info; 5828 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 5829 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 5830 u32 cnt; 5831 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 5832 bool delay_work = false; 5833 5834 switch (pkt_type) { 5835 case PACKET_DHCP: 5836 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP]; 5837 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5838 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 5839 wl->status.map.connecting = true; 5840 delay_work = true; 5841 break; 5842 case PACKET_EAPOL: 5843 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 5844 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5845 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 5846 wl->status.map._4way = true; 5847 delay_work = true; 5848 if (hfp->exist || hid->exist) 5849 delay /= 2; 5850 break; 5851 case PACKET_EAPOL_END: 5852 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 5853 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5854 "[BTC], %s(): EAPOL_End cnt=%d\n", 5855 __func__, cnt); 5856 wl->status.map._4way = false; 5857 cancel_delayed_work(&rtwdev->coex_act1_work); 5858 break; 5859 case PACKET_ARP: 5860 cnt = ++cx->cnt_wl[BTC_WCNT_ARP]; 5861 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5862 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 5863 return; 5864 case PACKET_ICMP: 5865 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5866 "[BTC], %s(): ICMP pkt\n", __func__); 5867 return; 5868 default: 5869 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5870 "[BTC], %s(): unknown packet type %d\n", 5871 __func__, pkt_type); 5872 return; 5873 } 5874 5875 if (delay_work) { 5876 cancel_delayed_work(&rtwdev->coex_act1_work); 5877 ieee80211_queue_delayed_work(rtwdev->hw, 5878 &rtwdev->coex_act1_work, delay); 5879 } 5880 5881 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 5882 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 5883 } 5884 5885 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work) 5886 { 5887 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5888 btc.eapol_notify_work); 5889 5890 mutex_lock(&rtwdev->mutex); 5891 rtw89_leave_ps_mode(rtwdev); 5892 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 5893 mutex_unlock(&rtwdev->mutex); 5894 } 5895 5896 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work) 5897 { 5898 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5899 btc.arp_notify_work); 5900 5901 mutex_lock(&rtwdev->mutex); 5902 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 5903 mutex_unlock(&rtwdev->mutex); 5904 } 5905 5906 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work) 5907 { 5908 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5909 btc.dhcp_notify_work); 5910 5911 mutex_lock(&rtwdev->mutex); 5912 rtw89_leave_ps_mode(rtwdev); 5913 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 5914 mutex_unlock(&rtwdev->mutex); 5915 } 5916 5917 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work) 5918 { 5919 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5920 btc.icmp_notify_work); 5921 5922 mutex_lock(&rtwdev->mutex); 5923 rtw89_leave_ps_mode(rtwdev); 5924 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 5925 mutex_unlock(&rtwdev->mutex); 5926 } 5927 5928 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi) 5929 { 5930 const struct rtw89_chip_info *chip = rtwdev->chip; 5931 struct rtw89_btc *btc = &rtwdev->btc; 5932 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5933 u8 *rssi_st, rssi_th, rssi_level = 0; 5934 u8 i; 5935 5936 /* for rssi locate in which {40, 36, 31, 28} 5937 * if rssi >= 40% (-60dBm) --> rssi_level = 4 5938 * if 36% <= rssi < 40% --> rssi_level = 3 5939 * if 31% <= rssi < 36% --> rssi_level = 2 5940 * if 28% <= rssi < 31% --> rssi_level = 1 5941 * if rssi < 28% --> rssi_level = 0 5942 */ 5943 5944 /* check if rssi across bt_rssi_thres boundary */ 5945 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) { 5946 rssi_th = chip->bt_rssi_thres[i]; 5947 rssi_st = &bt->link_info.rssi_state[i]; 5948 5949 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th); 5950 5951 if (BTC_RSSI_HIGH(*rssi_st)) { 5952 rssi_level = BTC_BT_RSSI_THMAX - i; 5953 break; 5954 } 5955 } 5956 return rssi_level; 5957 } 5958 5959 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4) 5960 5961 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 5962 { 5963 const struct rtw89_chip_info *chip = rtwdev->chip; 5964 struct rtw89_btc *btc = &rtwdev->btc; 5965 struct rtw89_btc_cx *cx = &btc->cx; 5966 struct rtw89_btc_bt_info *bt = &cx->bt; 5967 struct rtw89_btc_bt_link_info *b = &bt->link_info; 5968 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 5969 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 5970 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 5971 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 5972 union btc_btinfo btinfo; 5973 5974 if (buf[BTC_BTINFO_L1] != 6) 5975 return; 5976 5977 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) { 5978 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5979 "[BTC], %s(): return by bt-info duplicate!!\n", 5980 __func__); 5981 cx->cnt_bt[BTC_BCNT_INFOSAME]++; 5982 return; 5983 } 5984 5985 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX); 5986 5987 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5988 "[BTC], %s(): bt_info[2]=0x%02x\n", 5989 __func__, bt->raw_info[2]); 5990 5991 /* reset to mo-connect before update */ 5992 b->status.val = BTC_BLINK_NOCONNECT; 5993 b->profile_cnt.last = b->profile_cnt.now; 5994 b->relink.last = b->relink.now; 5995 a2dp->exist_last = a2dp->exist; 5996 b->multi_link.last = b->multi_link.now; 5997 bt->inq_pag.last = bt->inq_pag.now; 5998 b->profile_cnt.now = 0; 5999 hid->type = 0; 6000 6001 /* parse raw info low-Byte2 */ 6002 btinfo.val = bt->raw_info[BTC_BTINFO_L2]; 6003 b->status.map.connect = btinfo.lb2.connect; 6004 b->status.map.sco_busy = btinfo.lb2.sco_busy; 6005 b->status.map.acl_busy = btinfo.lb2.acl_busy; 6006 b->status.map.inq_pag = btinfo.lb2.inq_pag; 6007 bt->inq_pag.now = btinfo.lb2.inq_pag; 6008 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 6009 6010 hfp->exist = btinfo.lb2.hfp; 6011 b->profile_cnt.now += (u8)hfp->exist; 6012 hid->exist = btinfo.lb2.hid; 6013 b->profile_cnt.now += (u8)hid->exist; 6014 a2dp->exist = btinfo.lb2.a2dp; 6015 b->profile_cnt.now += (u8)a2dp->exist; 6016 pan->active = btinfo.lb2.pan; 6017 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 6018 6019 /* parse raw info low-Byte3 */ 6020 btinfo.val = bt->raw_info[BTC_BTINFO_L3]; 6021 if (btinfo.lb3.retry != 0) 6022 cx->cnt_bt[BTC_BCNT_RETRY]++; 6023 b->cqddr = btinfo.lb3.cqddr; 6024 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 6025 bt->inq = btinfo.lb3.inq; 6026 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 6027 bt->pag = btinfo.lb3.pag; 6028 6029 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 6030 /* parse raw info high-Byte0 */ 6031 btinfo.val = bt->raw_info[BTC_BTINFO_H0]; 6032 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 6033 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 6034 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi); 6035 btc->dm.trx_info.bt_rssi = bt->rssi_level; 6036 6037 /* parse raw info high-Byte1 */ 6038 btinfo.val = bt->raw_info[BTC_BTINFO_H1]; 6039 b->status.map.ble_connect = btinfo.hb1.ble_connect; 6040 if (btinfo.hb1.ble_connect) 6041 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); 6042 6043 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 6044 bt->reinit = btinfo.hb1.reinit; 6045 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 6046 b->relink.now = btinfo.hb1.relink; 6047 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 6048 bt->igno_wl = btinfo.hb1.igno_wl; 6049 6050 if (bt->igno_wl && !cx->wl.status.map.rf_off) 6051 _set_bt_ignore_wlan_act(rtwdev, false); 6052 6053 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); 6054 bt->ble_scan_en = btinfo.hb1.ble_scan; 6055 6056 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 6057 b->role_sw = btinfo.hb1.role_sw; 6058 6059 b->multi_link.now = btinfo.hb1.multi_link; 6060 6061 /* parse raw info high-Byte2 */ 6062 btinfo.val = bt->raw_info[BTC_BTINFO_H2]; 6063 pan->exist = btinfo.hb2.pan_active; 6064 b->profile_cnt.now += (u8)pan->exist; 6065 6066 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 6067 b->afh_update = btinfo.hb2.afh_update; 6068 a2dp->active = btinfo.hb2.a2dp_active; 6069 b->slave_role = btinfo.hb2.slave; 6070 hid->slot_info = btinfo.hb2.hid_slot; 6071 hid->pair_cnt = btinfo.hb2.hid_cnt; 6072 hid->type |= (hid->slot_info == BTC_HID_218 ? 6073 BTC_HID_218 : BTC_HID_418); 6074 /* parse raw info high-Byte3 */ 6075 btinfo.val = bt->raw_info[BTC_BTINFO_H3]; 6076 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 6077 6078 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 6079 cx->cnt_bt[BTC_BCNT_RATECHG]++; 6080 b->tx_3m = (u32)btinfo.hb3.tx_3m; 6081 6082 a2dp->sink = btinfo.hb3.a2dp_sink; 6083 6084 if (!a2dp->exist_last && a2dp->exist) { 6085 a2dp->vendor_id = 0; 6086 a2dp->flush_time = 0; 6087 a2dp->play_latency = 1; 6088 ieee80211_queue_delayed_work(rtwdev->hw, 6089 &rtwdev->coex_bt_devinfo_work, 6090 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 6091 } 6092 6093 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 6094 } 6095 6096 enum btc_wl_mode { 6097 BTC_WL_MODE_HT = 0, 6098 BTC_WL_MODE_VHT = 1, 6099 BTC_WL_MODE_HE = 2, 6100 BTC_WL_MODE_NUM, 6101 }; 6102 6103 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 6104 struct rtw89_sta *rtwsta, enum btc_role_state state) 6105 { 6106 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, 6107 rtwvif->sub_entity_idx); 6108 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 6109 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); 6110 struct rtw89_btc *btc = &rtwdev->btc; 6111 const struct rtw89_btc_ver *ver = btc->ver; 6112 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6113 struct rtw89_btc_wl_link_info r = {0}; 6114 struct rtw89_btc_wl_link_info *wlinfo = NULL; 6115 u8 mode = 0; 6116 6117 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 6118 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6119 "[BTC], role is STA=%d\n", 6120 vif->type == NL80211_IFTYPE_STATION); 6121 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); 6122 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 6123 chan->band_type, chan->channel, chan->band_width); 6124 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 6125 state == BTC_ROLE_MSTS_STA_CONN_END); 6126 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6127 "[BTC], bcn_period=%d dtim_period=%d\n", 6128 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); 6129 6130 if (rtwsta) { 6131 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 6132 rtwsta->mac_id); 6133 6134 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6135 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 6136 sta->deflink.he_cap.has_he, 6137 sta->deflink.vht_cap.vht_supported, 6138 sta->deflink.ht_cap.ht_supported); 6139 if (sta->deflink.he_cap.has_he) 6140 mode |= BIT(BTC_WL_MODE_HE); 6141 if (sta->deflink.vht_cap.vht_supported) 6142 mode |= BIT(BTC_WL_MODE_VHT); 6143 if (sta->deflink.ht_cap.ht_supported) 6144 mode |= BIT(BTC_WL_MODE_HT); 6145 6146 r.mode = mode; 6147 } 6148 6149 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) 6150 return; 6151 6152 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6153 "[BTC], wifi_role=%d\n", rtwvif->wifi_role); 6154 6155 r.role = rtwvif->wifi_role; 6156 r.phy = rtwvif->phy_idx; 6157 r.pid = rtwvif->port; 6158 r.active = true; 6159 r.connected = MLME_LINKED; 6160 r.bcn_period = vif->bss_conf.beacon_int; 6161 r.dtim_period = vif->bss_conf.dtim_period; 6162 r.band = chan->band_type; 6163 r.ch = chan->channel; 6164 r.bw = chan->band_width; 6165 ether_addr_copy(r.mac_addr, rtwvif->mac_addr); 6166 6167 if (rtwsta && vif->type == NL80211_IFTYPE_STATION) 6168 r.mac_id = rtwsta->mac_id; 6169 6170 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 6171 6172 wlinfo = &wl->link_info[r.pid]; 6173 6174 memcpy(wlinfo, &r, sizeof(*wlinfo)); 6175 if (ver->fwlrole == 0) 6176 _update_wl_info(rtwdev); 6177 else if (ver->fwlrole == 1) 6178 _update_wl_info_v1(rtwdev); 6179 else if (ver->fwlrole == 2) 6180 _update_wl_info_v2(rtwdev); 6181 6182 if (wlinfo->role == RTW89_WIFI_ROLE_STATION && 6183 wlinfo->connected == MLME_NO_LINK) 6184 btc->dm.leak_ap = 0; 6185 6186 if (state == BTC_ROLE_MSTS_STA_CONN_START) 6187 wl->status.map.connecting = 1; 6188 else 6189 wl->status.map.connecting = 0; 6190 6191 if (state == BTC_ROLE_MSTS_STA_DIS_CONN) 6192 wl->status.map._4way = false; 6193 6194 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 6195 } 6196 6197 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 6198 { 6199 const struct rtw89_chip_info *chip = rtwdev->chip; 6200 struct rtw89_btc *btc = &rtwdev->btc; 6201 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6202 u32 val; 6203 6204 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 6205 __func__, rf_state); 6206 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 6207 6208 switch (rf_state) { 6209 case BTC_RFCTRL_WL_OFF: 6210 wl->status.map.rf_off = 1; 6211 wl->status.map.lps = BTC_LPS_OFF; 6212 wl->status.map.busy = 0; 6213 break; 6214 case BTC_RFCTRL_FW_CTRL: 6215 wl->status.map.rf_off = 0; 6216 wl->status.map.lps = BTC_LPS_RF_OFF; 6217 wl->status.map.busy = 0; 6218 break; 6219 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */ 6220 wl->status.map.rf_off = 0; 6221 wl->status.map.lps = BTC_LPS_RF_ON; 6222 wl->status.map.busy = 0; 6223 break; 6224 case BTC_RFCTRL_WL_ON: 6225 default: 6226 wl->status.map.rf_off = 0; 6227 wl->status.map.lps = BTC_LPS_OFF; 6228 break; 6229 } 6230 6231 if (rf_state == BTC_RFCTRL_WL_ON) { 6232 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true); 6233 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 6234 _write_scbd(rtwdev, val, true); 6235 _update_bt_scbd(rtwdev, true); 6236 chip->ops->btc_init_cfg(rtwdev); 6237 } else { 6238 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false); 6239 if (rf_state == BTC_RFCTRL_FW_CTRL) 6240 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false); 6241 else if (rf_state == BTC_RFCTRL_WL_OFF) 6242 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 6243 else 6244 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false); 6245 6246 if (rf_state == BTC_RFCTRL_LPS_WL_ON && 6247 wl->status.map.lps_pre != BTC_LPS_OFF) 6248 _update_bt_scbd(rtwdev, true); 6249 } 6250 6251 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 6252 btc->dm.tdma_instant_excute = 1; 6253 6254 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 6255 wl->status.map.rf_off_pre = wl->status.map.rf_off; 6256 wl->status.map.lps_pre = wl->status.map.lps; 6257 } 6258 6259 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 6260 enum btc_wl_rfk_type type, 6261 enum btc_wl_rfk_state state) 6262 { 6263 struct rtw89_btc *btc = &rtwdev->btc; 6264 struct rtw89_btc_cx *cx = &btc->cx; 6265 struct rtw89_btc_wl_info *wl = &cx->wl; 6266 bool result = BTC_WRFK_REJECT; 6267 6268 wl->rfk_info.type = type; 6269 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 6270 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 6271 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 6272 6273 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6274 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 6275 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 6276 type, state); 6277 6278 switch (state) { 6279 case BTC_WRFK_START: 6280 result = _chk_wl_rfk_request(rtwdev); 6281 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP; 6282 6283 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result); 6284 6285 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 6286 break; 6287 case BTC_WRFK_ONESHOT_START: 6288 case BTC_WRFK_ONESHOT_STOP: 6289 if (wl->rfk_info.state == BTC_WRFK_STOP) { 6290 result = BTC_WRFK_REJECT; 6291 } else { 6292 result = BTC_WRFK_ALLOW; 6293 wl->rfk_info.state = state; 6294 } 6295 break; 6296 case BTC_WRFK_STOP: 6297 result = BTC_WRFK_ALLOW; 6298 wl->rfk_info.state = BTC_WRFK_STOP; 6299 6300 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 6301 cancel_delayed_work(&rtwdev->coex_rfk_chk_work); 6302 break; 6303 default: 6304 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6305 "[BTC], %s() warning state=%d\n", __func__, state); 6306 break; 6307 } 6308 6309 if (result == BTC_WRFK_ALLOW) { 6310 if (wl->rfk_info.state == BTC_WRFK_START || 6311 wl->rfk_info.state == BTC_WRFK_STOP) 6312 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 6313 6314 if (wl->rfk_info.state == BTC_WRFK_START) 6315 ieee80211_queue_delayed_work(rtwdev->hw, 6316 &rtwdev->coex_rfk_chk_work, 6317 RTW89_COEX_RFK_CHK_WORK_PERIOD); 6318 } 6319 6320 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6321 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 6322 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 6323 6324 return result == BTC_WRFK_ALLOW; 6325 } 6326 6327 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 6328 enum btc_wl_rfk_type type, 6329 enum btc_wl_rfk_state state) 6330 { 6331 u8 band; 6332 bool allow; 6333 int ret; 6334 6335 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 6336 6337 rtw89_debug(rtwdev, RTW89_DBG_RFK, 6338 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 6339 band == RTW89_BAND_2G ? "2G" : 6340 band == RTW89_BAND_5G ? "5G" : "6G", 6341 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 6342 type, 6343 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 6344 state == BTC_WRFK_STOP ? "RFK_STOP" : 6345 state == BTC_WRFK_START ? "RFK_START" : 6346 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 6347 "ONE-SHOT_STOP"); 6348 6349 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 6350 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 6351 return; 6352 } 6353 6354 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 6355 rtwdev, phy_map, type, state); 6356 if (ret) { 6357 rtw89_warn(rtwdev, "RFK notify timeout\n"); 6358 rtwdev->is_bt_iqk_timeout = true; 6359 } 6360 } 6361 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 6362 6363 struct rtw89_btc_wl_sta_iter_data { 6364 struct rtw89_dev *rtwdev; 6365 u8 busy_all; 6366 u8 dir_all; 6367 u8 rssi_map_all; 6368 bool is_sta_change; 6369 bool is_traffic_change; 6370 }; 6371 6372 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 6373 { 6374 struct rtw89_btc_wl_sta_iter_data *iter_data = 6375 (struct rtw89_btc_wl_sta_iter_data *)data; 6376 struct rtw89_dev *rtwdev = iter_data->rtwdev; 6377 struct rtw89_btc *btc = &rtwdev->btc; 6378 struct rtw89_btc_dm *dm = &btc->dm; 6379 const struct rtw89_btc_ver *ver = btc->ver; 6380 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6381 struct rtw89_btc_wl_link_info *link_info = NULL; 6382 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 6383 struct rtw89_traffic_stats *link_info_t = NULL; 6384 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 6385 struct rtw89_traffic_stats *stats = &rtwvif->stats; 6386 const struct rtw89_chip_info *chip = rtwdev->chip; 6387 struct rtw89_btc_wl_role_info *r; 6388 struct rtw89_btc_wl_role_info_v1 *r1; 6389 u32 last_tx_rate, last_rx_rate; 6390 u16 last_tx_lvl, last_rx_lvl; 6391 u8 port = rtwvif->port; 6392 u8 rssi; 6393 u8 busy = 0; 6394 u8 dir = 0; 6395 u8 rssi_map = 0; 6396 u8 i = 0; 6397 bool is_sta_change = false, is_traffic_change = false; 6398 6399 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; 6400 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 6401 6402 link_info = &wl->link_info[port]; 6403 link_info->stat.traffic = rtwvif->stats; 6404 link_info_t = &link_info->stat.traffic; 6405 6406 if (link_info->connected == MLME_NO_LINK) { 6407 link_info->rx_rate_drop_cnt = 0; 6408 return; 6409 } 6410 6411 link_info->stat.rssi = rssi; 6412 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 6413 link_info->rssi_state[i] = 6414 _update_rssi_state(rtwdev, 6415 link_info->rssi_state[i], 6416 link_info->stat.rssi, 6417 chip->wl_rssi_thres[i]); 6418 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 6419 rssi_map |= BIT(i); 6420 6421 if (btc->ant_type == BTC_ANT_DEDICATED && 6422 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 6423 is_sta_change = true; 6424 } 6425 iter_data->rssi_map_all |= rssi_map; 6426 6427 last_tx_rate = link_info_t->tx_rate; 6428 last_rx_rate = link_info_t->rx_rate; 6429 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 6430 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 6431 6432 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 6433 stats->rx_tfc_lv != RTW89_TFC_IDLE) 6434 busy = 1; 6435 6436 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 6437 dir = RTW89_TFC_UL; 6438 else 6439 dir = RTW89_TFC_DL; 6440 6441 link_info = &wl->link_info[port]; 6442 if (link_info->busy != busy || link_info->dir != dir) { 6443 is_sta_change = true; 6444 link_info->busy = busy; 6445 link_info->dir = dir; 6446 } 6447 6448 iter_data->busy_all |= busy; 6449 iter_data->dir_all |= BIT(dir); 6450 6451 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 6452 last_rx_rate > RTW89_HW_RATE_CCK2 && 6453 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 6454 link_info->rx_rate_drop_cnt++; 6455 6456 if (last_tx_rate != rtwsta->ra_report.hw_rate || 6457 last_rx_rate != rtwsta->rx_hw_rate || 6458 last_tx_lvl != link_info_t->tx_tfc_lv || 6459 last_rx_lvl != link_info_t->rx_tfc_lv) 6460 is_traffic_change = true; 6461 6462 link_info_t->tx_rate = rtwsta->ra_report.hw_rate; 6463 link_info_t->rx_rate = rtwsta->rx_hw_rate; 6464 6465 if (link_info->role == RTW89_WIFI_ROLE_STATION || 6466 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { 6467 dm->trx_info.tx_rate = link_info_t->tx_rate; 6468 dm->trx_info.rx_rate = link_info_t->rx_rate; 6469 } 6470 6471 if (ver->fwlrole == 0) { 6472 r = &wl->role_info; 6473 r->active_role[port].tx_lvl = stats->tx_tfc_lv; 6474 r->active_role[port].rx_lvl = stats->rx_tfc_lv; 6475 r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate; 6476 r->active_role[port].rx_rate = rtwsta->rx_hw_rate; 6477 } else if (ver->fwlrole == 1) { 6478 r1 = &wl->role_info_v1; 6479 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; 6480 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; 6481 r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate; 6482 r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate; 6483 } else if (ver->fwlrole == 2) { 6484 dm->trx_info.tx_lvl = stats->tx_tfc_lv; 6485 dm->trx_info.rx_lvl = stats->rx_tfc_lv; 6486 dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate; 6487 dm->trx_info.rx_rate = rtwsta->rx_hw_rate; 6488 } 6489 6490 dm->trx_info.tx_tp = link_info_t->tx_throughput; 6491 dm->trx_info.rx_tp = link_info_t->rx_throughput; 6492 6493 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */ 6494 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx && 6495 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) || 6496 (dm->wl_pre_agc_rb != dm->wl_pre_agc && 6497 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND)) 6498 iter_data->is_sta_change = true; 6499 6500 if (is_sta_change) 6501 iter_data->is_sta_change = true; 6502 6503 if (is_traffic_change) 6504 iter_data->is_traffic_change = true; 6505 } 6506 6507 #define BTC_NHM_CHK_INTVL 20 6508 6509 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 6510 { 6511 struct rtw89_btc *btc = &rtwdev->btc; 6512 struct rtw89_btc_dm *dm = &btc->dm; 6513 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6514 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 6515 u8 i; 6516 6517 ieee80211_iterate_stations_atomic(rtwdev->hw, 6518 rtw89_btc_ntfy_wl_sta_iter, 6519 &data); 6520 6521 wl->rssi_level = 0; 6522 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 6523 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 6524 /* set RSSI level 4 ~ 0 if rssi bit map match */ 6525 if (data.rssi_map_all & BIT(i - 1)) { 6526 wl->rssi_level = i; 6527 break; 6528 } 6529 } 6530 6531 if (dm->trx_info.wl_rssi != wl->rssi_level) 6532 dm->trx_info.wl_rssi = wl->rssi_level; 6533 6534 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 6535 __func__, !!wl->status.map.busy); 6536 6537 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 6538 6539 if (data.is_traffic_change) 6540 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6541 if (data.is_sta_change) { 6542 wl->status.map.busy = data.busy_all; 6543 wl->status.map.traffic_dir = data.dir_all; 6544 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 6545 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 6546 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 6547 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 6548 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 6549 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 6550 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 6551 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 6552 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 6553 } 6554 } 6555 6556 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 6557 u32 len, u8 class, u8 func) 6558 { 6559 struct rtw89_btc *btc = &rtwdev->btc; 6560 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6561 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 6562 6563 len -= RTW89_C2H_HEADER_LEN; 6564 6565 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6566 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 6567 __func__, len, class, func); 6568 6569 if (class != BTFC_FW_EVENT) 6570 return; 6571 6572 switch (func) { 6573 case BTF_EVNT_RPT: 6574 case BTF_EVNT_BUF_OVERFLOW: 6575 pfwinfo->event[func]++; 6576 /* Don't need rtw89_leave_ps_mode() */ 6577 btc_fw_event(rtwdev, func, buf, len); 6578 break; 6579 case BTF_EVNT_BT_INFO: 6580 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6581 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 6582 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++; 6583 _update_bt_info(rtwdev, buf, len); 6584 break; 6585 case BTF_EVNT_BT_SCBD: 6586 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6587 "[BTC], handle C2H BT SCBD with data %8ph\n", buf); 6588 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++; 6589 _update_bt_scbd(rtwdev, false); 6590 break; 6591 case BTF_EVNT_BT_PSD: 6592 break; 6593 case BTF_EVNT_BT_REG: 6594 btc->dbg.rb_done = true; 6595 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 6596 6597 break; 6598 case BTF_EVNT_C2H_LOOPBACK: 6599 btc->dbg.rb_done = true; 6600 btc->dbg.rb_val = buf[0]; 6601 break; 6602 case BTF_EVNT_CX_RUNINFO: 6603 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 6604 break; 6605 } 6606 } 6607 6608 #define BTC_CX_FW_OFFLOAD 0 6609 6610 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6611 { 6612 union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; 6613 const struct rtw89_chip_info *chip = rtwdev->chip; 6614 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 6615 struct rtw89_hal *hal = &rtwdev->hal; 6616 struct rtw89_btc *btc = &rtwdev->btc; 6617 struct rtw89_btc_dm *dm = &btc->dm; 6618 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6619 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6620 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 6621 u8 cv, rfe, iso, ant_num, ant_single_pos; 6622 6623 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 6624 return; 6625 6626 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 6627 6628 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n", 6629 chip->chip_id); 6630 6631 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 6632 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 6633 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 6634 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 6635 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ", 6636 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch); 6637 6638 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 6639 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 6640 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 6641 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 6642 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)", 6643 ver_main, ver_sub, ver_hotfix, id_branch); 6644 6645 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 6646 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 6647 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 6648 seq_printf(m, "(%s, desired:%d.%d.%d), ", 6649 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 6650 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 6651 6652 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n", 6653 bt->ver_info.fw_coex, 6654 (bt->ver_info.fw_coex >= chip->btcx_desired ? 6655 "Match" : "Mismatch"), chip->btcx_desired); 6656 6657 if (bt->enable.now && bt->ver_info.fw == 0) 6658 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 6659 else 6660 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 6661 6662 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 6663 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 6664 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 6665 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 6666 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n", 6667 "[sub_module]", 6668 ver_main, ver_sub, ver_hotfix, id_branch, 6669 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 6670 6671 if (ver->fcxinit == 7) { 6672 cv = md->md_v7.kt_ver; 6673 rfe = md->md_v7.rfe_type; 6674 iso = md->md_v7.ant.isolation; 6675 ant_num = md->md_v7.ant.num; 6676 ant_single_pos = md->md_v7.ant.single_pos; 6677 } else { 6678 cv = md->md.cv; 6679 rfe = md->md.rfe_type; 6680 iso = md->md.ant.isolation; 6681 ant_num = md->md.ant.num; 6682 ant_single_pos = md->md.ant.single_pos; 6683 } 6684 6685 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 6686 "[hw_info]", cv, rfe, iso, ant_num, 6687 ant_num > 1 ? "" : 6688 ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, "); 6689 6690 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 6691 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, 6692 hal->rx_nss); 6693 } 6694 6695 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6696 { 6697 struct rtw89_btc *btc = &rtwdev->btc; 6698 struct rtw89_btc_wl_link_info *plink = NULL; 6699 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6700 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6701 struct rtw89_traffic_stats *t; 6702 u8 i; 6703 6704 if (rtwdev->dbcc_en) { 6705 seq_printf(m, 6706 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ", 6707 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0], 6708 wl_dinfo->scan_band[RTW89_PHY_0], 6709 wl_dinfo->real_band[RTW89_PHY_0]); 6710 seq_printf(m, 6711 "PHY1_band(op:%d/scan:%d/real:%d)\n", 6712 wl_dinfo->op_band[RTW89_PHY_1], 6713 wl_dinfo->scan_band[RTW89_PHY_1], 6714 wl_dinfo->real_band[RTW89_PHY_1]); 6715 } 6716 6717 for (i = 0; i < RTW89_PORT_NUM; i++) { 6718 plink = &btc->cx.wl.link_info[i]; 6719 6720 if (!plink->active) 6721 continue; 6722 6723 seq_printf(m, 6724 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 6725 plink->pid, (u32)plink->role, plink->phy, 6726 (u32)plink->connected, plink->client_cnt - 1, 6727 (u32)plink->mode, plink->ch, (u32)plink->bw); 6728 6729 if (plink->connected == MLME_NO_LINK) 6730 continue; 6731 6732 seq_printf(m, 6733 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 6734 plink->mac_id, plink->tx_time, plink->tx_retry); 6735 6736 seq_printf(m, 6737 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 6738 plink->pid, 110 - plink->stat.rssi, 6739 plink->stat.rssi, plink->busy, 6740 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 6741 6742 t = &plink->stat.traffic; 6743 6744 seq_printf(m, 6745 "tx[rate:%d/busy_level:%d], ", 6746 (u32)t->tx_rate, t->tx_tfc_lv); 6747 6748 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n", 6749 (u32)t->rx_rate, 6750 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 6751 } 6752 } 6753 6754 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6755 { 6756 struct rtw89_btc *btc = &rtwdev->btc; 6757 const struct rtw89_btc_ver *ver = btc->ver; 6758 struct rtw89_btc_cx *cx = &btc->cx; 6759 struct rtw89_btc_wl_info *wl = &cx->wl; 6760 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6761 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 6762 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 6763 u8 mode; 6764 6765 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 6766 return; 6767 6768 seq_puts(m, "========== [WL Status] ==========\n"); 6769 6770 if (ver->fwlrole == 0) 6771 mode = wl_rinfo->link_mode; 6772 else if (ver->fwlrole == 1) 6773 mode = wl_rinfo_v1->link_mode; 6774 else if (ver->fwlrole == 2) 6775 mode = wl_rinfo_v2->link_mode; 6776 else 6777 return; 6778 6779 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode); 6780 6781 seq_printf(m, 6782 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 6783 wl->status.map.rf_off, wl->status.map.lps, 6784 wl->status.map.scan ? "Y" : "N", 6785 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 6786 6787 seq_printf(m, 6788 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n", 6789 wl->status.map.connecting ? "Y" : "N", 6790 wl->status.map.roaming ? "Y" : "N", 6791 wl->status.map._4way ? "Y" : "N", 6792 wl->status.map.init_ok ? "Y" : "N"); 6793 6794 _show_wl_role_info(rtwdev, m); 6795 } 6796 6797 enum btc_bt_a2dp_type { 6798 BTC_A2DP_LEGACY = 0, 6799 BTC_A2DP_TWS_SNIFF = 1, 6800 BTC_A2DP_TWS_RELAY = 2, 6801 }; 6802 6803 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6804 { 6805 struct rtw89_btc *btc = &rtwdev->btc; 6806 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 6807 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 6808 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 6809 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 6810 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 6811 6812 if (hfp.exist) { 6813 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 6814 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 6815 bt_linfo->sut_pwr_level[0], 6816 bt_linfo->golden_rx_shift[0]); 6817 } 6818 6819 if (hid.exist) { 6820 seq_printf(m, 6821 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 6822 "[HID]", 6823 hid.type & BTC_HID_218 ? "2/18," : "", 6824 hid.type & BTC_HID_418 ? "4/18," : "", 6825 hid.type & BTC_HID_BLE ? "BLE," : "", 6826 hid.type & BTC_HID_RCU ? "RCU," : "", 6827 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 6828 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 6829 bt_linfo->golden_rx_shift[1]); 6830 } 6831 6832 if (a2dp.exist) { 6833 seq_printf(m, 6834 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 6835 "[A2DP]", 6836 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 6837 a2dp.bitpool, a2dp.flush_time); 6838 6839 seq_printf(m, 6840 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 6841 a2dp.vendor_id, a2dp.device_name, 6842 bt_linfo->sut_pwr_level[2], 6843 bt_linfo->golden_rx_shift[2]); 6844 } 6845 6846 if (pan.exist) { 6847 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n", 6848 "[PAN]", 6849 bt_linfo->sut_pwr_level[3], 6850 bt_linfo->golden_rx_shift[3]); 6851 } 6852 } 6853 6854 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6855 { 6856 struct rtw89_btc *btc = &rtwdev->btc; 6857 const struct rtw89_btc_ver *ver = btc->ver; 6858 struct rtw89_btc_cx *cx = &btc->cx; 6859 struct rtw89_btc_bt_info *bt = &cx->bt; 6860 struct rtw89_btc_wl_info *wl = &cx->wl; 6861 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 6862 union rtw89_btc_module_info *md = &btc->mdinfo; 6863 u8 *afh = bt_linfo->afh_map; 6864 u8 *afh_le = bt_linfo->afh_map_le; 6865 u8 bt_pos; 6866 6867 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 6868 return; 6869 6870 if (ver->fcxinit == 7) 6871 bt_pos = md->md_v7.bt_pos; 6872 else 6873 bt_pos = md->md.bt_pos; 6874 6875 seq_puts(m, "========== [BT Status] ==========\n"); 6876 6877 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ", 6878 "[status]", bt->enable.now ? "Y" : "N", 6879 bt->btg_type ? "Y" : "N", 6880 (bt->enable.now && (bt->btg_type != bt_pos) ? 6881 "(efuse-mismatch!!)" : ""), 6882 (bt_linfo->status.map.connect ? "Y" : "N")); 6883 6884 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 6885 bt->igno_wl ? "Y" : "N", 6886 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 6887 6888 seq_printf(m, " %-15s : profile:%s%s%s%s%s ", 6889 "[profile]", 6890 (bt_linfo->profile_cnt.now == 0) ? "None," : "", 6891 bt_linfo->hfp_desc.exist ? "HFP," : "", 6892 bt_linfo->hid_desc.exist ? "HID," : "", 6893 bt_linfo->a2dp_desc.exist ? 6894 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 6895 bt_linfo->pan_desc.exist ? "PAN," : ""); 6896 6897 seq_printf(m, 6898 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 6899 bt_linfo->multi_link.now ? "Y" : "N", 6900 bt_linfo->slave_role ? "Slave" : "Master", 6901 bt_linfo->status.map.ble_connect ? "Y" : "N", 6902 bt_linfo->cqddr ? "Y" : "N", 6903 bt_linfo->a2dp_desc.active ? "Y" : "N", 6904 bt_linfo->pan_desc.active ? "Y" : "N"); 6905 6906 seq_printf(m, 6907 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s", 6908 "[link]", bt_linfo->rssi - 100, 6909 bt->rssi_level, 6910 bt_linfo->tx_3m ? 3 : 2, 6911 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 6912 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 6913 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 6914 6915 seq_printf(m, 6916 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 6917 bt_linfo->relink.now ? " ReLink!!" : "", 6918 afh[0], afh[1], afh[2], afh[3], afh[4], 6919 afh[5], afh[6], afh[7], afh[8], afh[9]); 6920 6921 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 6922 seq_printf(m, 6923 "LE[%02x%02x_%02x_%02x%02x]", 6924 afh_le[0], afh_le[1], afh_le[2], 6925 afh_le[3], afh_le[4]); 6926 6927 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n", 6928 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw); 6929 6930 seq_printf(m, 6931 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 6932 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY], 6933 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG], 6934 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]); 6935 6936 seq_printf(m, 6937 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 6938 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH], 6939 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ], 6940 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]); 6941 6942 _show_bt_profile_info(rtwdev, m); 6943 6944 seq_printf(m, 6945 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 6946 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 6947 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 6948 bt->raw_info[7], 6949 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 6950 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 6951 cx->cnt_bt[BTC_BCNT_INFOSAME]); 6952 6953 seq_printf(m, 6954 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)", 6955 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX], 6956 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX], 6957 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]); 6958 6959 if (!bt->scan_info_update) { 6960 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true); 6961 seq_puts(m, "\n"); 6962 } else { 6963 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false); 6964 if (ver->fcxbtscan == 1) { 6965 seq_printf(m, 6966 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)", 6967 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win), 6968 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl), 6969 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win), 6970 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl), 6971 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win), 6972 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl), 6973 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win), 6974 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl)); 6975 } else if (ver->fcxbtscan == 2) { 6976 seq_printf(m, 6977 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)", 6978 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win), 6979 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl), 6980 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win), 6981 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl), 6982 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win), 6983 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl)); 6984 } 6985 seq_puts(m, "\n"); 6986 } 6987 6988 if (bt->enable.now && bt->ver_info.fw == 0) 6989 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 6990 else 6991 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 6992 6993 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect) 6994 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true); 6995 else 6996 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false); 6997 6998 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 6999 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true); 7000 else 7001 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false); 7002 7003 if (bt_linfo->a2dp_desc.exist && 7004 (bt_linfo->a2dp_desc.flush_time == 0 || 7005 bt_linfo->a2dp_desc.vendor_id == 0 || 7006 bt_linfo->a2dp_desc.play_latency == 1)) 7007 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true); 7008 else 7009 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false); 7010 } 7011 7012 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 7013 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 7014 #define CASE_BTC_POLICY_STR(e) \ 7015 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 7016 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 7017 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e 7018 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e 7019 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e 7020 7021 static const char *steps_to_str(u16 step) 7022 { 7023 switch (step) { 7024 CASE_BTC_RSN_STR(NONE); 7025 CASE_BTC_RSN_STR(NTFY_INIT); 7026 CASE_BTC_RSN_STR(NTFY_SWBAND); 7027 CASE_BTC_RSN_STR(NTFY_WL_STA); 7028 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 7029 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 7030 CASE_BTC_RSN_STR(NTFY_WL_RFK); 7031 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 7032 CASE_BTC_RSN_STR(NTFY_SCAN_START); 7033 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 7034 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 7035 CASE_BTC_RSN_STR(NTFY_POWEROFF); 7036 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 7037 CASE_BTC_RSN_STR(CMD_SET_COEX); 7038 CASE_BTC_RSN_STR(ACT1_WORK); 7039 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 7040 CASE_BTC_RSN_STR(RFK_CHK_WORK); 7041 7042 CASE_BTC_ACT_STR(NONE); 7043 CASE_BTC_ACT_STR(WL_ONLY); 7044 CASE_BTC_ACT_STR(WL_5G); 7045 CASE_BTC_ACT_STR(WL_OTHER); 7046 CASE_BTC_ACT_STR(WL_IDLE); 7047 CASE_BTC_ACT_STR(WL_NC); 7048 CASE_BTC_ACT_STR(WL_RFK); 7049 CASE_BTC_ACT_STR(WL_INIT); 7050 CASE_BTC_ACT_STR(WL_OFF); 7051 CASE_BTC_ACT_STR(FREERUN); 7052 CASE_BTC_ACT_STR(BT_WHQL); 7053 CASE_BTC_ACT_STR(BT_RFK); 7054 CASE_BTC_ACT_STR(BT_OFF); 7055 CASE_BTC_ACT_STR(BT_IDLE); 7056 CASE_BTC_ACT_STR(BT_HFP); 7057 CASE_BTC_ACT_STR(BT_HID); 7058 CASE_BTC_ACT_STR(BT_A2DP); 7059 CASE_BTC_ACT_STR(BT_A2DPSINK); 7060 CASE_BTC_ACT_STR(BT_PAN); 7061 CASE_BTC_ACT_STR(BT_A2DP_HID); 7062 CASE_BTC_ACT_STR(BT_A2DP_PAN); 7063 CASE_BTC_ACT_STR(BT_PAN_HID); 7064 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 7065 CASE_BTC_ACT_STR(WL_25G_MCC); 7066 CASE_BTC_ACT_STR(WL_2G_MCC); 7067 CASE_BTC_ACT_STR(WL_2G_SCC); 7068 CASE_BTC_ACT_STR(WL_2G_AP); 7069 CASE_BTC_ACT_STR(WL_2G_GO); 7070 CASE_BTC_ACT_STR(WL_2G_GC); 7071 CASE_BTC_ACT_STR(WL_2G_NAN); 7072 7073 CASE_BTC_POLICY_STR(OFF_BT); 7074 CASE_BTC_POLICY_STR(OFF_WL); 7075 CASE_BTC_POLICY_STR(OFF_EQ0); 7076 CASE_BTC_POLICY_STR(OFF_EQ1); 7077 CASE_BTC_POLICY_STR(OFF_EQ2); 7078 CASE_BTC_POLICY_STR(OFF_EQ3); 7079 CASE_BTC_POLICY_STR(OFF_EQ4); 7080 CASE_BTC_POLICY_STR(OFF_EQ5); 7081 CASE_BTC_POLICY_STR(OFF_BWB0); 7082 CASE_BTC_POLICY_STR(OFF_BWB1); 7083 CASE_BTC_POLICY_STR(OFF_BWB2); 7084 CASE_BTC_POLICY_STR(OFF_BWB3); 7085 CASE_BTC_POLICY_STR(OFF_WL2); 7086 CASE_BTC_POLICY_STR(OFFB_BWB0); 7087 CASE_BTC_POLICY_STR(OFFE_DEF); 7088 CASE_BTC_POLICY_STR(OFFE_DEF2); 7089 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 7090 CASE_BTC_POLICY_STR(OFFE_2GISOB); 7091 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 7092 CASE_BTC_POLICY_STR(OFFE_WL); 7093 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 7094 CASE_BTC_POLICY_STR(FIX_TD3030); 7095 CASE_BTC_POLICY_STR(FIX_TD5050); 7096 CASE_BTC_POLICY_STR(FIX_TD2030); 7097 CASE_BTC_POLICY_STR(FIX_TD4010); 7098 CASE_BTC_POLICY_STR(FIX_TD7010); 7099 CASE_BTC_POLICY_STR(FIX_TD2060); 7100 CASE_BTC_POLICY_STR(FIX_TD3060); 7101 CASE_BTC_POLICY_STR(FIX_TD2080); 7102 CASE_BTC_POLICY_STR(FIX_TDW1B1); 7103 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 7104 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL); 7105 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL); 7106 CASE_BTC_POLICY_STR(PFIX_TD3030); 7107 CASE_BTC_POLICY_STR(PFIX_TD5050); 7108 CASE_BTC_POLICY_STR(PFIX_TD2030); 7109 CASE_BTC_POLICY_STR(PFIX_TD2060); 7110 CASE_BTC_POLICY_STR(PFIX_TD3070); 7111 CASE_BTC_POLICY_STR(PFIX_TD2080); 7112 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 7113 CASE_BTC_POLICY_STR(AUTO_TD50B1); 7114 CASE_BTC_POLICY_STR(AUTO_TD60B1); 7115 CASE_BTC_POLICY_STR(AUTO_TD20B1); 7116 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 7117 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 7118 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 7119 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 7120 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 7121 CASE_BTC_POLICY_STR(AUTO2_TD3050); 7122 CASE_BTC_POLICY_STR(AUTO2_TD3070); 7123 CASE_BTC_POLICY_STR(AUTO2_TD5050); 7124 CASE_BTC_POLICY_STR(AUTO2_TD6060); 7125 CASE_BTC_POLICY_STR(AUTO2_TD2080); 7126 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 7127 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 7128 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 7129 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 7130 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 7131 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 7132 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 7133 default: 7134 return "unknown step"; 7135 } 7136 } 7137 7138 static const char *id_to_slot(u32 id) 7139 { 7140 switch (id) { 7141 CASE_BTC_SLOT_STR(OFF); 7142 CASE_BTC_SLOT_STR(B2W); 7143 CASE_BTC_SLOT_STR(W1); 7144 CASE_BTC_SLOT_STR(W2); 7145 CASE_BTC_SLOT_STR(W2B); 7146 CASE_BTC_SLOT_STR(B1); 7147 CASE_BTC_SLOT_STR(B2); 7148 CASE_BTC_SLOT_STR(B3); 7149 CASE_BTC_SLOT_STR(B4); 7150 CASE_BTC_SLOT_STR(LK); 7151 CASE_BTC_SLOT_STR(BLK); 7152 CASE_BTC_SLOT_STR(E2G); 7153 CASE_BTC_SLOT_STR(E5G); 7154 CASE_BTC_SLOT_STR(EBT); 7155 CASE_BTC_SLOT_STR(ENULL); 7156 CASE_BTC_SLOT_STR(WLK); 7157 CASE_BTC_SLOT_STR(W1FDD); 7158 CASE_BTC_SLOT_STR(B1FDD); 7159 default: 7160 return "unknown"; 7161 } 7162 } 7163 7164 static const char *id_to_evt(u32 id) 7165 { 7166 switch (id) { 7167 CASE_BTC_EVT_STR(TDMA_ENTRY); 7168 CASE_BTC_EVT_STR(WL_TMR); 7169 CASE_BTC_EVT_STR(B1_TMR); 7170 CASE_BTC_EVT_STR(B2_TMR); 7171 CASE_BTC_EVT_STR(B3_TMR); 7172 CASE_BTC_EVT_STR(B4_TMR); 7173 CASE_BTC_EVT_STR(W2B_TMR); 7174 CASE_BTC_EVT_STR(B2W_TMR); 7175 CASE_BTC_EVT_STR(BCN_EARLY); 7176 CASE_BTC_EVT_STR(A2DP_EMPTY); 7177 CASE_BTC_EVT_STR(LK_END); 7178 CASE_BTC_EVT_STR(RX_ISR); 7179 CASE_BTC_EVT_STR(RX_FC0); 7180 CASE_BTC_EVT_STR(RX_FC1); 7181 CASE_BTC_EVT_STR(BT_RELINK); 7182 CASE_BTC_EVT_STR(BT_RETRY); 7183 CASE_BTC_EVT_STR(E2G); 7184 CASE_BTC_EVT_STR(E5G); 7185 CASE_BTC_EVT_STR(EBT); 7186 CASE_BTC_EVT_STR(ENULL); 7187 CASE_BTC_EVT_STR(DRV_WLK); 7188 CASE_BTC_EVT_STR(BCN_OK); 7189 CASE_BTC_EVT_STR(BT_CHANGE); 7190 CASE_BTC_EVT_STR(EBT_EXTEND); 7191 CASE_BTC_EVT_STR(E2G_NULL1); 7192 CASE_BTC_EVT_STR(B1FDD_TMR); 7193 default: 7194 return "unknown"; 7195 } 7196 } 7197 7198 static const char *id_to_mode(u8 id) 7199 { 7200 switch (id) { 7201 CASE_BTC_INIT(NORMAL); 7202 CASE_BTC_INIT(WL); 7203 CASE_BTC_INIT(BT); 7204 CASE_BTC_INIT(WLOFF); 7205 default: 7206 return "unknown"; 7207 } 7208 } 7209 7210 static const char *id_to_ant(u32 id) 7211 { 7212 switch (id) { 7213 CASE_BTC_ANTPATH_STR(WPOWERON); 7214 CASE_BTC_ANTPATH_STR(WINIT); 7215 CASE_BTC_ANTPATH_STR(WONLY); 7216 CASE_BTC_ANTPATH_STR(WOFF); 7217 CASE_BTC_ANTPATH_STR(W2G); 7218 CASE_BTC_ANTPATH_STR(W5G); 7219 CASE_BTC_ANTPATH_STR(W25G); 7220 CASE_BTC_ANTPATH_STR(FREERUN); 7221 CASE_BTC_ANTPATH_STR(WRFK); 7222 CASE_BTC_ANTPATH_STR(BRFK); 7223 CASE_BTC_ANTPATH_STR(MAX); 7224 default: 7225 return "unknown"; 7226 } 7227 } 7228 7229 static 7230 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data, 7231 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 7232 { 7233 u8 i; 7234 u8 cur_index; 7235 7236 for (i = 0; i < len ; i++) { 7237 if ((i % seg_len) == 0) 7238 seq_printf(m, " %-15s : ", prefix); 7239 cur_index = (start_idx + i) % ring_len; 7240 if (i % 3 == 0) 7241 seq_printf(m, "-> %-20s", 7242 steps_to_str(*(data + cur_index))); 7243 else if (i % 3 == 1) 7244 seq_printf(m, "-> %-15s", 7245 steps_to_str(*(data + cur_index))); 7246 else 7247 seq_printf(m, "-> %-13s", 7248 steps_to_str(*(data + cur_index))); 7249 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 7250 seq_puts(m, "\n"); 7251 } 7252 } 7253 7254 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m) 7255 { 7256 struct rtw89_btc *btc = &rtwdev->btc; 7257 struct rtw89_btc_dm *dm = &btc->dm; 7258 u8 start_idx; 7259 u8 len; 7260 7261 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 7262 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 7263 7264 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx, 7265 ARRAY_SIZE(dm->dm_step.step)); 7266 } 7267 7268 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m) 7269 { 7270 struct rtw89_btc *btc = &rtwdev->btc; 7271 const struct rtw89_btc_ver *ver = btc->ver; 7272 struct rtw89_btc_dm *dm = &btc->dm; 7273 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7274 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7275 u8 igno_bt; 7276 7277 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 7278 return; 7279 7280 seq_printf(m, "========== [Mechanism Status %s] ==========\n", 7281 (btc->manual_ctrl ? "(Manual)" : "(Auto)")); 7282 7283 seq_printf(m, 7284 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n", 7285 "[status]", 7286 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated", 7287 steps_to_str(dm->run_reason), 7288 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 7289 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)), 7290 id_to_mode(wl->coex_mode), 7291 dm->cnt_dm[BTC_DCNT_RUN]); 7292 7293 _show_dm_step(rtwdev, m); 7294 7295 if (ver->fcxctrl == 7) 7296 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 7297 else 7298 igno_bt = btc->ctrl.ctrl.igno_bt; 7299 7300 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 7301 "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt, 7302 dm->freerun, btc->lps, dm->wl_mimo_ps); 7303 7304 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap, 7305 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 7306 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 7307 "" : "(Mismatch!!)")); 7308 7309 if (dm->rf_trx_para.wl_tx_power == 0xff) 7310 seq_printf(m, 7311 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ", 7312 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level); 7313 7314 else 7315 seq_printf(m, 7316 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ", 7317 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level, 7318 dm->rf_trx_para.wl_tx_power); 7319 7320 seq_printf(m, 7321 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n", 7322 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power, 7323 dm->rf_trx_para.bt_rx_gain, 7324 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx); 7325 7326 seq_printf(m, 7327 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 7328 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time, 7329 dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri); 7330 } 7331 7332 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m) 7333 { 7334 struct rtw89_btc *btc = &rtwdev->btc; 7335 const struct rtw89_btc_ver *ver = btc->ver; 7336 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7337 union rtw89_btc_fbtc_cysta_info *pcysta; 7338 u32 except_cnt, exception_map; 7339 7340 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 7341 if (ver->fcxcysta == 2) { 7342 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 7343 except_cnt = le32_to_cpu(pcysta->v2.except_cnt); 7344 exception_map = le32_to_cpu(pcysta->v2.exception); 7345 } else if (ver->fcxcysta == 3) { 7346 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 7347 except_cnt = le32_to_cpu(pcysta->v3.except_cnt); 7348 exception_map = le32_to_cpu(pcysta->v3.except_map); 7349 } else if (ver->fcxcysta == 4) { 7350 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 7351 except_cnt = pcysta->v4.except_cnt; 7352 exception_map = le32_to_cpu(pcysta->v4.except_map); 7353 } else if (ver->fcxcysta == 5) { 7354 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 7355 except_cnt = pcysta->v5.except_cnt; 7356 exception_map = le32_to_cpu(pcysta->v5.except_map); 7357 } else { 7358 return; 7359 } 7360 7361 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 7362 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 7363 return; 7364 7365 seq_printf(m, " %-15s : ", "[error]"); 7366 7367 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 7368 seq_printf(m, 7369 "overflow-cnt: %d, ", 7370 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 7371 } 7372 7373 if (pfwinfo->len_mismch) { 7374 seq_printf(m, 7375 "len-mismatch: 0x%x, ", 7376 pfwinfo->len_mismch); 7377 } 7378 7379 if (pfwinfo->fver_mismch) { 7380 seq_printf(m, 7381 "fver-mismatch: 0x%x, ", 7382 pfwinfo->fver_mismch); 7383 } 7384 7385 /* cycle statistics exceptions */ 7386 if (exception_map || except_cnt) { 7387 seq_printf(m, 7388 "exception-type: 0x%x, exception-cnt = %d", 7389 exception_map, except_cnt); 7390 } 7391 seq_puts(m, "\n"); 7392 } 7393 7394 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m) 7395 { 7396 struct rtw89_btc *btc = &rtwdev->btc; 7397 const struct rtw89_btc_ver *ver = btc->ver; 7398 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7399 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 7400 struct rtw89_btc_fbtc_tdma *t = NULL; 7401 7402 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 7403 if (!pcinfo->valid) 7404 return; 7405 7406 if (ver->fcxtdma == 1) 7407 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 7408 else 7409 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma; 7410 7411 seq_printf(m, 7412 " %-15s : ", "[tdma_policy]"); 7413 seq_printf(m, 7414 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ", 7415 (u32)t->type, 7416 t->rxflctrl, t->txpause); 7417 7418 seq_printf(m, 7419 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ", 7420 t->wtgle_n, t->leak_n, t->ext_ctrl); 7421 7422 seq_printf(m, 7423 "policy_type:%d", 7424 (u32)btc->policy_type); 7425 7426 seq_puts(m, "\n"); 7427 } 7428 7429 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m) 7430 { 7431 struct rtw89_btc *btc = &rtwdev->btc; 7432 struct rtw89_btc_dm *dm = &btc->dm; 7433 struct rtw89_btc_fbtc_slot *s; 7434 u8 i = 0; 7435 7436 for (i = 0; i < CXST_MAX; i++) { 7437 s = &dm->slot_now[i]; 7438 if (i % 5 == 0) 7439 seq_printf(m, 7440 " %-15s : %5s[%03d/0x%x/%d]", 7441 "[slot_list]", 7442 id_to_slot((u32)i), 7443 s->dur, s->cxtbl, s->cxtype); 7444 else 7445 seq_printf(m, 7446 ", %5s[%03d/0x%x/%d]", 7447 id_to_slot((u32)i), 7448 s->dur, s->cxtbl, s->cxtype); 7449 if (i % 5 == 4) 7450 seq_puts(m, "\n"); 7451 } 7452 seq_puts(m, "\n"); 7453 } 7454 7455 static void _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, struct seq_file *m) 7456 { 7457 struct rtw89_btc *btc = &rtwdev->btc; 7458 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7459 struct rtw89_btc_dm *dm = &btc->dm; 7460 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7461 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 7462 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL; 7463 union rtw89_btc_fbtc_rxflct r; 7464 u8 i, cnt = 0, slot_pair; 7465 u16 cycle, c_begin, c_end, store_index; 7466 7467 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7468 if (!pcinfo->valid) 7469 return; 7470 7471 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 7472 seq_printf(m, 7473 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7474 "[cycle_cnt]", 7475 le16_to_cpu(pcysta_le32->cycles), 7476 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]), 7477 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]), 7478 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]), 7479 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK])); 7480 7481 for (i = 0; i < CXST_MAX; i++) { 7482 if (!le32_to_cpu(pcysta_le32->slot_cnt[i])) 7483 continue; 7484 seq_printf(m, ", %s:%d", id_to_slot((u32)i), 7485 le32_to_cpu(pcysta_le32->slot_cnt[i])); 7486 } 7487 7488 if (dm->tdma_now.rxflctrl) { 7489 seq_printf(m, ", leak_rx:%d", 7490 le32_to_cpu(pcysta_le32->leakrx_cnt)); 7491 } 7492 7493 if (le32_to_cpu(pcysta_le32->collision_cnt)) { 7494 seq_printf(m, ", collision:%d", 7495 le32_to_cpu(pcysta_le32->collision_cnt)); 7496 } 7497 7498 if (le32_to_cpu(pcysta_le32->skip_cnt)) { 7499 seq_printf(m, ", skip:%d", 7500 le32_to_cpu(pcysta_le32->skip_cnt)); 7501 } 7502 seq_puts(m, "\n"); 7503 7504 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7505 "[cycle_time]", 7506 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]), 7507 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]), 7508 le16_to_cpu(pcysta_le32->tavg_lk) / 1000, 7509 le16_to_cpu(pcysta_le32->tavg_lk) % 1000); 7510 seq_printf(m, ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 7511 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]), 7512 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]), 7513 le16_to_cpu(pcysta_le32->tmax_lk) / 1000, 7514 le16_to_cpu(pcysta_le32->tmax_lk) % 1000); 7515 seq_printf(m, ", maxdiff_t[wl:%d/bt:%d]\n", 7516 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]), 7517 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT])); 7518 7519 if (le16_to_cpu(pcysta_le32->cycles) <= 1) 7520 return; 7521 7522 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7523 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7524 7525 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair) 7526 c_begin = 1; 7527 else 7528 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1; 7529 7530 c_end = le16_to_cpu(pcysta_le32->cycles); 7531 7532 for (cycle = c_begin; cycle <= c_end; cycle++) { 7533 cnt++; 7534 store_index = ((cycle - 1) % slot_pair) * 2; 7535 7536 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 7537 seq_printf(m, 7538 " %-15s : ->b%02d->w%02d", "[cycle_step]", 7539 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 7540 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 7541 else 7542 seq_printf(m, 7543 "->b%02d->w%02d", 7544 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 7545 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 7546 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 7547 seq_puts(m, "\n"); 7548 } 7549 7550 if (a2dp->exist) { 7551 seq_printf(m, 7552 " %-15s : a2dp_ept:%d, a2dp_late:%d", 7553 "[a2dp_t_sta]", 7554 le16_to_cpu(pcysta_le32->a2dpept), 7555 le16_to_cpu(pcysta_le32->a2dpeptto)); 7556 7557 seq_printf(m, 7558 ", avg_t:%d, max_t:%d", 7559 le16_to_cpu(pcysta_le32->tavg_a2dpept), 7560 le16_to_cpu(pcysta_le32->tmax_a2dpept)); 7561 r.val = dm->tdma_now.rxflctrl; 7562 7563 if (r.type && r.tgln_n) { 7564 seq_printf(m, 7565 ", cycle[PSTDMA:%d/TDMA:%d], ", 7566 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]), 7567 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF])); 7568 7569 seq_printf(m, 7570 "avg_t[PSTDMA:%d/TDMA:%d], ", 7571 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]), 7572 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF])); 7573 7574 seq_printf(m, 7575 "max_t[PSTDMA:%d/TDMA:%d]", 7576 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]), 7577 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF])); 7578 } 7579 seq_puts(m, "\n"); 7580 } 7581 } 7582 7583 static void _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, struct seq_file *m) 7584 { 7585 struct rtw89_btc *btc = &rtwdev->btc; 7586 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7587 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7588 struct rtw89_btc_dm *dm = &btc->dm; 7589 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 7590 struct rtw89_btc_fbtc_cysta_v3 *pcysta; 7591 struct rtw89_btc_rpt_cmn_info *pcinfo; 7592 u8 i, cnt = 0, slot_pair, divide_cnt; 7593 u16 cycle, c_begin, c_end, store_index; 7594 7595 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7596 if (!pcinfo->valid) 7597 return; 7598 7599 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 7600 seq_printf(m, 7601 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7602 "[cycle_cnt]", 7603 le16_to_cpu(pcysta->cycles), 7604 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 7605 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 7606 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 7607 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 7608 7609 for (i = 0; i < CXST_MAX; i++) { 7610 if (!le32_to_cpu(pcysta->slot_cnt[i])) 7611 continue; 7612 7613 seq_printf(m, ", %s:%d", id_to_slot(i), 7614 le32_to_cpu(pcysta->slot_cnt[i])); 7615 } 7616 7617 if (dm->tdma_now.rxflctrl) 7618 seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 7619 7620 if (le32_to_cpu(pcysta->collision_cnt)) 7621 seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt)); 7622 7623 if (le32_to_cpu(pcysta->skip_cnt)) 7624 seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt)); 7625 7626 seq_puts(m, "\n"); 7627 7628 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7629 "[cycle_time]", 7630 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 7631 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 7632 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 7633 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 7634 seq_printf(m, 7635 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 7636 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 7637 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 7638 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 7639 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 7640 seq_printf(m, 7641 ", maxdiff_t[wl:%d/bt:%d]\n", 7642 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 7643 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 7644 7645 cycle = le16_to_cpu(pcysta->cycles); 7646 if (cycle <= 1) 7647 return; 7648 7649 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7650 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7651 7652 if (cycle <= slot_pair) 7653 c_begin = 1; 7654 else 7655 c_begin = cycle - slot_pair + 1; 7656 7657 c_end = cycle; 7658 7659 if (a2dp->exist) 7660 divide_cnt = 3; 7661 else 7662 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 7663 7664 for (cycle = c_begin; cycle <= c_end; cycle++) { 7665 cnt++; 7666 store_index = ((cycle - 1) % slot_pair) * 2; 7667 7668 if (cnt % divide_cnt == 1) 7669 seq_printf(m, " %-15s : ", "[cycle_step]"); 7670 7671 seq_printf(m, "->b%02d", 7672 le16_to_cpu(pcysta->slot_step_time[store_index])); 7673 if (a2dp->exist) { 7674 a2dp_trx = &pcysta->a2dp_trx[store_index]; 7675 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7676 a2dp_trx->empty_cnt, 7677 a2dp_trx->retry_cnt, 7678 a2dp_trx->tx_rate ? 3 : 2, 7679 a2dp_trx->tx_cnt, 7680 a2dp_trx->ack_cnt, 7681 a2dp_trx->nack_cnt); 7682 } 7683 seq_printf(m, "->w%02d", 7684 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 7685 if (a2dp->exist) { 7686 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 7687 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7688 a2dp_trx->empty_cnt, 7689 a2dp_trx->retry_cnt, 7690 a2dp_trx->tx_rate ? 3 : 2, 7691 a2dp_trx->tx_cnt, 7692 a2dp_trx->ack_cnt, 7693 a2dp_trx->nack_cnt); 7694 } 7695 if (cnt % divide_cnt == 0 || cnt == c_end) 7696 seq_puts(m, "\n"); 7697 } 7698 7699 if (a2dp->exist) { 7700 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d", 7701 "[a2dp_t_sta]", 7702 le16_to_cpu(pcysta->a2dp_ept.cnt), 7703 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 7704 7705 seq_printf(m, ", avg_t:%d, max_t:%d", 7706 le16_to_cpu(pcysta->a2dp_ept.tavg), 7707 le16_to_cpu(pcysta->a2dp_ept.tmax)); 7708 7709 seq_puts(m, "\n"); 7710 } 7711 } 7712 7713 static void _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, struct seq_file *m) 7714 { 7715 struct rtw89_btc *btc = &rtwdev->btc; 7716 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7717 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7718 struct rtw89_btc_dm *dm = &btc->dm; 7719 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 7720 struct rtw89_btc_fbtc_cysta_v4 *pcysta; 7721 struct rtw89_btc_rpt_cmn_info *pcinfo; 7722 u8 i, cnt = 0, slot_pair, divide_cnt; 7723 u16 cycle, c_begin, c_end, store_index; 7724 7725 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7726 if (!pcinfo->valid) 7727 return; 7728 7729 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 7730 seq_printf(m, 7731 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7732 "[cycle_cnt]", 7733 le16_to_cpu(pcysta->cycles), 7734 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 7735 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 7736 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 7737 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 7738 7739 for (i = 0; i < CXST_MAX; i++) { 7740 if (!le16_to_cpu(pcysta->slot_cnt[i])) 7741 continue; 7742 7743 seq_printf(m, ", %s:%d", id_to_slot(i), 7744 le16_to_cpu(pcysta->slot_cnt[i])); 7745 } 7746 7747 if (dm->tdma_now.rxflctrl) 7748 seq_printf(m, ", leak_rx:%d", 7749 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 7750 7751 if (pcysta->collision_cnt) 7752 seq_printf(m, ", collision:%d", pcysta->collision_cnt); 7753 7754 if (le16_to_cpu(pcysta->skip_cnt)) 7755 seq_printf(m, ", skip:%d", 7756 le16_to_cpu(pcysta->skip_cnt)); 7757 7758 seq_puts(m, "\n"); 7759 7760 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7761 "[cycle_time]", 7762 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 7763 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 7764 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 7765 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 7766 seq_printf(m, 7767 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 7768 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 7769 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 7770 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 7771 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 7772 seq_printf(m, 7773 ", maxdiff_t[wl:%d/bt:%d]\n", 7774 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 7775 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 7776 7777 cycle = le16_to_cpu(pcysta->cycles); 7778 if (cycle <= 1) 7779 return; 7780 7781 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7782 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7783 7784 if (cycle <= slot_pair) 7785 c_begin = 1; 7786 else 7787 c_begin = cycle - slot_pair + 1; 7788 7789 c_end = cycle; 7790 7791 if (a2dp->exist) 7792 divide_cnt = 3; 7793 else 7794 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 7795 7796 for (cycle = c_begin; cycle <= c_end; cycle++) { 7797 cnt++; 7798 store_index = ((cycle - 1) % slot_pair) * 2; 7799 7800 if (cnt % divide_cnt == 1) 7801 seq_printf(m, " %-15s : ", "[cycle_step]"); 7802 7803 seq_printf(m, "->b%02d", 7804 le16_to_cpu(pcysta->slot_step_time[store_index])); 7805 if (a2dp->exist) { 7806 a2dp_trx = &pcysta->a2dp_trx[store_index]; 7807 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7808 a2dp_trx->empty_cnt, 7809 a2dp_trx->retry_cnt, 7810 a2dp_trx->tx_rate ? 3 : 2, 7811 a2dp_trx->tx_cnt, 7812 a2dp_trx->ack_cnt, 7813 a2dp_trx->nack_cnt); 7814 } 7815 seq_printf(m, "->w%02d", 7816 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 7817 if (a2dp->exist) { 7818 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 7819 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7820 a2dp_trx->empty_cnt, 7821 a2dp_trx->retry_cnt, 7822 a2dp_trx->tx_rate ? 3 : 2, 7823 a2dp_trx->tx_cnt, 7824 a2dp_trx->ack_cnt, 7825 a2dp_trx->nack_cnt); 7826 } 7827 if (cnt % divide_cnt == 0 || cnt == c_end) 7828 seq_puts(m, "\n"); 7829 } 7830 7831 if (a2dp->exist) { 7832 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d", 7833 "[a2dp_t_sta]", 7834 le16_to_cpu(pcysta->a2dp_ept.cnt), 7835 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 7836 7837 seq_printf(m, ", avg_t:%d, max_t:%d", 7838 le16_to_cpu(pcysta->a2dp_ept.tavg), 7839 le16_to_cpu(pcysta->a2dp_ept.tmax)); 7840 7841 seq_puts(m, "\n"); 7842 } 7843 } 7844 7845 static void _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, struct seq_file *m) 7846 { 7847 struct rtw89_btc *btc = &rtwdev->btc; 7848 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7849 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7850 struct rtw89_btc_dm *dm = &btc->dm; 7851 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 7852 struct rtw89_btc_fbtc_cysta_v5 *pcysta; 7853 struct rtw89_btc_rpt_cmn_info *pcinfo; 7854 u8 i, cnt = 0, slot_pair, divide_cnt; 7855 u16 cycle, c_begin, c_end, store_index; 7856 7857 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7858 if (!pcinfo->valid) 7859 return; 7860 7861 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 7862 seq_printf(m, 7863 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7864 "[cycle_cnt]", 7865 le16_to_cpu(pcysta->cycles), 7866 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 7867 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 7868 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 7869 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 7870 7871 for (i = 0; i < CXST_MAX; i++) { 7872 if (!le16_to_cpu(pcysta->slot_cnt[i])) 7873 continue; 7874 7875 seq_printf(m, ", %s:%d", id_to_slot(i), 7876 le16_to_cpu(pcysta->slot_cnt[i])); 7877 } 7878 7879 if (dm->tdma_now.rxflctrl) 7880 seq_printf(m, ", leak_rx:%d", 7881 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 7882 7883 if (pcysta->collision_cnt) 7884 seq_printf(m, ", collision:%d", pcysta->collision_cnt); 7885 7886 if (le16_to_cpu(pcysta->skip_cnt)) 7887 seq_printf(m, ", skip:%d", 7888 le16_to_cpu(pcysta->skip_cnt)); 7889 7890 seq_puts(m, "\n"); 7891 7892 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7893 "[cycle_time]", 7894 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 7895 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 7896 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 7897 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 7898 seq_printf(m, 7899 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 7900 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 7901 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 7902 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 7903 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 7904 7905 cycle = le16_to_cpu(pcysta->cycles); 7906 if (cycle <= 1) 7907 return; 7908 7909 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7910 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7911 7912 if (cycle <= slot_pair) 7913 c_begin = 1; 7914 else 7915 c_begin = cycle - slot_pair + 1; 7916 7917 c_end = cycle; 7918 7919 if (a2dp->exist) 7920 divide_cnt = 3; 7921 else 7922 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 7923 7924 if (c_begin > c_end) 7925 return; 7926 7927 for (cycle = c_begin; cycle <= c_end; cycle++) { 7928 cnt++; 7929 store_index = ((cycle - 1) % slot_pair) * 2; 7930 7931 if (cnt % divide_cnt == 1) 7932 seq_printf(m, " %-15s : ", "[cycle_step]"); 7933 7934 seq_printf(m, "->b%02d", 7935 le16_to_cpu(pcysta->slot_step_time[store_index])); 7936 if (a2dp->exist) { 7937 a2dp_trx = &pcysta->a2dp_trx[store_index]; 7938 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7939 a2dp_trx->empty_cnt, 7940 a2dp_trx->retry_cnt, 7941 a2dp_trx->tx_rate ? 3 : 2, 7942 a2dp_trx->tx_cnt, 7943 a2dp_trx->ack_cnt, 7944 a2dp_trx->nack_cnt); 7945 } 7946 seq_printf(m, "->w%02d", 7947 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 7948 if (a2dp->exist) { 7949 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 7950 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7951 a2dp_trx->empty_cnt, 7952 a2dp_trx->retry_cnt, 7953 a2dp_trx->tx_rate ? 3 : 2, 7954 a2dp_trx->tx_cnt, 7955 a2dp_trx->ack_cnt, 7956 a2dp_trx->nack_cnt); 7957 } 7958 if (cnt % divide_cnt == 0 || cnt == c_end) 7959 seq_puts(m, "\n"); 7960 } 7961 7962 if (a2dp->exist) { 7963 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d", 7964 "[a2dp_t_sta]", 7965 le16_to_cpu(pcysta->a2dp_ept.cnt), 7966 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 7967 7968 seq_printf(m, ", avg_t:%d, max_t:%d", 7969 le16_to_cpu(pcysta->a2dp_ept.tavg), 7970 le16_to_cpu(pcysta->a2dp_ept.tmax)); 7971 7972 seq_puts(m, "\n"); 7973 } 7974 } 7975 7976 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m) 7977 { 7978 struct rtw89_btc *btc = &rtwdev->btc; 7979 const struct rtw89_btc_ver *ver = btc->ver; 7980 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7981 struct rtw89_btc_rpt_cmn_info *pcinfo; 7982 union rtw89_btc_fbtc_cynullsta_info *ns; 7983 u8 i = 0; 7984 7985 if (!btc->dm.tdma_now.rxflctrl) 7986 return; 7987 7988 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 7989 if (!pcinfo->valid) 7990 return; 7991 7992 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 7993 if (ver->fcxnullsta == 1) { 7994 for (i = 0; i < 2; i++) { 7995 seq_printf(m, " %-15s : ", "[NULL-STA]"); 7996 seq_printf(m, "null-%d", i); 7997 seq_printf(m, "[ok:%d/", 7998 le32_to_cpu(ns->v1.result[i][1])); 7999 seq_printf(m, "fail:%d/", 8000 le32_to_cpu(ns->v1.result[i][0])); 8001 seq_printf(m, "on_time:%d/", 8002 le32_to_cpu(ns->v1.result[i][2])); 8003 seq_printf(m, "retry:%d/", 8004 le32_to_cpu(ns->v1.result[i][3])); 8005 seq_printf(m, "avg_t:%d.%03d/", 8006 le32_to_cpu(ns->v1.avg_t[i]) / 1000, 8007 le32_to_cpu(ns->v1.avg_t[i]) % 1000); 8008 seq_printf(m, "max_t:%d.%03d]\n", 8009 le32_to_cpu(ns->v1.max_t[i]) / 1000, 8010 le32_to_cpu(ns->v1.max_t[i]) % 1000); 8011 } 8012 } else { 8013 for (i = 0; i < 2; i++) { 8014 seq_printf(m, " %-15s : ", "[NULL-STA]"); 8015 seq_printf(m, "null-%d", i); 8016 seq_printf(m, "[Tx:%d/", 8017 le32_to_cpu(ns->v2.result[i][4])); 8018 seq_printf(m, "[ok:%d/", 8019 le32_to_cpu(ns->v2.result[i][1])); 8020 seq_printf(m, "fail:%d/", 8021 le32_to_cpu(ns->v2.result[i][0])); 8022 seq_printf(m, "on_time:%d/", 8023 le32_to_cpu(ns->v2.result[i][2])); 8024 seq_printf(m, "retry:%d/", 8025 le32_to_cpu(ns->v2.result[i][3])); 8026 seq_printf(m, "avg_t:%d.%03d/", 8027 le32_to_cpu(ns->v2.avg_t[i]) / 1000, 8028 le32_to_cpu(ns->v2.avg_t[i]) % 1000); 8029 seq_printf(m, "max_t:%d.%03d]\n", 8030 le32_to_cpu(ns->v2.max_t[i]) / 1000, 8031 le32_to_cpu(ns->v2.max_t[i]) % 1000); 8032 } 8033 } 8034 } 8035 8036 static void _show_fbtc_step_v2(struct rtw89_dev *rtwdev, struct seq_file *m) 8037 { 8038 struct rtw89_btc *btc = &rtwdev->btc; 8039 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8040 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 8041 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL; 8042 const struct rtw89_btc_ver *ver = btc->ver; 8043 u8 type, val, cnt = 0, state = 0; 8044 bool outloop = false; 8045 u16 i, diff_t, n_start = 0, n_stop = 0; 8046 u16 pos_old, pos_new, trace_step; 8047 8048 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 8049 if (!pcinfo->valid) 8050 return; 8051 8052 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2; 8053 pos_old = le16_to_cpu(pstep->pos_old); 8054 pos_new = le16_to_cpu(pstep->pos_new); 8055 8056 if (pcinfo->req_fver != pstep->fver) 8057 return; 8058 8059 /* store step info by using ring instead of FIFO*/ 8060 do { 8061 switch (state) { 8062 case 0: 8063 if (ver->fcxctrl == 7 || ver->fcxctrl == 1) 8064 trace_step = 50; 8065 else 8066 trace_step = btc->ctrl.ctrl.trace_step; 8067 8068 n_start = pos_old; 8069 if (pos_new >= pos_old) 8070 n_stop = pos_new; 8071 else 8072 n_stop = trace_step - 1; 8073 8074 state = 1; 8075 break; 8076 case 1: 8077 for (i = n_start; i <= n_stop; i++) { 8078 type = pstep->step[i].type; 8079 val = pstep->step[i].val; 8080 diff_t = le16_to_cpu(pstep->step[i].difft); 8081 8082 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 8083 continue; 8084 8085 if (cnt % 10 == 0) 8086 seq_printf(m, " %-15s : ", "[steps]"); 8087 8088 seq_printf(m, "-> %s(%02d)(%02d)", 8089 (type == CXSTEP_SLOT ? "SLT" : 8090 "EVT"), (u32)val, diff_t); 8091 if (cnt % 10 == 9) 8092 seq_puts(m, "\n"); 8093 cnt++; 8094 } 8095 8096 state = 2; 8097 break; 8098 case 2: 8099 if (pos_new < pos_old && n_start != 0) { 8100 n_start = 0; 8101 n_stop = pos_new; 8102 state = 1; 8103 } else { 8104 outloop = true; 8105 } 8106 break; 8107 } 8108 } while (!outloop); 8109 } 8110 8111 static void _show_fbtc_step_v3(struct rtw89_dev *rtwdev, struct seq_file *m) 8112 { 8113 struct rtw89_btc *btc = &rtwdev->btc; 8114 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8115 struct rtw89_btc_rpt_cmn_info *pcinfo; 8116 struct rtw89_btc_fbtc_steps_v3 *pstep; 8117 u32 i, n_begin, n_end, array_idx, cnt = 0; 8118 u8 type, val; 8119 u16 diff_t; 8120 8121 if ((pfwinfo->rpt_en_map & 8122 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0) 8123 return; 8124 8125 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 8126 if (!pcinfo->valid) 8127 return; 8128 8129 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3; 8130 if (pcinfo->req_fver != pstep->fver) 8131 return; 8132 8133 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP) 8134 n_begin = 1; 8135 else 8136 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1; 8137 8138 n_end = le32_to_cpu(pstep->cnt); 8139 8140 if (n_begin > n_end) 8141 return; 8142 8143 /* restore step info by using ring instead of FIFO */ 8144 for (i = n_begin; i <= n_end; i++) { 8145 array_idx = (i - 1) % FCXDEF_STEP; 8146 type = pstep->step[array_idx].type; 8147 val = pstep->step[array_idx].val; 8148 diff_t = le16_to_cpu(pstep->step[array_idx].difft); 8149 8150 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 8151 continue; 8152 8153 if (cnt % 10 == 0) 8154 seq_printf(m, " %-15s : ", "[steps]"); 8155 8156 seq_printf(m, "-> %s(%02d)", 8157 (type == CXSTEP_SLOT ? 8158 id_to_slot((u32)val) : 8159 id_to_evt((u32)val)), diff_t); 8160 8161 if (cnt % 10 == 9) 8162 seq_puts(m, "\n"); 8163 8164 cnt++; 8165 } 8166 } 8167 8168 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m) 8169 { 8170 struct rtw89_btc *btc = &rtwdev->btc; 8171 const struct rtw89_btc_ver *ver = btc->ver; 8172 8173 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 8174 return; 8175 8176 _show_error(rtwdev, m); 8177 _show_fbtc_tdma(rtwdev, m); 8178 _show_fbtc_slots(rtwdev, m); 8179 8180 if (ver->fcxcysta == 2) 8181 _show_fbtc_cysta_v2(rtwdev, m); 8182 else if (ver->fcxcysta == 3) 8183 _show_fbtc_cysta_v3(rtwdev, m); 8184 else if (ver->fcxcysta == 4) 8185 _show_fbtc_cysta_v4(rtwdev, m); 8186 else if (ver->fcxcysta == 5) 8187 _show_fbtc_cysta_v5(rtwdev, m); 8188 8189 _show_fbtc_nullsta(rtwdev, m); 8190 8191 if (ver->fcxstep == 2) 8192 _show_fbtc_step_v2(rtwdev, m); 8193 else if (ver->fcxstep == 3) 8194 _show_fbtc_step_v3(rtwdev, m); 8195 8196 } 8197 8198 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 8199 { 8200 const struct rtw89_chip_info *chip = rtwdev->chip; 8201 struct rtw89_mac_ax_gnt *gnt; 8202 u32 val, status; 8203 8204 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || 8205 chip->chip_id == RTL8851B) { 8206 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 8207 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 8208 8209 gnt = &gnt_cfg->band[0]; 8210 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 8211 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 8212 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 8213 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 8214 8215 gnt = &gnt_cfg->band[1]; 8216 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 8217 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 8218 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 8219 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 8220 } else if (chip->chip_id == RTL8852C) { 8221 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 8222 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 8223 8224 gnt = &gnt_cfg->band[0]; 8225 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 8226 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 8227 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 8228 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 8229 8230 gnt = &gnt_cfg->band[1]; 8231 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 8232 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 8233 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 8234 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 8235 } else { 8236 return; 8237 } 8238 } 8239 8240 static void _show_mreg_v1(struct rtw89_dev *rtwdev, struct seq_file *m) 8241 { 8242 const struct rtw89_chip_info *chip = rtwdev->chip; 8243 struct rtw89_btc *btc = &rtwdev->btc; 8244 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8245 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 8246 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL; 8247 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 8248 struct rtw89_btc_cx *cx = &btc->cx; 8249 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8250 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 8251 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 8252 struct rtw89_mac_ax_gnt gnt; 8253 u8 i = 0, type = 0, cnt = 0; 8254 u32 val, offset; 8255 8256 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 8257 return; 8258 8259 seq_puts(m, "========== [HW Status] ==========\n"); 8260 8261 seq_printf(m, 8262 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 8263 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 8264 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 8265 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 8266 8267 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 8268 _get_gnt(rtwdev, &gnt_cfg); 8269 8270 gnt = gnt_cfg.band[0]; 8271 seq_printf(m, 8272 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 8273 "[gnt_status]", 8274 chip->chip_id == RTL8852C ? "HW" : 8275 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 8276 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 8277 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 8278 8279 gnt = gnt_cfg.band[1]; 8280 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 8281 gnt.gnt_wl_sw_en ? "SW" : "HW", 8282 gnt.gnt_wl, 8283 gnt.gnt_bt_sw_en ? "SW" : "HW", 8284 gnt.gnt_bt); 8285 8286 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 8287 if (!pcinfo->valid) { 8288 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8289 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 8290 __func__); 8291 return; 8292 } 8293 8294 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 8295 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8296 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 8297 __func__, pmreg->reg_num); 8298 8299 for (i = 0; i < pmreg->reg_num; i++) { 8300 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 8301 offset = le32_to_cpu(chip->mon_reg[i].offset); 8302 val = le32_to_cpu(pmreg->mreg_val[i]); 8303 8304 if (cnt % 6 == 0) 8305 seq_printf(m, " %-15s : %d_0x%04x=0x%08x", 8306 "[reg]", (u32)type, offset, val); 8307 else 8308 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type, 8309 offset, val); 8310 if (cnt % 6 == 5) 8311 seq_puts(m, "\n"); 8312 cnt++; 8313 8314 if (i >= pmreg->reg_num) 8315 seq_puts(m, "\n"); 8316 } 8317 8318 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 8319 if (!pcinfo->valid) { 8320 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8321 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 8322 __func__); 8323 seq_puts(m, "\n"); 8324 return; 8325 } 8326 8327 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 8328 if (!gdbg->en_map) 8329 return; 8330 8331 seq_printf(m, " %-15s : enable_map:0x%08x", 8332 "[gpio_dbg]", gdbg->en_map); 8333 8334 for (i = 0; i < BTC_DBG_MAX1; i++) { 8335 if (!(gdbg->en_map & BIT(i))) 8336 continue; 8337 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]); 8338 } 8339 seq_puts(m, "\n"); 8340 } 8341 8342 static void _show_mreg_v2(struct rtw89_dev *rtwdev, struct seq_file *m) 8343 { 8344 const struct rtw89_chip_info *chip = rtwdev->chip; 8345 struct rtw89_btc *btc = &rtwdev->btc; 8346 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8347 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 8348 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL; 8349 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 8350 struct rtw89_btc_cx *cx = &btc->cx; 8351 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8352 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 8353 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 8354 struct rtw89_mac_ax_gnt gnt; 8355 u8 i = 0, type = 0, cnt = 0; 8356 u32 val, offset; 8357 8358 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 8359 return; 8360 8361 seq_puts(m, "========== [HW Status] ==========\n"); 8362 8363 seq_printf(m, 8364 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 8365 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 8366 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 8367 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 8368 8369 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 8370 _get_gnt(rtwdev, &gnt_cfg); 8371 8372 gnt = gnt_cfg.band[0]; 8373 seq_printf(m, 8374 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 8375 "[gnt_status]", 8376 chip->chip_id == RTL8852C ? "HW" : 8377 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 8378 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 8379 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 8380 8381 gnt = gnt_cfg.band[1]; 8382 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 8383 gnt.gnt_wl_sw_en ? "SW" : "HW", 8384 gnt.gnt_wl, 8385 gnt.gnt_bt_sw_en ? "SW" : "HW", 8386 gnt.gnt_bt); 8387 8388 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 8389 if (!pcinfo->valid) { 8390 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8391 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 8392 __func__); 8393 return; 8394 } 8395 8396 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 8397 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8398 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 8399 __func__, pmreg->reg_num); 8400 8401 for (i = 0; i < pmreg->reg_num; i++) { 8402 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 8403 offset = le32_to_cpu(chip->mon_reg[i].offset); 8404 val = le32_to_cpu(pmreg->mreg_val[i]); 8405 8406 if (cnt % 6 == 0) 8407 seq_printf(m, " %-15s : %d_0x%04x=0x%08x", 8408 "[reg]", (u32)type, offset, val); 8409 else 8410 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type, 8411 offset, val); 8412 if (cnt % 6 == 5) 8413 seq_puts(m, "\n"); 8414 cnt++; 8415 8416 if (i >= pmreg->reg_num) 8417 seq_puts(m, "\n"); 8418 } 8419 8420 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 8421 if (!pcinfo->valid) { 8422 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8423 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 8424 __func__); 8425 seq_puts(m, "\n"); 8426 return; 8427 } 8428 8429 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 8430 if (!gdbg->en_map) 8431 return; 8432 8433 seq_printf(m, " %-15s : enable_map:0x%08x", 8434 "[gpio_dbg]", gdbg->en_map); 8435 8436 for (i = 0; i < BTC_DBG_MAX1; i++) { 8437 if (!(gdbg->en_map & BIT(i))) 8438 continue; 8439 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]); 8440 } 8441 seq_puts(m, "\n"); 8442 } 8443 8444 static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m) 8445 { 8446 struct rtw89_btc *btc = &rtwdev->btc; 8447 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8448 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 8449 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL; 8450 struct rtw89_btc_cx *cx = &btc->cx; 8451 struct rtw89_btc_dm *dm = &btc->dm; 8452 struct rtw89_btc_wl_info *wl = &cx->wl; 8453 struct rtw89_btc_bt_info *bt = &cx->bt; 8454 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8455 u8 i; 8456 8457 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8458 return; 8459 8460 seq_puts(m, "========== [Statistics] ==========\n"); 8461 8462 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8463 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8464 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1; 8465 8466 seq_printf(m, 8467 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 8468 "[summary]", pfwinfo->cnt_h2c, 8469 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 8470 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 8471 8472 seq_printf(m, 8473 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 8474 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt, 8475 prptctrl->rpt_enable, dm->error.val); 8476 8477 if (dm->error.map.wl_fw_hang) 8478 seq_puts(m, " (WL FW Hang!!)"); 8479 seq_puts(m, "\n"); 8480 seq_printf(m, 8481 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 8482 "[mailbox]", prptctrl->mb_send_ok_cnt, 8483 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt); 8484 8485 seq_printf(m, 8486 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 8487 prptctrl->mb_a2dp_empty_cnt, 8488 prptctrl->mb_a2dp_flct_cnt, 8489 prptctrl->mb_a2dp_full_cnt); 8490 8491 seq_printf(m, 8492 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 8493 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8494 cx->cnt_wl[BTC_WCNT_RFK_GO], 8495 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8496 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8497 8498 seq_printf(m, 8499 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 8500 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 8501 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 8502 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 8503 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 8504 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 8505 8506 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 8507 bt->rfk_info.map.timeout = 1; 8508 else 8509 bt->rfk_info.map.timeout = 0; 8510 8511 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 8512 } else { 8513 seq_printf(m, 8514 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 8515 "[summary]", pfwinfo->cnt_h2c, 8516 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 8517 pfwinfo->event[BTF_EVNT_RPT], 8518 btc->fwinfo.rpt_en_map); 8519 seq_puts(m, " (WL FW report invalid!!)\n"); 8520 } 8521 8522 for (i = 0; i < BTC_NCNT_NUM; i++) 8523 cnt_sum += dm->cnt_notify[i]; 8524 8525 seq_printf(m, 8526 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8527 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8528 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8529 8530 seq_printf(m, 8531 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 8532 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8533 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8534 cnt[BTC_NCNT_WL_STA]); 8535 8536 seq_printf(m, 8537 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8538 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 8539 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 8540 cnt[BTC_NCNT_SPECIAL_PACKET]); 8541 8542 seq_printf(m, 8543 "timer=%d, control=%d, customerize=%d\n", 8544 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8545 cnt[BTC_NCNT_CUSTOMERIZE]); 8546 } 8547 8548 static void _show_summary_v4(struct rtw89_dev *rtwdev, struct seq_file *m) 8549 { 8550 struct rtw89_btc *btc = &rtwdev->btc; 8551 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8552 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl; 8553 struct rtw89_btc_rpt_cmn_info *pcinfo; 8554 struct rtw89_btc_cx *cx = &btc->cx; 8555 struct rtw89_btc_dm *dm = &btc->dm; 8556 struct rtw89_btc_wl_info *wl = &cx->wl; 8557 struct rtw89_btc_bt_info *bt = &cx->bt; 8558 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8559 u8 i; 8560 8561 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8562 return; 8563 8564 seq_puts(m, "========== [Statistics] ==========\n"); 8565 8566 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8567 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8568 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4; 8569 8570 seq_printf(m, 8571 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 8572 "[summary]", pfwinfo->cnt_h2c, 8573 pfwinfo->cnt_h2c_fail, 8574 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 8575 pfwinfo->cnt_c2h, 8576 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 8577 8578 seq_printf(m, 8579 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 8580 pfwinfo->event[BTF_EVNT_RPT], 8581 le32_to_cpu(prptctrl->rpt_info.cnt), 8582 le32_to_cpu(prptctrl->rpt_info.en), 8583 dm->error.val); 8584 8585 if (dm->error.map.wl_fw_hang) 8586 seq_puts(m, " (WL FW Hang!!)"); 8587 seq_puts(m, "\n"); 8588 seq_printf(m, 8589 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 8590 "[mailbox]", 8591 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 8592 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 8593 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 8594 8595 seq_printf(m, 8596 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 8597 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 8598 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 8599 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 8600 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 8601 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 8602 8603 seq_printf(m, 8604 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 8605 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8606 cx->cnt_wl[BTC_WCNT_RFK_GO], 8607 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8608 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8609 8610 seq_printf(m, 8611 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 8612 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 8613 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 8614 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 8615 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 8616 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 8617 8618 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 8619 bt->rfk_info.map.timeout = 1; 8620 else 8621 bt->rfk_info.map.timeout = 0; 8622 8623 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 8624 } else { 8625 seq_printf(m, 8626 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 8627 "[summary]", pfwinfo->cnt_h2c, 8628 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 8629 pfwinfo->event[BTF_EVNT_RPT], 8630 btc->fwinfo.rpt_en_map); 8631 seq_puts(m, " (WL FW report invalid!!)\n"); 8632 } 8633 8634 for (i = 0; i < BTC_NCNT_NUM; i++) 8635 cnt_sum += dm->cnt_notify[i]; 8636 8637 seq_printf(m, 8638 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8639 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8640 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8641 8642 seq_printf(m, 8643 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 8644 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8645 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8646 cnt[BTC_NCNT_WL_STA]); 8647 8648 seq_printf(m, 8649 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8650 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 8651 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 8652 cnt[BTC_NCNT_SPECIAL_PACKET]); 8653 8654 seq_printf(m, 8655 "timer=%d, control=%d, customerize=%d\n", 8656 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8657 cnt[BTC_NCNT_CUSTOMERIZE]); 8658 } 8659 8660 static void _show_summary_v5(struct rtw89_dev *rtwdev, struct seq_file *m) 8661 { 8662 struct rtw89_btc *btc = &rtwdev->btc; 8663 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8664 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl; 8665 struct rtw89_btc_rpt_cmn_info *pcinfo; 8666 struct rtw89_btc_cx *cx = &btc->cx; 8667 struct rtw89_btc_dm *dm = &btc->dm; 8668 struct rtw89_btc_wl_info *wl = &cx->wl; 8669 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8670 u8 i; 8671 8672 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8673 return; 8674 8675 seq_puts(m, "========== [Statistics] ==========\n"); 8676 8677 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8678 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8679 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5; 8680 8681 seq_printf(m, 8682 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 8683 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 8684 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 8685 pfwinfo->cnt_c2h, 8686 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 8687 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 8688 8689 seq_printf(m, 8690 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 8691 pfwinfo->event[BTF_EVNT_RPT], 8692 le16_to_cpu(prptctrl->rpt_info.cnt), 8693 le32_to_cpu(prptctrl->rpt_info.en)); 8694 8695 if (dm->error.map.wl_fw_hang) 8696 seq_puts(m, " (WL FW Hang!!)"); 8697 seq_puts(m, "\n"); 8698 seq_printf(m, 8699 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 8700 "[mailbox]", 8701 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 8702 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 8703 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 8704 8705 seq_printf(m, 8706 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 8707 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 8708 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 8709 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 8710 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 8711 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 8712 8713 seq_printf(m, 8714 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 8715 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8716 cx->cnt_wl[BTC_WCNT_RFK_GO], 8717 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8718 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8719 8720 seq_printf(m, 8721 ", bt_rfk[req:%d]", 8722 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 8723 8724 seq_printf(m, 8725 ", AOAC[RF_on:%d/RF_off:%d]", 8726 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 8727 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 8728 } else { 8729 seq_printf(m, 8730 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 8731 "[summary]", pfwinfo->cnt_h2c, 8732 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 8733 } 8734 8735 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 8736 pfwinfo->err[BTFRE_EXCEPTION]) { 8737 seq_puts(m, "\n"); 8738 seq_printf(m, 8739 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 8740 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 8741 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 8742 pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION], 8743 wl->status.map.lps, wl->status.map.rf_off); 8744 } 8745 8746 for (i = 0; i < BTC_NCNT_NUM; i++) 8747 cnt_sum += dm->cnt_notify[i]; 8748 8749 seq_puts(m, "\n"); 8750 seq_printf(m, 8751 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8752 "[notify_cnt]", 8753 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8754 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8755 8756 seq_printf(m, 8757 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 8758 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8759 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8760 cnt[BTC_NCNT_WL_STA]); 8761 8762 seq_puts(m, "\n"); 8763 seq_printf(m, 8764 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8765 "[notify_cnt]", 8766 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 8767 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]); 8768 8769 seq_printf(m, 8770 "timer=%d, control=%d, customerize=%d", 8771 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8772 cnt[BTC_NCNT_CUSTOMERIZE]); 8773 } 8774 8775 static void _show_summary_v105(struct rtw89_dev *rtwdev, struct seq_file *m) 8776 { 8777 struct rtw89_btc *btc = &rtwdev->btc; 8778 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8779 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl; 8780 struct rtw89_btc_rpt_cmn_info *pcinfo; 8781 struct rtw89_btc_cx *cx = &btc->cx; 8782 struct rtw89_btc_dm *dm = &btc->dm; 8783 struct rtw89_btc_wl_info *wl = &cx->wl; 8784 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8785 u8 i; 8786 8787 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8788 return; 8789 8790 seq_puts(m, "========== [Statistics] ==========\n"); 8791 8792 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8793 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8794 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105; 8795 8796 seq_printf(m, 8797 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 8798 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 8799 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 8800 pfwinfo->cnt_c2h, 8801 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 8802 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 8803 8804 seq_printf(m, 8805 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 8806 pfwinfo->event[BTF_EVNT_RPT], 8807 le16_to_cpu(prptctrl->rpt_info.cnt), 8808 le32_to_cpu(prptctrl->rpt_info.en)); 8809 8810 if (dm->error.map.wl_fw_hang) 8811 seq_puts(m, " (WL FW Hang!!)"); 8812 seq_puts(m, "\n"); 8813 seq_printf(m, 8814 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 8815 "[mailbox]", 8816 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 8817 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 8818 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 8819 8820 seq_printf(m, 8821 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 8822 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 8823 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 8824 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 8825 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 8826 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 8827 8828 seq_printf(m, 8829 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 8830 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8831 cx->cnt_wl[BTC_WCNT_RFK_GO], 8832 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8833 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8834 8835 seq_printf(m, 8836 ", bt_rfk[req:%d]", 8837 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 8838 8839 seq_printf(m, 8840 ", AOAC[RF_on:%d/RF_off:%d]", 8841 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 8842 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 8843 } else { 8844 seq_printf(m, 8845 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 8846 "[summary]", pfwinfo->cnt_h2c, 8847 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 8848 } 8849 8850 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 8851 pfwinfo->err[BTFRE_EXCEPTION]) { 8852 seq_puts(m, "\n"); 8853 seq_printf(m, 8854 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 8855 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 8856 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 8857 pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION], 8858 wl->status.map.lps, wl->status.map.rf_off); 8859 } 8860 8861 for (i = 0; i < BTC_NCNT_NUM; i++) 8862 cnt_sum += dm->cnt_notify[i]; 8863 8864 seq_puts(m, "\n"); 8865 seq_printf(m, 8866 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8867 "[notify_cnt]", 8868 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8869 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8870 8871 seq_printf(m, 8872 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 8873 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8874 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8875 cnt[BTC_NCNT_WL_STA]); 8876 8877 seq_puts(m, "\n"); 8878 seq_printf(m, 8879 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8880 "[notify_cnt]", 8881 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 8882 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]); 8883 8884 seq_printf(m, 8885 "timer=%d, control=%d, customerize=%d", 8886 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8887 cnt[BTC_NCNT_CUSTOMERIZE]); 8888 } 8889 8890 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m) 8891 { 8892 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal; 8893 struct rtw89_btc *btc = &rtwdev->btc; 8894 const struct rtw89_btc_ver *ver = btc->ver; 8895 struct rtw89_btc_cx *cx = &btc->cx; 8896 struct rtw89_btc_bt_info *bt = &cx->bt; 8897 8898 seq_puts(m, "=========================================\n"); 8899 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n", 8900 fw_suit->major_ver, fw_suit->minor_ver, 8901 fw_suit->sub_ver, fw_suit->sub_idex); 8902 seq_printf(m, "manual %d\n", btc->manual_ctrl); 8903 8904 seq_puts(m, "=========================================\n"); 8905 8906 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)", 8907 "[bt_info]", 8908 bt->raw_info[2], bt->raw_info[3], 8909 bt->raw_info[4], bt->raw_info[5], 8910 bt->raw_info[6], bt->raw_info[7], 8911 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 8912 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 8913 cx->cnt_bt[BTC_BCNT_INFOSAME]); 8914 8915 seq_puts(m, "\n=========================================\n"); 8916 8917 _show_cx_info(rtwdev, m); 8918 _show_wl_info(rtwdev, m); 8919 _show_bt_info(rtwdev, m); 8920 _show_dm_info(rtwdev, m); 8921 _show_fw_dm_msg(rtwdev, m); 8922 8923 if (ver->fcxmreg == 1) 8924 _show_mreg_v1(rtwdev, m); 8925 else if (ver->fcxmreg == 2) 8926 _show_mreg_v2(rtwdev, m); 8927 8928 if (ver->fcxbtcrpt == 1) 8929 _show_summary_v1(rtwdev, m); 8930 else if (ver->fcxbtcrpt == 4) 8931 _show_summary_v4(rtwdev, m); 8932 else if (ver->fcxbtcrpt == 5) 8933 _show_summary_v5(rtwdev, m); 8934 else if (ver->fcxbtcrpt == 105) 8935 _show_summary_v105(rtwdev, m); 8936 } 8937 8938 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) 8939 { 8940 const struct rtw89_chip_info *chip = rtwdev->chip; 8941 struct rtw89_btc *btc = &rtwdev->btc; 8942 const struct rtw89_btc_ver *btc_ver_def; 8943 const struct rtw89_fw_suit *fw_suit; 8944 u32 suit_ver_code; 8945 int i; 8946 8947 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); 8948 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); 8949 8950 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) { 8951 btc_ver_def = &rtw89_btc_ver_defs[i]; 8952 8953 if (chip->chip_id != btc_ver_def->chip_id) 8954 continue; 8955 8956 if (suit_ver_code >= btc_ver_def->fw_ver_code) { 8957 btc->ver = btc_ver_def; 8958 goto out; 8959 } 8960 } 8961 8962 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX]; 8963 8964 out: 8965 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", 8966 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); 8967 } 8968