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