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