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