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 0x07000313 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(5, 0xea5a5a5a, SLOT_MIX), 93 [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO), 94 [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 95 [CXST_ENULL] = __DEF_FBTC_SLOT(5, 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_NUM; 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_NUM; 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_NUM; 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_NUM; 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_NUM; 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_NUM; 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_NUM; 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_NUM; 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_NUM; 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_dm *dm = &btc->dm; 4587 4588 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4589 4590 dm->slot_dur[CXST_W1] = 20; 4591 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 4592 4593 switch (btc->cx.state_map) { 4594 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 4595 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 4596 break; 4597 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 4598 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 4599 break; 4600 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 4601 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 4602 break; 4603 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 4604 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 4605 if (btc->cx.wl.rfk_info.con_rfk) 4606 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP); 4607 else 4608 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP); 4609 break; 4610 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 4611 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 4612 break; 4613 } 4614 } 4615 4616 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 4617 { 4618 struct rtw89_btc *btc = &rtwdev->btc; 4619 4620 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4621 4622 switch (btc->cx.state_map) { 4623 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 4624 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 4625 break; 4626 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 4627 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 4628 break; 4629 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 4630 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 4631 break; 4632 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 4633 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 4634 break; 4635 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 4636 if (btc->cx.wl.rfk_info.con_rfk) 4637 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK); 4638 else 4639 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 4640 break; 4641 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 4642 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 4643 break; 4644 } 4645 } 4646 4647 static void _action_bt_pan(struct rtw89_dev *rtwdev) 4648 { 4649 struct rtw89_btc *btc = &rtwdev->btc; 4650 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 4651 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 4652 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 4653 4654 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4655 4656 switch (btc->cx.state_map) { 4657 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 4658 if (a2dp.active || !pan.exist) { 4659 btc->dm.slot_dur[CXST_W1] = 80; 4660 btc->dm.slot_dur[CXST_B1] = 20; 4661 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); 4662 } else { 4663 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 4664 } 4665 break; 4666 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 4667 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 4668 break; 4669 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 4670 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 4671 break; 4672 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 4673 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 4674 break; 4675 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 4676 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN); 4677 break; 4678 case BTC_WIDLE: /* wl-idle + bt-pan */ 4679 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 4680 break; 4681 } 4682 } 4683 4684 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 4685 { 4686 struct rtw89_btc *btc = &rtwdev->btc; 4687 struct rtw89_btc_dm *dm = &btc->dm; 4688 4689 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4690 4691 dm->slot_dur[CXST_W1] = 20; 4692 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 4693 4694 switch (btc->cx.state_map) { 4695 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 4696 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 4697 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 4698 break; 4699 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 4700 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID); 4701 break; 4702 4703 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 4704 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 4705 break; 4706 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 4707 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 4708 if (btc->cx.wl.rfk_info.con_rfk) 4709 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID); 4710 else 4711 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 4712 break; 4713 } 4714 } 4715 4716 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 4717 { 4718 struct rtw89_btc *btc = &rtwdev->btc; 4719 4720 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4721 4722 switch (btc->cx.state_map) { 4723 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 4724 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 4725 break; 4726 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 4727 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 4728 break; 4729 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 4730 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 4731 break; 4732 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 4733 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 4734 break; 4735 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 4736 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 4737 break; 4738 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 4739 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 4740 break; 4741 } 4742 } 4743 4744 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 4745 { 4746 struct rtw89_btc *btc = &rtwdev->btc; 4747 4748 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4749 4750 switch (btc->cx.state_map) { 4751 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 4752 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 4753 break; 4754 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 4755 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 4756 break; 4757 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 4758 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 4759 break; 4760 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 4761 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 4762 break; 4763 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 4764 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 4765 break; 4766 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 4767 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 4768 break; 4769 } 4770 } 4771 4772 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 4773 { 4774 struct rtw89_btc *btc = &rtwdev->btc; 4775 4776 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4777 4778 switch (btc->cx.state_map) { 4779 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 4780 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 4781 BTC_ACT_BT_A2DP_PAN_HID); 4782 break; 4783 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 4784 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 4785 BTC_ACT_BT_A2DP_PAN_HID); 4786 break; 4787 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 4788 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 4789 BTC_ACT_BT_A2DP_PAN_HID); 4790 break; 4791 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 4792 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 4793 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 4794 BTC_ACT_BT_A2DP_PAN_HID); 4795 break; 4796 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 4797 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 4798 BTC_ACT_BT_A2DP_PAN_HID); 4799 break; 4800 } 4801 } 4802 4803 static void _action_wl_5g(struct rtw89_dev *rtwdev) 4804 { 4805 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 4806 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 4807 } 4808 4809 static void _action_wl_other(struct rtw89_dev *rtwdev) 4810 { 4811 struct rtw89_btc *btc = &rtwdev->btc; 4812 4813 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4814 4815 if (btc->ant_type == BTC_ANT_SHARED) 4816 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 4817 else 4818 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 4819 } 4820 4821 static void _action_wl_nc(struct rtw89_dev *rtwdev) 4822 { 4823 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4824 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 4825 } 4826 4827 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 4828 { 4829 struct rtw89_btc *btc = &rtwdev->btc; 4830 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 4831 4832 if (rfk.state != BTC_WRFK_START) 4833 return; 4834 4835 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 4836 __func__, rfk.band); 4837 4838 btc->dm.tdma_instant_excute = 1; 4839 4840 if (rfk.state == BTC_WRFK_ONESHOT_START || 4841 btc->ant_type == BTC_ANT_SHARED) { 4842 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); 4843 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); 4844 } else { 4845 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 4846 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 4847 } 4848 } 4849 4850 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 4851 { 4852 struct rtw89_btc *btc = &rtwdev->btc; 4853 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4854 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 4855 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 4856 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 4857 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 4858 struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info; 4859 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4860 const struct rtw89_chip_info *chip = rtwdev->chip; 4861 const struct rtw89_btc_ver *ver = btc->ver; 4862 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4863 struct rtw89_btc_dm *dm = &btc->dm; 4864 struct _wl_rinfo_now wl_rinfo; 4865 u32 run_reason = btc->dm.run_reason; 4866 u32 is_btg; 4867 u8 i, val; 4868 4869 if (btc->manual_ctrl) 4870 return; 4871 4872 if (ver->fwlrole == 0) 4873 wl_rinfo.link_mode = wl_rinfo_v0->link_mode; 4874 else if (ver->fwlrole == 1) 4875 wl_rinfo.link_mode = wl_rinfo_v1->link_mode; 4876 else if (ver->fwlrole == 2) 4877 wl_rinfo.link_mode = wl_rinfo_v2->link_mode; 4878 else if (ver->fwlrole == 7) 4879 wl_rinfo.link_mode = wl_rinfo_v7->link_mode; 4880 else if (ver->fwlrole == 8) 4881 wl_rinfo.link_mode = wl_rinfo_v8->link_mode; 4882 else 4883 return; 4884 4885 if (rtwdev->dbcc_en) { 4886 if (ver->fwlrole == 0) { 4887 wl_rinfo.dbcc_2g_phy = RTW89_PHY_NUM; 4888 4889 for (i = 0; i < RTW89_PHY_NUM; i++) { 4890 if (wl_dinfo->real_band[i] == RTW89_BAND_2G) 4891 wl_rinfo.dbcc_2g_phy = i; 4892 } 4893 } else if (ver->fwlrole == 1) { 4894 wl_rinfo.dbcc_2g_phy = wl_rinfo_v1->dbcc_2g_phy; 4895 } else if (ver->fwlrole == 2) { 4896 wl_rinfo.dbcc_2g_phy = wl_rinfo_v2->dbcc_2g_phy; 4897 } else if (ver->fwlrole == 7) { 4898 wl_rinfo.dbcc_2g_phy = wl_rinfo_v7->dbcc_2g_phy; 4899 } else if (ver->fwlrole == 8) { 4900 wl_rinfo.dbcc_2g_phy = wl_rinfo_v8->dbcc_2g_phy; 4901 } else { 4902 return; 4903 } 4904 } 4905 4906 if (wl_rinfo.link_mode == BTC_WLINK_25G_MCC) 4907 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; 4908 else if (!(bt->run_patch_code && bt->enable.now)) 4909 is_btg = BTC_BTGCTRL_DISABLE; 4910 else if (wl_rinfo.link_mode == BTC_WLINK_5G) 4911 is_btg = BTC_BTGCTRL_DISABLE; 4912 else if (dm->freerun) 4913 is_btg = BTC_BTGCTRL_DISABLE; 4914 else if (rtwdev->dbcc_en && wl_rinfo.dbcc_2g_phy != RTW89_PHY_1) 4915 is_btg = BTC_BTGCTRL_DISABLE; 4916 else 4917 is_btg = BTC_BTGCTRL_ENABLE; 4918 4919 if (dm->wl_btg_rx_rb != dm->wl_btg_rx && 4920 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) { 4921 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX, &val); 4922 dm->wl_btg_rx_rb = val; 4923 } 4924 4925 if (run_reason == BTC_RSN_NTFY_INIT || 4926 run_reason == BTC_RSN_NTFY_SWBAND || 4927 dm->wl_btg_rx_rb != dm->wl_btg_rx || 4928 is_btg != dm->wl_btg_rx) { 4929 4930 dm->wl_btg_rx = is_btg; 4931 4932 if (is_btg > BTC_BTGCTRL_ENABLE) 4933 return; 4934 4935 chip->ops->ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0); 4936 } 4937 } 4938 4939 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) 4940 { 4941 struct rtw89_btc *btc = &rtwdev->btc; 4942 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 4943 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4944 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2; 4945 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; 4946 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; 4947 const struct rtw89_chip_info *chip = rtwdev->chip; 4948 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4949 struct rtw89_btc_dm *dm = &btc->dm; 4950 u8 is_preagc, val, link_mode, dbcc_2g_phy; 4951 u8 role_ver = rtwdev->btc.ver->fwlrole; 4952 bool dbcc_en; 4953 4954 if (btc->manual_ctrl) 4955 return; 4956 4957 if (role_ver == 2) { 4958 dbcc_en = rinfo_v2->dbcc_en; 4959 link_mode = rinfo_v2->link_mode; 4960 dbcc_2g_phy = rinfo_v2->dbcc_2g_phy; 4961 } else if (role_ver == 7) { 4962 dbcc_en = rinfo_v7->dbcc_en; 4963 link_mode = rinfo_v7->link_mode; 4964 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy; 4965 } else if (role_ver == 8) { 4966 dbcc_en = rinfo_v8->dbcc_en; 4967 link_mode = rinfo_v8->link_mode; 4968 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy; 4969 } else { 4970 return; 4971 } 4972 4973 if (link_mode == BTC_WLINK_25G_MCC) { 4974 is_preagc = BTC_PREAGC_BB_FWCTRL; 4975 } else if (!(bt->run_patch_code && bt->enable.now)) { 4976 is_preagc = BTC_PREAGC_DISABLE; 4977 } else if (link_mode == BTC_WLINK_5G) { 4978 is_preagc = BTC_PREAGC_DISABLE; 4979 } else if (link_mode == BTC_WLINK_NOLINK || 4980 btc->cx.bt.link_info.profile_cnt.now == 0) { 4981 is_preagc = BTC_PREAGC_DISABLE; 4982 } else if (dm->tdma_now.type != CXTDMA_OFF && 4983 !bt_linfo->hfp_desc.exist && 4984 !bt_linfo->hid_desc.exist && 4985 dm->fddt_train == BTC_FDDT_DISABLE) { 4986 is_preagc = BTC_PREAGC_DISABLE; 4987 } else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) { 4988 is_preagc = BTC_PREAGC_DISABLE; 4989 } else if (btc->ant_type == BTC_ANT_SHARED) { 4990 is_preagc = BTC_PREAGC_DISABLE; 4991 } else { 4992 is_preagc = BTC_PREAGC_ENABLE; 4993 } 4994 4995 if (dm->wl_pre_agc_rb != dm->wl_pre_agc && 4996 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) { 4997 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val); 4998 dm->wl_pre_agc_rb = val; 4999 } 5000 5001 if ((wl->coex_mode == BTC_MODE_NORMAL && 5002 (dm->run_reason == BTC_RSN_NTFY_INIT || 5003 dm->run_reason == BTC_RSN_NTFY_SWBAND || 5004 dm->wl_pre_agc_rb != dm->wl_pre_agc)) || 5005 is_preagc != dm->wl_pre_agc) { 5006 dm->wl_pre_agc = is_preagc; 5007 5008 if (is_preagc > BTC_PREAGC_ENABLE) 5009 return; 5010 chip->ops->ctrl_nbtg_bt_tx(rtwdev, dm->wl_pre_agc, RTW89_PHY_0); 5011 } 5012 } 5013 5014 struct rtw89_txtime_data { 5015 struct rtw89_dev *rtwdev; 5016 int type; 5017 u32 tx_time; 5018 u8 tx_retry; 5019 u16 enable; 5020 bool reenable; 5021 }; 5022 5023 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, 5024 struct rtw89_sta_link *rtwsta_link, 5025 struct rtw89_txtime_data *iter_data) 5026 { 5027 struct rtw89_dev *rtwdev = iter_data->rtwdev; 5028 struct rtw89_btc *btc = &rtwdev->btc; 5029 struct rtw89_btc_cx *cx = &btc->cx; 5030 struct rtw89_btc_wl_info *wl = &cx->wl; 5031 struct rtw89_btc_wl_link_info *plink = NULL; 5032 u8 port = rtwvif_link->port; 5033 u32 tx_time = iter_data->tx_time; 5034 u8 tx_retry = iter_data->tx_retry; 5035 u16 enable = iter_data->enable; 5036 bool reenable = iter_data->reenable; 5037 5038 if (btc->ver->fwlrole == 8) 5039 plink = &wl->rlink_info[port][0]; 5040 else 5041 plink = &wl->link_info[port]; 5042 5043 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5044 "[BTC], %s(): port = %d\n", __func__, port); 5045 5046 if (!plink->connected) { 5047 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5048 "[BTC], %s(): connected = %d\n", 5049 __func__, plink->connected); 5050 return; 5051 } 5052 5053 /* backup the original tx time before tx-limit on */ 5054 if (reenable) { 5055 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); 5056 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); 5057 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5058 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 5059 __func__, plink->tx_time, plink->tx_retry); 5060 } 5061 5062 /* restore the original tx time if no tx-limit */ 5063 if (!enable) { 5064 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); 5065 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, 5066 plink->tx_retry); 5067 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5068 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 5069 __func__, plink->tx_time, plink->tx_retry); 5070 5071 } else { 5072 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); 5073 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); 5074 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5075 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 5076 __func__, tx_time, tx_retry); 5077 } 5078 } 5079 5080 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 5081 { 5082 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 5083 struct rtw89_txtime_data *iter_data = 5084 (struct rtw89_txtime_data *)data; 5085 struct rtw89_vif_link *rtwvif_link; 5086 struct rtw89_sta_link *rtwsta_link; 5087 unsigned int link_id; 5088 5089 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 5090 rtwvif_link = rtwsta_link->rtwvif_link; 5091 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); 5092 } 5093 } 5094 5095 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 5096 { 5097 struct rtw89_btc *btc = &rtwdev->btc; 5098 const struct rtw89_btc_ver *ver = btc->ver; 5099 struct rtw89_btc_cx *cx = &btc->cx; 5100 struct rtw89_btc_dm *dm = &btc->dm; 5101 struct rtw89_btc_wl_info *wl = &cx->wl; 5102 struct rtw89_btc_bt_info *bt = &cx->bt; 5103 struct rtw89_btc_bt_link_info *b = &bt->link_info; 5104 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 5105 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 5106 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5107 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5108 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5109 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 5110 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 5111 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 5112 u8 mode, igno_bt, tx_retry; 5113 u32 tx_time; 5114 u16 enable; 5115 bool reenable = false; 5116 5117 if (btc->manual_ctrl) 5118 return; 5119 5120 if (ver->fwlrole == 0) 5121 mode = wl_rinfo->link_mode; 5122 else if (ver->fwlrole == 1) 5123 mode = wl_rinfo_v1->link_mode; 5124 else if (ver->fwlrole == 2) 5125 mode = wl_rinfo_v2->link_mode; 5126 else if (ver->fwlrole == 7) 5127 mode = wl_rinfo_v7->link_mode; 5128 else if (ver->fwlrole == 8) 5129 mode = wl_rinfo_v8->link_mode; 5130 else 5131 return; 5132 5133 if (ver->fcxctrl == 7) 5134 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 5135 else 5136 igno_bt = btc->ctrl.ctrl.igno_bt; 5137 5138 if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 || 5139 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) { 5140 enable = 0; 5141 tx_time = BTC_MAX_TX_TIME_DEF; 5142 tx_retry = BTC_MAX_TX_RETRY_DEF; 5143 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 5144 enable = 1; 5145 tx_time = BTC_MAX_TX_TIME_L2; 5146 tx_retry = BTC_MAX_TX_RETRY_L1; 5147 } else if (hfp->exist || hid->exist) { 5148 enable = 1; 5149 tx_time = BTC_MAX_TX_TIME_L3; 5150 tx_retry = BTC_MAX_TX_RETRY_L1; 5151 } else { 5152 enable = 0; 5153 tx_time = BTC_MAX_TX_TIME_DEF; 5154 tx_retry = BTC_MAX_TX_RETRY_DEF; 5155 } 5156 5157 if (dm->wl_tx_limit.enable == enable && 5158 dm->wl_tx_limit.tx_time == tx_time && 5159 dm->wl_tx_limit.tx_retry == tx_retry) 5160 return; 5161 5162 if (!dm->wl_tx_limit.enable && enable) 5163 reenable = true; 5164 5165 dm->wl_tx_limit.enable = enable; 5166 dm->wl_tx_limit.tx_time = tx_time; 5167 dm->wl_tx_limit.tx_retry = tx_retry; 5168 5169 data.enable = enable; 5170 data.tx_time = tx_time; 5171 data.tx_retry = tx_retry; 5172 data.reenable = reenable; 5173 5174 ieee80211_iterate_stations_atomic(rtwdev->hw, 5175 rtw89_tx_time_iter, 5176 &data); 5177 } 5178 5179 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 5180 { 5181 struct rtw89_btc *btc = &rtwdev->btc; 5182 const struct rtw89_btc_ver *ver = btc->ver; 5183 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5184 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5185 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5186 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5187 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 5188 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 5189 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5190 bool bt_hi_lna_rx = false; 5191 u8 mode; 5192 5193 if (ver->fwlrole == 0) 5194 mode = wl_rinfo->link_mode; 5195 else if (ver->fwlrole == 1) 5196 mode = wl_rinfo_v1->link_mode; 5197 else if (ver->fwlrole == 2) 5198 mode = wl_rinfo_v2->link_mode; 5199 else if (ver->fwlrole == 7) 5200 mode = wl_rinfo_v7->link_mode; 5201 else if (ver->fwlrole == 8) 5202 mode = wl_rinfo_v8->link_mode; 5203 else 5204 return; 5205 5206 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 5207 bt_hi_lna_rx = true; 5208 5209 if (bt_hi_lna_rx == bt->hi_lna_rx) 5210 return; 5211 5212 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 5213 } 5214 5215 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 5216 { 5217 struct rtw89_btc *btc = &rtwdev->btc; 5218 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5219 5220 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri)); 5221 } 5222 5223 static void _action_common(struct rtw89_dev *rtwdev) 5224 { 5225 struct rtw89_btc *btc = &rtwdev->btc; 5226 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5227 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; 5228 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5229 struct rtw89_btc_dm *dm = &btc->dm; 5230 u32 bt_rom_code_id, bt_fw_ver; 5231 5232 _set_btg_ctrl(rtwdev); 5233 _set_wl_preagc_ctrl(rtwdev); 5234 _set_wl_tx_limit(rtwdev); 5235 _set_bt_afh_info(rtwdev); 5236 _set_bt_rx_agc(rtwdev); 5237 _set_rf_trx_para(rtwdev); 5238 _set_bt_rx_scan_pri(rtwdev); 5239 5240 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id); 5241 bt_fw_ver = bt->ver_info.fw & 0xffff; 5242 if (bt->enable.now && 5243 (bt_fw_ver == 0 || 5244 (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd))) 5245 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1); 5246 else 5247 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0); 5248 5249 if (dm->run_reason == BTC_RSN_NTFY_INIT || 5250 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE || 5251 dm->run_reason == BTC_RSN_NTFY_POWEROFF) { 5252 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5253 5254 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF) 5255 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 5256 else 5257 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1); 5258 } 5259 5260 if (wl->scbd_change) { 5261 rtw89_mac_cfg_sb(rtwdev, wl->scbd); 5262 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n", 5263 wl->scbd); 5264 wl->scbd_change = false; 5265 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++; 5266 } 5267 btc->dm.tdma_instant_excute = 0; 5268 } 5269 5270 static void _action_by_bt(struct rtw89_dev *rtwdev) 5271 { 5272 struct rtw89_btc *btc = &rtwdev->btc; 5273 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5274 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 5275 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 5276 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 5277 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 5278 struct rtw89_btc_dm *dm = &btc->dm; 5279 u8 profile_map = 0; 5280 5281 if (dm->freerun_chk) { 5282 _action_freerun(rtwdev); 5283 return; 5284 } 5285 5286 if (bt_linfo->hfp_desc.exist) 5287 profile_map |= BTC_BT_HFP; 5288 5289 if (bt_linfo->hid_desc.exist) 5290 profile_map |= BTC_BT_HID; 5291 5292 if (bt_linfo->a2dp_desc.exist) 5293 profile_map |= BTC_BT_A2DP; 5294 5295 if (bt_linfo->pan_desc.exist) 5296 profile_map |= BTC_BT_PAN; 5297 5298 switch (profile_map) { 5299 case BTC_BT_NOPROFILE: 5300 if (pan.active) 5301 _action_bt_pan(rtwdev); 5302 else 5303 _action_bt_idle(rtwdev); 5304 break; 5305 case BTC_BT_HFP: 5306 _action_bt_hfp(rtwdev); 5307 break; 5308 case BTC_BT_HFP | BTC_BT_HID: 5309 case BTC_BT_HID: 5310 _action_bt_hid(rtwdev); 5311 break; 5312 case BTC_BT_A2DP: 5313 if (a2dp.sink) 5314 _action_bt_a2dpsink(rtwdev); 5315 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 5316 _action_bt_a2dp_pan(rtwdev); 5317 else 5318 _action_bt_a2dp(rtwdev); 5319 break; 5320 case BTC_BT_PAN: 5321 _action_bt_pan(rtwdev); 5322 break; 5323 case BTC_BT_A2DP | BTC_BT_HFP: 5324 case BTC_BT_A2DP | BTC_BT_HID: 5325 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 5326 if (a2dp.sink) 5327 _action_bt_a2dpsink(rtwdev); 5328 else if (pan.active) 5329 _action_bt_a2dp_pan_hid(rtwdev); 5330 else 5331 _action_bt_a2dp_hid(rtwdev); 5332 break; 5333 case BTC_BT_A2DP | BTC_BT_PAN: 5334 if (a2dp.sink) 5335 _action_bt_a2dpsink(rtwdev); 5336 else 5337 _action_bt_a2dp_pan(rtwdev); 5338 break; 5339 case BTC_BT_PAN | BTC_BT_HFP: 5340 case BTC_BT_PAN | BTC_BT_HID: 5341 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 5342 _action_bt_pan_hid(rtwdev); 5343 break; 5344 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 5345 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 5346 default: 5347 if (a2dp.sink) 5348 _action_bt_a2dpsink(rtwdev); 5349 else 5350 _action_bt_a2dp_pan_hid(rtwdev); 5351 break; 5352 } 5353 } 5354 5355 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 5356 { 5357 _action_by_bt(rtwdev); 5358 } 5359 5360 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 5361 { 5362 struct rtw89_btc *btc = &rtwdev->btc; 5363 u16 policy_type = BTC_CXP_OFF_BT; 5364 5365 if (btc->ant_type == BTC_ANT_SHARED) { 5366 if (btc->cx.wl.status.map._4way) 5367 policy_type = BTC_CXP_OFFE_WL; 5368 else if (btc->cx.wl.status.val & btc_scanning_map.val) 5369 policy_type = BTC_CXP_OFFE_2GBWMIXB; 5370 else if (btc->cx.bt.link_info.status.map.connect == 0) 5371 policy_type = BTC_CXP_OFFE_2GISOB; 5372 else 5373 policy_type = BTC_CXP_OFFE_2GBWISOB; 5374 } else { /* dedicated-antenna */ 5375 policy_type = BTC_CXP_OFF_EQ0; 5376 } 5377 5378 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF; 5379 5380 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 5381 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC); 5382 } 5383 5384 static void _action_wl_scan(struct rtw89_dev *rtwdev) 5385 { 5386 struct rtw89_btc *btc = &rtwdev->btc; 5387 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5388 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5389 5390 if (btc->cx.state_map != BTC_WLINKING && 5391 RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { 5392 _action_wl_25g_mcc(rtwdev); 5393 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 5394 } else if (rtwdev->dbcc_en) { 5395 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 5396 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 5397 _action_wl_5g(rtwdev); 5398 else 5399 _action_by_bt(rtwdev); 5400 } else { 5401 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 5402 _action_wl_5g(rtwdev); 5403 else 5404 _action_by_bt(rtwdev); 5405 } 5406 } 5407 5408 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 5409 { struct rtw89_btc *btc = &rtwdev->btc; 5410 5411 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5412 5413 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5414 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5415 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 5416 BTC_ACT_WL_2G_MCC); 5417 else 5418 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 5419 BTC_ACT_WL_2G_MCC); 5420 } else { /* dedicated-antenna */ 5421 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 5422 } 5423 } 5424 5425 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 5426 { 5427 struct rtw89_btc *btc = &rtwdev->btc; 5428 5429 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5430 5431 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5432 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5433 _set_policy(rtwdev, 5434 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC); 5435 else 5436 _set_policy(rtwdev, 5437 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC); 5438 } else { /* dedicated-antenna */ 5439 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC); 5440 } 5441 } 5442 5443 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev) 5444 { 5445 struct rtw89_btc *btc = &rtwdev->btc; 5446 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5447 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5448 struct rtw89_btc_dm *dm = &btc->dm; 5449 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 5450 u16 policy_type = BTC_CXP_OFF_BT; 5451 u32 dur; 5452 5453 if (btc->ant_type == BTC_ANT_DEDICATED) { 5454 policy_type = BTC_CXP_OFF_EQ0; 5455 } else { 5456 /* shared-antenna */ 5457 switch (wl_rinfo->mrole_type) { 5458 case BTC_WLMROLE_STA_GC: 5459 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5460 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 5461 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5462 _action_by_bt(rtwdev); 5463 return; 5464 case BTC_WLMROLE_STA_STA: 5465 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5466 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 5467 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5468 _action_by_bt(rtwdev); 5469 return; 5470 case BTC_WLMROLE_STA_GC_NOA: 5471 case BTC_WLMROLE_STA_GO: 5472 case BTC_WLMROLE_STA_GO_NOA: 5473 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5474 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 5475 dur = wl_rinfo->mrole_noa_duration; 5476 5477 if (wl->status.map._4way) { 5478 dm->wl_scc.ebt_null = 0; 5479 policy_type = BTC_CXP_OFFE_WL; 5480 } else if (bt->link_info.status.map.connect == 0) { 5481 dm->wl_scc.ebt_null = 0; 5482 policy_type = BTC_CXP_OFFE_2GISOB; 5483 } else if (bt->link_info.a2dp_desc.exist && 5484 dur < btc->bt_req_len) { 5485 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5486 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 5487 } else if (bt->link_info.a2dp_desc.exist || 5488 bt->link_info.pan_desc.exist) { 5489 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5490 policy_type = BTC_CXP_OFFE_2GBWISOB; 5491 } else { 5492 dm->wl_scc.ebt_null = 0; 5493 policy_type = BTC_CXP_OFFE_2GBWISOB; 5494 } 5495 break; 5496 default: 5497 break; 5498 } 5499 } 5500 5501 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5502 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 5503 } 5504 5505 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev) 5506 { 5507 struct rtw89_btc *btc = &rtwdev->btc; 5508 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5509 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5510 struct rtw89_btc_dm *dm = &btc->dm; 5511 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2; 5512 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; 5513 u32 dur, mrole_type, mrole_noa_duration; 5514 u16 policy_type = BTC_CXP_OFF_BT; 5515 5516 if (btc->ver->fwlrole == 2) { 5517 mrole_type = rinfo_v2->mrole_type; 5518 mrole_noa_duration = rinfo_v2->mrole_noa_duration; 5519 } else if (btc->ver->fwlrole == 7) { 5520 mrole_type = rinfo_v7->mrole_type; 5521 mrole_noa_duration = rinfo_v7->mrole_noa_duration; 5522 } else { 5523 return; 5524 } 5525 5526 if (btc->ant_type == BTC_ANT_DEDICATED) { 5527 policy_type = BTC_CXP_OFF_EQ0; 5528 } else { 5529 /* shared-antenna */ 5530 switch (mrole_type) { 5531 case BTC_WLMROLE_STA_GC: 5532 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5533 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 5534 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5535 _action_by_bt(rtwdev); 5536 return; 5537 case BTC_WLMROLE_STA_STA: 5538 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5539 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 5540 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5541 _action_by_bt(rtwdev); 5542 return; 5543 case BTC_WLMROLE_STA_GC_NOA: 5544 case BTC_WLMROLE_STA_GO: 5545 case BTC_WLMROLE_STA_GO_NOA: 5546 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5547 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 5548 dur = mrole_noa_duration; 5549 5550 if (wl->status.map._4way) { 5551 dm->wl_scc.ebt_null = 0; 5552 policy_type = BTC_CXP_OFFE_WL; 5553 } else if (bt->link_info.status.map.connect == 0) { 5554 dm->wl_scc.ebt_null = 0; 5555 policy_type = BTC_CXP_OFFE_2GISOB; 5556 } else if (bt->link_info.a2dp_desc.exist && 5557 dur < btc->bt_req_len) { 5558 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5559 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 5560 } else if (bt->link_info.a2dp_desc.exist || 5561 bt->link_info.pan_desc.exist) { 5562 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5563 policy_type = BTC_CXP_OFFE_2GBWISOB; 5564 } else { 5565 dm->wl_scc.ebt_null = 0; 5566 policy_type = BTC_CXP_OFFE_2GBWISOB; 5567 } 5568 break; 5569 default: 5570 break; 5571 } 5572 } 5573 5574 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5575 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 5576 } 5577 5578 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev) 5579 { 5580 struct rtw89_btc *btc = &rtwdev->btc; 5581 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5582 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5583 struct rtw89_btc_dm *dm = &btc->dm; 5584 u16 policy_type = BTC_CXP_OFF_BT; 5585 5586 if (btc->ant_type == BTC_ANT_SHARED) { 5587 if (wl->status.map._4way) 5588 policy_type = BTC_CXP_OFFE_WL; 5589 else if (bt->link_info.status.map.connect == 0) 5590 policy_type = BTC_CXP_OFFE_2GISOB; 5591 else 5592 policy_type = BTC_CXP_OFFE_2GBWISOB; 5593 } else { 5594 policy_type = BTC_CXP_OFF_EQ0; 5595 } 5596 5597 dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF; 5598 5599 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5600 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 5601 } 5602 5603 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 5604 { 5605 struct rtw89_btc *btc = &rtwdev->btc; 5606 5607 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5608 5609 if (btc->ant_type == BTC_ANT_SHARED) { 5610 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5611 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 5612 BTC_ACT_WL_2G_AP); 5613 else 5614 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 5615 } else {/* dedicated-antenna */ 5616 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 5617 } 5618 } 5619 5620 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 5621 { 5622 struct rtw89_btc *btc = &rtwdev->btc; 5623 5624 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5625 5626 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5627 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5628 _set_policy(rtwdev, 5629 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 5630 else 5631 _set_policy(rtwdev, 5632 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 5633 } else { /* dedicated-antenna */ 5634 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 5635 } 5636 } 5637 5638 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 5639 { 5640 struct rtw89_btc *btc = &rtwdev->btc; 5641 5642 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5643 5644 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5645 _action_by_bt(rtwdev); 5646 } else {/* dedicated-antenna */ 5647 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 5648 } 5649 } 5650 5651 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 5652 { 5653 struct rtw89_btc *btc = &rtwdev->btc; 5654 5655 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5656 5657 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5658 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5659 _set_policy(rtwdev, 5660 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 5661 else 5662 _set_policy(rtwdev, 5663 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 5664 } else { /* dedicated-antenna */ 5665 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 5666 } 5667 } 5668 5669 static u32 _read_scbd(struct rtw89_dev *rtwdev) 5670 { 5671 const struct rtw89_chip_info *chip = rtwdev->chip; 5672 struct rtw89_btc *btc = &rtwdev->btc; 5673 u32 scbd_val = 0; 5674 5675 if (!chip->scbd) 5676 return 0; 5677 5678 scbd_val = rtw89_mac_get_sb(rtwdev); 5679 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n", 5680 scbd_val); 5681 5682 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++; 5683 return scbd_val; 5684 } 5685 5686 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state) 5687 { 5688 const struct rtw89_chip_info *chip = rtwdev->chip; 5689 struct rtw89_btc *btc = &rtwdev->btc; 5690 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5691 u32 scbd_val = 0; 5692 u8 force_exec = false; 5693 5694 if (!chip->scbd) 5695 return; 5696 5697 scbd_val = state ? wl->scbd | val : wl->scbd & ~val; 5698 5699 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON) 5700 force_exec = true; 5701 5702 if (scbd_val != wl->scbd || force_exec) { 5703 wl->scbd = scbd_val; 5704 wl->scbd_change = true; 5705 } 5706 } 5707 5708 static u8 5709 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 5710 { 5711 const struct rtw89_chip_info *chip = rtwdev->chip; 5712 u8 next_state, tol = chip->rssi_tol; 5713 5714 if (pre_state == BTC_RSSI_ST_LOW || 5715 pre_state == BTC_RSSI_ST_STAY_LOW) { 5716 if (rssi >= (thresh + tol)) 5717 next_state = BTC_RSSI_ST_HIGH; 5718 else 5719 next_state = BTC_RSSI_ST_STAY_LOW; 5720 } else { 5721 if (rssi < thresh) 5722 next_state = BTC_RSSI_ST_LOW; 5723 else 5724 next_state = BTC_RSSI_ST_STAY_HIGH; 5725 } 5726 5727 return next_state; 5728 } 5729 5730 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac) 5731 { 5732 if (mac == RTW89_MAC_0) 5733 rtw89_write32_clr(rtwdev, R_AX_BTC_CFG, B_AX_WL_SRC); 5734 else 5735 rtw89_write32_set(rtwdev, R_AX_BTC_CFG, B_AX_WL_SRC); 5736 } 5737 5738 static 5739 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 5740 { 5741 struct rtw89_btc *btc = &rtwdev->btc; 5742 5743 btc->cx.wl.dbcc_info.real_band[phy_idx] = 5744 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 5745 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 5746 btc->cx.wl.dbcc_info.op_band[phy_idx]; 5747 } 5748 5749 static void _update_wl_info(struct rtw89_dev *rtwdev) 5750 { 5751 struct rtw89_btc *btc = &rtwdev->btc; 5752 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5753 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 5754 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5755 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5756 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 5757 u8 cnt_2g = 0, cnt_5g = 0, phy; 5758 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0}; 5759 bool b2g = false, b5g = false, client_joined = false; 5760 5761 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 5762 5763 for (i = 0; i < RTW89_PORT_NUM; i++) { 5764 /* check if role active? */ 5765 if (!wl_linfo[i].active) 5766 continue; 5767 5768 cnt_active++; 5769 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role; 5770 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid; 5771 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy; 5772 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band; 5773 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 5774 wl_rinfo->active_role[cnt_active - 1].connected = 0; 5775 5776 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 5777 5778 phy = wl_linfo[i].phy; 5779 5780 /* check dbcc role */ 5781 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) { 5782 wl_dinfo->role[phy] = wl_linfo[i].role; 5783 wl_dinfo->op_band[phy] = wl_linfo[i].band; 5784 _update_dbcc_band(rtwdev, phy); 5785 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5786 } 5787 5788 if (wl_linfo[i].connected == MLME_NO_LINK) { 5789 continue; 5790 } else if (wl_linfo[i].connected == MLME_LINKING) { 5791 cnt_connecting++; 5792 } else { 5793 cnt_connect++; 5794 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 5795 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 5796 wl_linfo[i].client_cnt > 1) 5797 client_joined = true; 5798 } 5799 5800 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 5801 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch; 5802 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw; 5803 wl_rinfo->active_role[cnt_active - 1].connected = 1; 5804 5805 /* only care 2 roles + BT coex */ 5806 if (wl_linfo[i].band != RTW89_BAND_2G) { 5807 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 5808 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 5809 cnt_5g++; 5810 b5g = true; 5811 } else { 5812 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 5813 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 5814 cnt_2g++; 5815 b2g = true; 5816 } 5817 } 5818 5819 wl_rinfo->connect_cnt = cnt_connect; 5820 5821 /* Be careful to change the following sequence!! */ 5822 if (cnt_connect == 0) { 5823 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5824 wl_rinfo->role_map.role.none = 1; 5825 } else if (!b2g && b5g) { 5826 wl_rinfo->link_mode = BTC_WLINK_5G; 5827 } else if (wl_rinfo->role_map.role.nan) { 5828 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 5829 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 5830 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5831 } else if (b2g && b5g && cnt_connect == 2) { 5832 if (rtwdev->dbcc_en) { 5833 switch (wl_dinfo->role[RTW89_PHY_0]) { 5834 case RTW89_WIFI_ROLE_STATION: 5835 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5836 break; 5837 case RTW89_WIFI_ROLE_P2P_GO: 5838 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5839 break; 5840 case RTW89_WIFI_ROLE_P2P_CLIENT: 5841 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5842 break; 5843 case RTW89_WIFI_ROLE_AP: 5844 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5845 break; 5846 default: 5847 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5848 break; 5849 } 5850 } else { 5851 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 5852 } 5853 } else if (!b5g && cnt_connect == 2) { 5854 if (wl_rinfo->role_map.role.station && 5855 (wl_rinfo->role_map.role.p2p_go || 5856 wl_rinfo->role_map.role.p2p_gc || 5857 wl_rinfo->role_map.role.ap)) { 5858 if (wl_2g_ch[0] == wl_2g_ch[1]) 5859 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 5860 else 5861 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 5862 } else { 5863 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 5864 } 5865 } else if (!b5g && cnt_connect == 1) { 5866 if (wl_rinfo->role_map.role.station) 5867 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5868 else if (wl_rinfo->role_map.role.ap) 5869 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5870 else if (wl_rinfo->role_map.role.p2p_go) 5871 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5872 else if (wl_rinfo->role_map.role.p2p_gc) 5873 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5874 else 5875 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5876 } 5877 5878 /* if no client_joined, don't care P2P-GO/AP role */ 5879 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 5880 if (!client_joined) { 5881 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 5882 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 5883 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5884 wl_rinfo->connect_cnt = 1; 5885 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 5886 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 5887 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5888 wl_rinfo->connect_cnt = 0; 5889 } 5890 } 5891 } 5892 5893 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5894 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 5895 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 5896 5897 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5898 } 5899 5900 static void _update_wl_info_v1(struct rtw89_dev *rtwdev) 5901 { 5902 struct rtw89_btc *btc = &rtwdev->btc; 5903 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5904 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 5905 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 5906 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5907 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 5908 u8 cnt_2g = 0, cnt_5g = 0, phy; 5909 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 5910 bool b2g = false, b5g = false, client_joined = false; 5911 u8 i; 5912 5913 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 5914 5915 for (i = 0; i < RTW89_PORT_NUM; i++) { 5916 if (!wl_linfo[i].active) 5917 continue; 5918 5919 cnt_active++; 5920 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role; 5921 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid; 5922 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy; 5923 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band; 5924 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 5925 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0; 5926 5927 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 5928 5929 phy = wl_linfo[i].phy; 5930 5931 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) { 5932 wl_dinfo->role[phy] = wl_linfo[i].role; 5933 wl_dinfo->op_band[phy] = wl_linfo[i].band; 5934 _update_dbcc_band(rtwdev, phy); 5935 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5936 } 5937 5938 if (wl_linfo[i].connected == MLME_NO_LINK) { 5939 continue; 5940 } else if (wl_linfo[i].connected == MLME_LINKING) { 5941 cnt_connecting++; 5942 } else { 5943 cnt_connect++; 5944 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 5945 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 5946 wl_linfo[i].client_cnt > 1) 5947 client_joined = true; 5948 } 5949 5950 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 5951 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch; 5952 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw; 5953 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1; 5954 5955 /* only care 2 roles + BT coex */ 5956 if (wl_linfo[i].band != RTW89_BAND_2G) { 5957 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 5958 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 5959 cnt_5g++; 5960 b5g = true; 5961 } else { 5962 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 5963 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 5964 cnt_2g++; 5965 b2g = true; 5966 } 5967 } 5968 5969 wl_rinfo->connect_cnt = cnt_connect; 5970 5971 /* Be careful to change the following sequence!! */ 5972 if (cnt_connect == 0) { 5973 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 5974 wl_rinfo->role_map.role.none = 1; 5975 } else if (!b2g && b5g) { 5976 wl_rinfo->link_mode = BTC_WLINK_5G; 5977 } else if (wl_rinfo->role_map.role.nan) { 5978 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 5979 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 5980 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5981 } else if (b2g && b5g && cnt_connect == 2) { 5982 if (rtwdev->dbcc_en) { 5983 switch (wl_dinfo->role[RTW89_PHY_0]) { 5984 case RTW89_WIFI_ROLE_STATION: 5985 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 5986 break; 5987 case RTW89_WIFI_ROLE_P2P_GO: 5988 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 5989 break; 5990 case RTW89_WIFI_ROLE_P2P_CLIENT: 5991 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 5992 break; 5993 case RTW89_WIFI_ROLE_AP: 5994 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 5995 break; 5996 default: 5997 wl_rinfo->link_mode = BTC_WLINK_OTHER; 5998 break; 5999 } 6000 } else { 6001 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 6002 } 6003 } else if (!b5g && cnt_connect == 2) { 6004 if (wl_rinfo->role_map.role.station && 6005 (wl_rinfo->role_map.role.p2p_go || 6006 wl_rinfo->role_map.role.p2p_gc || 6007 wl_rinfo->role_map.role.ap)) { 6008 if (wl_2g_ch[0] == wl_2g_ch[1]) 6009 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 6010 else 6011 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6012 } else { 6013 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6014 } 6015 } else if (!b5g && cnt_connect == 1) { 6016 if (wl_rinfo->role_map.role.station) 6017 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6018 else if (wl_rinfo->role_map.role.ap) 6019 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6020 else if (wl_rinfo->role_map.role.p2p_go) 6021 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6022 else if (wl_rinfo->role_map.role.p2p_gc) 6023 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6024 else 6025 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6026 } 6027 6028 /* if no client_joined, don't care P2P-GO/AP role */ 6029 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 6030 if (!client_joined) { 6031 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 6032 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 6033 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6034 wl_rinfo->connect_cnt = 1; 6035 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 6036 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 6037 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6038 wl_rinfo->connect_cnt = 0; 6039 } 6040 } 6041 } 6042 6043 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6044 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 6045 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 6046 6047 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6048 } 6049 6050 static void _update_wl_info_v2(struct rtw89_dev *rtwdev) 6051 { 6052 struct rtw89_btc *btc = &rtwdev->btc; 6053 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6054 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 6055 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 6056 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6057 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 6058 u8 cnt_2g = 0, cnt_5g = 0, phy; 6059 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 6060 bool b2g = false, b5g = false, client_joined = false; 6061 u8 i; 6062 6063 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 6064 6065 for (i = 0; i < RTW89_PORT_NUM; i++) { 6066 if (!wl_linfo[i].active) 6067 continue; 6068 6069 cnt_active++; 6070 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role; 6071 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid; 6072 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy; 6073 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band; 6074 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 6075 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0; 6076 6077 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 6078 6079 phy = wl_linfo[i].phy; 6080 6081 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) { 6082 wl_dinfo->role[phy] = wl_linfo[i].role; 6083 wl_dinfo->op_band[phy] = wl_linfo[i].band; 6084 _update_dbcc_band(rtwdev, phy); 6085 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 6086 } 6087 6088 if (wl_linfo[i].connected == MLME_NO_LINK) { 6089 continue; 6090 } else if (wl_linfo[i].connected == MLME_LINKING) { 6091 cnt_connecting++; 6092 } else { 6093 cnt_connect++; 6094 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6095 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 6096 wl_linfo[i].client_cnt > 1) 6097 client_joined = true; 6098 } 6099 6100 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 6101 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch; 6102 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw; 6103 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1; 6104 6105 /* only care 2 roles + BT coex */ 6106 if (wl_linfo[i].band != RTW89_BAND_2G) { 6107 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 6108 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 6109 cnt_5g++; 6110 b5g = true; 6111 } else { 6112 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 6113 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 6114 cnt_2g++; 6115 b2g = true; 6116 } 6117 } 6118 6119 wl_rinfo->connect_cnt = cnt_connect; 6120 6121 /* Be careful to change the following sequence!! */ 6122 if (cnt_connect == 0) { 6123 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6124 wl_rinfo->role_map.role.none = 1; 6125 } else if (!b2g && b5g) { 6126 wl_rinfo->link_mode = BTC_WLINK_5G; 6127 } else if (wl_rinfo->role_map.role.nan) { 6128 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 6129 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 6130 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6131 } else if (b2g && b5g && cnt_connect == 2) { 6132 if (rtwdev->dbcc_en) { 6133 switch (wl_dinfo->role[RTW89_PHY_0]) { 6134 case RTW89_WIFI_ROLE_STATION: 6135 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6136 break; 6137 case RTW89_WIFI_ROLE_P2P_GO: 6138 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6139 break; 6140 case RTW89_WIFI_ROLE_P2P_CLIENT: 6141 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6142 break; 6143 case RTW89_WIFI_ROLE_AP: 6144 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6145 break; 6146 default: 6147 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6148 break; 6149 } 6150 } else { 6151 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 6152 } 6153 } else if (!b5g && cnt_connect == 2) { 6154 if (wl_rinfo->role_map.role.station && 6155 (wl_rinfo->role_map.role.p2p_go || 6156 wl_rinfo->role_map.role.p2p_gc || 6157 wl_rinfo->role_map.role.ap)) { 6158 if (wl_2g_ch[0] == wl_2g_ch[1]) 6159 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 6160 else 6161 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6162 } else { 6163 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6164 } 6165 } else if (!b5g && cnt_connect == 1) { 6166 if (wl_rinfo->role_map.role.station) 6167 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6168 else if (wl_rinfo->role_map.role.ap) 6169 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6170 else if (wl_rinfo->role_map.role.p2p_go) 6171 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6172 else if (wl_rinfo->role_map.role.p2p_gc) 6173 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6174 else 6175 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6176 } 6177 6178 /* if no client_joined, don't care P2P-GO/AP role */ 6179 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 6180 if (!client_joined) { 6181 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 6182 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 6183 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6184 wl_rinfo->connect_cnt = 1; 6185 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 6186 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 6187 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6188 wl_rinfo->connect_cnt = 0; 6189 } 6190 } 6191 } 6192 6193 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6194 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 6195 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 6196 6197 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6198 } 6199 6200 #define BTC_CHK_HANG_MAX 3 6201 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 6202 6203 static u8 _get_role_link_mode(u8 role) 6204 { 6205 switch (role) { 6206 case RTW89_WIFI_ROLE_STATION: 6207 return BTC_WLINK_2G_STA; 6208 case RTW89_WIFI_ROLE_P2P_GO: 6209 return BTC_WLINK_2G_GO; 6210 case RTW89_WIFI_ROLE_P2P_CLIENT: 6211 return BTC_WLINK_2G_GC; 6212 case RTW89_WIFI_ROLE_AP: 6213 return BTC_WLINK_2G_AP; 6214 default: 6215 return BTC_WLINK_OTHER; 6216 } 6217 } 6218 6219 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1, 6220 const struct rtw89_btc_chdef *r2) 6221 { 6222 if (r1->chan != r2->chan) { /* primary ch is different */ 6223 return false; 6224 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 && 6225 r2->bw == RTW89_CHANNEL_WIDTH_40) { 6226 if (r1->offset != r2->offset) 6227 return false; 6228 } 6229 return true; 6230 } 6231 6232 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch, 6233 u8 *phy, u8 *role, u8 *dbcc_2g_phy) 6234 { 6235 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 6236 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; 6237 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; 6238 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false; 6239 u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, connect_cnt; 6240 6241 if (rtwdev->btc.ver->fwlrole == 7) 6242 connect_cnt = rinfo_v7->connect_cnt; 6243 else if (rtwdev->btc.ver->fwlrole == 8) 6244 connect_cnt = rinfo_v8->connect_cnt; 6245 else 6246 return BTC_WLINK_NOLINK; 6247 6248 /* find out the 2G-PHY by connect-id ->ch */ 6249 for (j = 0; j < connect_cnt; j++) { 6250 if (ch[j].center_ch <= 14) { 6251 is_2g_ch_exist = true; 6252 break; 6253 } 6254 } 6255 6256 /* If no any 2G-port exist, it's impossible because 5G-exclude */ 6257 if (!is_2g_ch_exist) 6258 return BTC_WLINK_OTHER; 6259 6260 dbcc_2g_cid = j; 6261 *dbcc_2g_phy = phy[dbcc_2g_cid]; 6262 6263 /* connect_cnt <= 2 */ 6264 if (connect_cnt < BTC_TDMA_WLROLE_MAX) 6265 return (_get_role_link_mode((role[dbcc_2g_cid]))); 6266 6267 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */ 6268 for (k = 0; k < connect_cnt; k++) { 6269 if (k == dbcc_2g_cid) 6270 continue; 6271 6272 if (phy[k] == *dbcc_2g_phy) { 6273 is_multi_role_in_2g_phy = true; 6274 dbcc_2g_cid2 = k; 6275 break; 6276 } 6277 } 6278 6279 /* Single-role in 2G-PHY */ 6280 if (!is_multi_role_in_2g_phy) 6281 return (_get_role_link_mode(role[dbcc_2g_cid])); 6282 6283 /* 2-role in 2G-PHY */ 6284 if (ch[dbcc_2g_cid2].center_ch > 14) 6285 return BTC_WLINK_25G_MCC; 6286 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2])) 6287 return BTC_WLINK_2G_SCC; 6288 else 6289 return BTC_WLINK_2G_MCC; 6290 } 6291 6292 static void _update_role_link_mode(struct rtw89_dev *rtwdev, 6293 bool client_joined, u32 noa) 6294 { 6295 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8; 6296 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7; 6297 u8 role_ver = rtwdev->btc.ver->fwlrole; 6298 u32 type = BTC_WLMROLE_NONE, dur = 0; 6299 u8 link_mode, connect_cnt; 6300 u32 wl_role; 6301 6302 if (role_ver == 7) { 6303 wl_role = rinfo_v7->role_map; 6304 link_mode = rinfo_v7->link_mode; 6305 connect_cnt = rinfo_v7->connect_cnt; 6306 } else if (role_ver == 8) { 6307 wl_role = rinfo_v8->role_map; 6308 link_mode = rinfo_v8->link_mode; 6309 connect_cnt = rinfo_v8->connect_cnt; 6310 } else { 6311 return; 6312 } 6313 6314 /* if no client_joined, don't care P2P-GO/AP role */ 6315 if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 6316 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) { 6317 if (link_mode == BTC_WLINK_2G_SCC) { 6318 if (role_ver == 7) { 6319 rinfo_v7->link_mode = BTC_WLINK_2G_STA; 6320 rinfo_v7->connect_cnt--; 6321 } else if (role_ver == 8) { 6322 rinfo_v8->link_mode = BTC_WLINK_2G_STA; 6323 rinfo_v8->connect_cnt--; 6324 } 6325 } else if (link_mode == BTC_WLINK_2G_GO || 6326 link_mode == BTC_WLINK_2G_AP) { 6327 if (role_ver == 7) { 6328 rinfo_v7->link_mode = BTC_WLINK_NOLINK; 6329 rinfo_v7->connect_cnt--; 6330 } else if (role_ver == 8) { 6331 rinfo_v8->link_mode = BTC_WLINK_NOLINK; 6332 rinfo_v8->connect_cnt--; 6333 } 6334 } 6335 } 6336 6337 /* Identify 2-Role type */ 6338 if (connect_cnt >= 2 && 6339 (link_mode == BTC_WLINK_2G_SCC || 6340 link_mode == BTC_WLINK_2G_MCC || 6341 link_mode == BTC_WLINK_25G_MCC || 6342 link_mode == BTC_WLINK_5G)) { 6343 if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 6344 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) 6345 type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO; 6346 else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) 6347 type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC; 6348 else 6349 type = BTC_WLMROLE_STA_STA; 6350 6351 dur = noa; 6352 } 6353 6354 if (role_ver == 7) { 6355 rinfo_v7->mrole_type = type; 6356 rinfo_v7->mrole_noa_duration = dur; 6357 } else if (role_ver == 8) { 6358 rinfo_v8->mrole_type = type; 6359 rinfo_v8->mrole_noa_duration = dur; 6360 } 6361 } 6362 6363 static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid) 6364 { 6365 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER]; 6366 struct rtw89_btc *btc = &rtwdev->btc; 6367 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6368 struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7; 6369 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6370 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 6371 struct rtw89_btc_wl_active_role_v7 *act_role = NULL; 6372 u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_NUM, phy_dbcc; 6373 bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false; 6374 u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6375 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6376 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6377 u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0; 6378 u32 noa_duration = 0; 6379 6380 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 6381 6382 for (i = 0; i < RTW89_PORT_NUM; i++) { 6383 if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_NUM) 6384 continue; 6385 6386 act_role = &wl_rinfo->active_role[i]; 6387 act_role->role = wl_linfo[i].role; 6388 6389 /* check if role connect? */ 6390 if (wl_linfo[i].connected == MLME_NO_LINK) { 6391 act_role->connected = 0; 6392 continue; 6393 } else if (wl_linfo[i].connected == MLME_LINKING) { 6394 continue; 6395 } 6396 6397 cnt++; 6398 act_role->connected = 1; 6399 act_role->pid = wl_linfo[i].pid; 6400 act_role->phy = wl_linfo[i].phy; 6401 act_role->band = wl_linfo[i].band; 6402 act_role->ch = wl_linfo[i].ch; 6403 act_role->bw = wl_linfo[i].bw; 6404 act_role->noa = wl_linfo[i].noa; 6405 act_role->noa_dur = wl_linfo[i].noa_duration; 6406 cid_ch[cnt - 1] = wl_linfo[i].chdef; 6407 cid_phy[cnt - 1] = wl_linfo[i].phy; 6408 cid_role[cnt - 1] = wl_linfo[i].role; 6409 wl_rinfo->role_map |= BIT(wl_linfo[i].role); 6410 6411 if (rid == i) 6412 phy_now = act_role->phy; 6413 6414 if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6415 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) { 6416 if (wl_linfo[i].client_cnt > 1) 6417 client_joined = true; 6418 if (client_cnt_last[i] < wl_linfo[i].client_cnt && 6419 wl_linfo[i].chdef.band == RTW89_BAND_2G) 6420 client_inc_2g = true; 6421 act_role->client_cnt = wl_linfo[i].client_cnt; 6422 } else { 6423 act_role->client_cnt = 0; 6424 } 6425 6426 if (act_role->noa && act_role->noa_dur > 0) 6427 noa_duration = act_role->noa_dur; 6428 6429 if (rtwdev->dbcc_en) { 6430 phy_dbcc = wl_linfo[i].phy; 6431 wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role); 6432 wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band; 6433 } 6434 6435 if (wl_linfo[i].chdef.band != RTW89_BAND_2G) { 6436 cnt_5g++; 6437 b5g = true; 6438 } else { 6439 if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6440 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 6441 client_joined) || 6442 wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT) 6443 wl_rinfo->p2p_2g = 1; 6444 6445 if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) || 6446 (wl_linfo[i].mode & BIT(BTC_WL_MODE_11G))) 6447 wl->bg_mode = 1; 6448 else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE)) 6449 wl->he_mode = true; 6450 6451 cnt_2g++; 6452 b2g = true; 6453 } 6454 6455 if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100) 6456 wl->is_5g_hi_channel = 1; 6457 else 6458 wl->is_5g_hi_channel = 0; 6459 } 6460 6461 wl_rinfo->connect_cnt = cnt; 6462 wl->client_cnt_inc_2g = client_inc_2g; 6463 6464 if (cnt == 0) { 6465 mode = BTC_WLINK_NOLINK; 6466 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE); 6467 } else if (!b2g && b5g) { 6468 mode = BTC_WLINK_5G; 6469 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) { 6470 mode = BTC_WLINK_2G_NAN; 6471 } else if (cnt > BTC_TDMA_WLROLE_MAX) { 6472 mode = BTC_WLINK_OTHER; 6473 } else if (rtwdev->dbcc_en) { 6474 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, &dbcc_2g_phy); 6475 6476 /* correct 2G-located PHY band for gnt ctrl */ 6477 if (dbcc_2g_phy < RTW89_PHY_NUM) 6478 wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G; 6479 } else if (b2g && b5g && cnt == 2) { 6480 mode = BTC_WLINK_25G_MCC; 6481 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */ 6482 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1])) 6483 mode = BTC_WLINK_2G_SCC; 6484 else 6485 mode = BTC_WLINK_2G_MCC; 6486 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */ 6487 mode = _get_role_link_mode(cid_role[0]); 6488 } else { 6489 mode = BTC_WLINK_NOLINK; 6490 } 6491 6492 wl_rinfo->link_mode = mode; 6493 _update_role_link_mode(rtwdev, client_joined, noa_duration); 6494 6495 /* todo DBCC related event */ 6496 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now); 6497 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6498 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g); 6499 6500 if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) { 6501 wl_rinfo->dbcc_chg = 1; 6502 wl_rinfo->dbcc_en = rtwdev->dbcc_en; 6503 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++; 6504 } 6505 6506 if (rtwdev->dbcc_en) { 6507 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy; 6508 6509 if (dbcc_2g_phy == RTW89_PHY_1) 6510 mac = RTW89_MAC_1; 6511 6512 _update_dbcc_band(rtwdev, RTW89_PHY_0); 6513 _update_dbcc_band(rtwdev, RTW89_PHY_1); 6514 } 6515 _wl_req_mac(rtwdev, mac); 6516 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6517 } 6518 6519 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id, 6520 enum btc_role_state state) 6521 { 6522 struct rtw89_btc *btc = &rtwdev->btc; 6523 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6524 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER]; 6525 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 6526 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6527 bool client_joined = false, b2g = false, b5g = false; 6528 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6529 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6530 u8 dbcc_en = 0, pta_req_band = RTW89_MAC_0; 6531 u8 i, j, cnt = 0, cnt_2g = 0, cnt_5g = 0; 6532 struct rtw89_btc_wl_link_info *wl_linfo; 6533 struct rtw89_btc_wl_rlink *rlink = NULL; 6534 u8 dbcc_2g_phy = RTW89_PHY_0; 6535 u8 mode = BTC_WLINK_NOLINK; 6536 u32 noa_dur = 0; 6537 6538 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id > RTW89_MAC_1) 6539 return; 6540 6541 /* Extract wl->link_info[role_id][rlink_id] to wl->role_info 6542 * role_id: role index 6543 * rlink_id: rlink index (= HW-band index) 6544 * pid: port_index 6545 */ 6546 6547 wl_linfo = &wl->rlink_info[role_id][rlink_id]; 6548 if (wl_linfo->connected == MLME_LINKING) 6549 return; 6550 6551 rlink = &wl_rinfo->rlink[role_id][rlink_id]; 6552 rlink->role = wl_linfo->role; 6553 rlink->active = wl_linfo->active; /* Doze or not */ 6554 rlink->pid = wl_linfo->pid; 6555 rlink->phy = wl_linfo->phy; 6556 rlink->rf_band = wl_linfo->band; 6557 rlink->ch = wl_linfo->ch; 6558 rlink->bw = wl_linfo->bw; 6559 rlink->noa = wl_linfo->noa; 6560 rlink->noa_dur = wl_linfo->noa_duration / 1000; 6561 rlink->client_cnt = wl_linfo->client_cnt; 6562 rlink->mode = wl_linfo->mode; 6563 6564 switch (wl_linfo->connected) { 6565 case MLME_NO_LINK: 6566 rlink->connected = 0; 6567 if (rlink->role == RTW89_WIFI_ROLE_STATION) 6568 btc->dm.leak_ap = 0; 6569 break; 6570 case MLME_LINKED: 6571 rlink->connected = 1; 6572 break; 6573 default: 6574 return; 6575 } 6576 6577 wl->is_5g_hi_channel = false; 6578 wl->bg_mode = false; 6579 wl_rinfo->role_map = 0; 6580 wl_rinfo->p2p_2g = 0; 6581 memset(cid_ch, 0, sizeof(cid_ch)); 6582 6583 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 6584 for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) { 6585 rlink = &wl_rinfo->rlink[i][j]; 6586 6587 if (!rlink->active || !rlink->connected) 6588 continue; 6589 6590 cnt++; 6591 wl_rinfo->role_map |= BIT(rlink->role); 6592 6593 /* only if client connect for p2p-Go/AP */ 6594 if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO || 6595 rlink->role == RTW89_WIFI_ROLE_AP) && 6596 rlink->client_cnt > 1) 6597 client_joined = true; 6598 6599 /* Identufy if P2P-Go (GO/GC/AP) exist at 2G band*/ 6600 if (rlink->rf_band == RTW89_BAND_2G && 6601 (client_joined || rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) 6602 wl_rinfo->p2p_2g = 1; 6603 6604 /* only one noa-role exist */ 6605 if (rlink->noa && rlink->noa_dur > 0) 6606 noa_dur = rlink->noa_dur; 6607 6608 /* for WL 5G-Rx interfered with BT issue */ 6609 if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100) 6610 wl->is_5g_hi_channel = 1; 6611 6612 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) || 6613 (rlink->mode & BIT(BTC_WL_MODE_11G))) 6614 wl->bg_mode = 1; 6615 6616 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) 6617 continue; 6618 6619 cid_ch[cnt - 1] = wl_linfo->chdef; 6620 cid_phy[cnt - 1] = rlink->phy; 6621 cid_role[cnt - 1] = rlink->role; 6622 6623 if (rlink->rf_band != RTW89_BAND_2G) { 6624 cnt_5g++; 6625 b5g = true; 6626 } else { 6627 cnt_2g++; 6628 b2g = true; 6629 } 6630 } 6631 } 6632 6633 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { 6634 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6635 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g); 6636 rtw89_warn(rtwdev, "not support MLO feature yet"); 6637 } else { 6638 dbcc_en = rtwdev->dbcc_en; 6639 6640 /* Be careful to change the following sequence!! */ 6641 if (cnt == 0) { 6642 mode = BTC_WLINK_NOLINK; 6643 } else if (!b2g && b5g) { 6644 mode = BTC_WLINK_5G; 6645 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) { 6646 mode = BTC_WLINK_2G_NAN; 6647 } else if (cnt > BTC_TDMA_WLROLE_MAX) { 6648 mode = BTC_WLINK_OTHER; 6649 } else if (dbcc_en) { 6650 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, 6651 &dbcc_2g_phy); 6652 } else if (b2g && b5g && cnt == 2) { 6653 mode = BTC_WLINK_25G_MCC; 6654 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */ 6655 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1])) 6656 mode = BTC_WLINK_2G_SCC; 6657 else 6658 mode = BTC_WLINK_2G_MCC; 6659 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */ 6660 mode = _get_role_link_mode(cid_role[0]); 6661 } 6662 } 6663 6664 wl_rinfo->link_mode = mode; 6665 wl_rinfo->connect_cnt = cnt; 6666 if (wl_rinfo->connect_cnt == 0) 6667 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE); 6668 _update_role_link_mode(rtwdev, client_joined, noa_dur); 6669 6670 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy; 6671 if (wl_rinfo->dbcc_en != dbcc_en) { 6672 wl_rinfo->dbcc_en = dbcc_en; 6673 wl_rinfo->dbcc_chg = 1; 6674 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++; 6675 } else { 6676 wl_rinfo->dbcc_chg = 0; 6677 } 6678 6679 if (wl_rinfo->dbcc_en) { 6680 memset(wl_dinfo, 0, sizeof(struct rtw89_btc_wl_dbcc_info)); 6681 6682 if (mode == BTC_WLINK_5G) { 6683 pta_req_band = RTW89_PHY_0; 6684 wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G; 6685 wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G; 6686 } else if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_1) { 6687 pta_req_band = RTW89_PHY_1; 6688 wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G; 6689 wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G; 6690 } else { 6691 pta_req_band = RTW89_PHY_0; 6692 wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_2G; 6693 wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_5G; 6694 } 6695 _update_dbcc_band(rtwdev, RTW89_PHY_0); 6696 _update_dbcc_band(rtwdev, RTW89_PHY_1); 6697 } 6698 6699 wl_rinfo->pta_req_band = pta_req_band; 6700 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6701 } 6702 6703 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work) 6704 { 6705 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 6706 coex_act1_work.work); 6707 struct rtw89_btc *btc = &rtwdev->btc; 6708 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 6709 struct rtw89_btc_cx *cx = &btc->cx; 6710 struct rtw89_btc_wl_info *wl = &cx->wl; 6711 6712 lockdep_assert_wiphy(wiphy); 6713 6714 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 6715 dm->cnt_notify[BTC_NCNT_TIMER]++; 6716 if (wl->status.map._4way) 6717 wl->status.map._4way = false; 6718 if (wl->status.map.connecting) 6719 wl->status.map.connecting = false; 6720 6721 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 6722 } 6723 6724 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work) 6725 { 6726 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 6727 coex_bt_devinfo_work.work); 6728 struct rtw89_btc *btc = &rtwdev->btc; 6729 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 6730 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 6731 6732 lockdep_assert_wiphy(wiphy); 6733 6734 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 6735 dm->cnt_notify[BTC_NCNT_TIMER]++; 6736 a2dp->play_latency = 0; 6737 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 6738 } 6739 6740 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work) 6741 { 6742 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 6743 coex_rfk_chk_work.work); 6744 struct rtw89_btc *btc = &rtwdev->btc; 6745 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 6746 struct rtw89_btc_cx *cx = &btc->cx; 6747 struct rtw89_btc_wl_info *wl = &cx->wl; 6748 6749 lockdep_assert_wiphy(wiphy); 6750 6751 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 6752 dm->cnt_notify[BTC_NCNT_TIMER]++; 6753 if (wl->rfk_info.state != BTC_WRFK_STOP) { 6754 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6755 "[BTC], %s(): RFK timeout\n", __func__); 6756 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++; 6757 dm->error.map.wl_rfk_timeout = true; 6758 wl->rfk_info.state = BTC_WRFK_STOP; 6759 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 6760 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 6761 } 6762 } 6763 6764 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) 6765 { 6766 const struct rtw89_chip_info *chip = rtwdev->chip; 6767 struct rtw89_btc *btc = &rtwdev->btc; 6768 struct rtw89_btc_cx *cx = &btc->cx; 6769 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6770 u32 val; 6771 bool status_change = false; 6772 6773 if (!chip->scbd) 6774 return; 6775 6776 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 6777 6778 val = _read_scbd(rtwdev); 6779 if (val == BTC_SCB_INV_VALUE) { 6780 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6781 "[BTC], %s(): return by invalid scbd value\n", 6782 __func__); 6783 return; 6784 } 6785 6786 if (!(val & BTC_BSCB_ON)) 6787 bt->enable.now = 0; 6788 else 6789 bt->enable.now = 1; 6790 6791 if (bt->enable.now != bt->enable.last) 6792 status_change = true; 6793 6794 /* reset bt info if bt re-enable */ 6795 if (bt->enable.now && !bt->enable.last) { 6796 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 6797 cx->cnt_bt[BTC_BCNT_REENABLE]++; 6798 bt->enable.now = 1; 6799 } 6800 6801 bt->enable.last = bt->enable.now; 6802 bt->scbd = val; 6803 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 6804 6805 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 6806 status_change = true; 6807 6808 bt->whql_test = !!(val & BTC_BSCB_WHQL); 6809 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE; 6810 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT); 6811 6812 bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) + 6813 !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4; 6814 6815 /* if rfk run 1->0 */ 6816 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN)) 6817 status_change = true; 6818 6819 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN); 6820 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); 6821 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 6822 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); 6823 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 6824 6825 if (!only_update && status_change) 6826 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 6827 } 6828 6829 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) 6830 { 6831 struct rtw89_btc *btc = &rtwdev->btc; 6832 struct rtw89_btc_cx *cx = &btc->cx; 6833 struct rtw89_btc_bt_info *bt = &cx->bt; 6834 6835 _update_bt_scbd(rtwdev, true); 6836 6837 cx->cnt_wl[BTC_WCNT_RFK_REQ]++; 6838 6839 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) && 6840 !bt->rfk_info.map.timeout) { 6841 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++; 6842 } else { 6843 cx->cnt_wl[BTC_WCNT_RFK_GO]++; 6844 return true; 6845 } 6846 return false; 6847 } 6848 6849 static 6850 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 6851 { 6852 struct rtw89_btc *btc = &rtwdev->btc; 6853 const struct rtw89_btc_ver *ver = btc->ver; 6854 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 6855 struct rtw89_btc_cx *cx = &btc->cx; 6856 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6857 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6858 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6859 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 6860 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 6861 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 6862 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 6863 u8 mode, igno_bt, always_freerun; 6864 6865 lockdep_assert_wiphy(rtwdev->hw->wiphy); 6866 6867 dm->run_reason = reason; 6868 _update_dm_step(rtwdev, reason); 6869 _update_btc_state_map(rtwdev); 6870 6871 if (ver->fwlrole == 0) 6872 mode = wl_rinfo->link_mode; 6873 else if (ver->fwlrole == 1) 6874 mode = wl_rinfo_v1->link_mode; 6875 else if (ver->fwlrole == 2) 6876 mode = wl_rinfo_v2->link_mode; 6877 else if (ver->fwlrole == 7) 6878 mode = wl_rinfo_v7->link_mode; 6879 else if (ver->fwlrole == 8) 6880 mode = wl_rinfo_v8->link_mode; 6881 else 6882 return; 6883 6884 if (ver->fcxctrl == 7) { 6885 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 6886 always_freerun = btc->ctrl.ctrl_v7.always_freerun; 6887 } else { 6888 igno_bt = btc->ctrl.ctrl.igno_bt; 6889 always_freerun = btc->ctrl.ctrl.always_freerun; 6890 } 6891 6892 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 6893 __func__, reason, mode); 6894 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 6895 __func__, dm->wl_only, dm->bt_only); 6896 6897 /* Be careful to change the following function sequence!! */ 6898 if (btc->manual_ctrl) { 6899 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6900 "[BTC], %s(): return for Manual CTRL!!\n", 6901 __func__); 6902 return; 6903 } 6904 6905 if (igno_bt && 6906 (reason == BTC_RSN_UPDATE_BT_INFO || 6907 reason == BTC_RSN_UPDATE_BT_SCBD)) { 6908 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6909 "[BTC], %s(): return for Stop Coex DM!!\n", 6910 __func__); 6911 return; 6912 } 6913 6914 if (!wl->status.map.init_ok) { 6915 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6916 "[BTC], %s(): return for WL init fail!!\n", 6917 __func__); 6918 return; 6919 } 6920 6921 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 6922 wl->status.map.lps_pre == wl->status.map.lps) { 6923 if (reason == BTC_RSN_NTFY_POWEROFF || 6924 reason == BTC_RSN_NTFY_RADIO_STATE) { 6925 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6926 "[BTC], %s(): return for WL rf off state no change!!\n", 6927 __func__); 6928 return; 6929 } 6930 if (wl->status.map.rf_off == 1 || 6931 wl->status.map.lps == BTC_LPS_RF_OFF) { 6932 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6933 "[BTC], %s(): return for WL rf off state!!\n", 6934 __func__); 6935 return; 6936 } 6937 } 6938 6939 dm->freerun = false; 6940 dm->cnt_dm[BTC_DCNT_RUN]++; 6941 dm->fddt_train = BTC_FDDT_DISABLE; 6942 bt->scan_rx_low_pri = false; 6943 igno_bt = false; 6944 6945 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ 6946 6947 if (always_freerun) { 6948 _action_freerun(rtwdev); 6949 igno_bt = true; 6950 goto exit; 6951 } 6952 6953 if (dm->wl_only) { 6954 _action_wl_only(rtwdev); 6955 igno_bt = true; 6956 goto exit; 6957 } 6958 6959 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) { 6960 _action_wl_off(rtwdev, mode); 6961 igno_bt = true; 6962 goto exit; 6963 } 6964 6965 if (reason == BTC_RSN_NTFY_INIT) { 6966 _action_wl_init(rtwdev); 6967 goto exit; 6968 } 6969 6970 if (!cx->bt.enable.now && !cx->other.type) { 6971 _action_bt_off(rtwdev); 6972 goto exit; 6973 } 6974 6975 if (cx->bt.whql_test) { 6976 _action_bt_whql(rtwdev); 6977 goto exit; 6978 } 6979 6980 if (wl->rfk_info.state != BTC_WRFK_STOP) { 6981 _action_wl_rfk(rtwdev); 6982 goto exit; 6983 } 6984 6985 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) { 6986 _action_wl_scan(rtwdev); 6987 bt->scan_rx_low_pri = true; 6988 goto exit; 6989 } 6990 6991 switch (mode) { 6992 case BTC_WLINK_NOLINK: 6993 _action_wl_nc(rtwdev); 6994 break; 6995 case BTC_WLINK_2G_STA: 6996 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 6997 bt->scan_rx_low_pri = true; 6998 _action_wl_2g_sta(rtwdev); 6999 break; 7000 case BTC_WLINK_2G_AP: 7001 bt->scan_rx_low_pri = true; 7002 _action_wl_2g_ap(rtwdev); 7003 break; 7004 case BTC_WLINK_2G_GO: 7005 bt->scan_rx_low_pri = true; 7006 _action_wl_2g_go(rtwdev); 7007 break; 7008 case BTC_WLINK_2G_GC: 7009 bt->scan_rx_low_pri = true; 7010 _action_wl_2g_gc(rtwdev); 7011 break; 7012 case BTC_WLINK_2G_SCC: 7013 bt->scan_rx_low_pri = true; 7014 if (ver->fwlrole == 0) 7015 _action_wl_2g_scc(rtwdev); 7016 else if (ver->fwlrole == 1) 7017 _action_wl_2g_scc_v1(rtwdev); 7018 else if (ver->fwlrole == 2 || ver->fwlrole == 7) 7019 _action_wl_2g_scc_v2(rtwdev); 7020 else if (ver->fwlrole == 8) 7021 _action_wl_2g_scc_v8(rtwdev); 7022 break; 7023 case BTC_WLINK_2G_MCC: 7024 bt->scan_rx_low_pri = true; 7025 _action_wl_2g_mcc(rtwdev); 7026 break; 7027 case BTC_WLINK_25G_MCC: 7028 bt->scan_rx_low_pri = true; 7029 _action_wl_25g_mcc(rtwdev); 7030 break; 7031 case BTC_WLINK_5G: 7032 _action_wl_5g(rtwdev); 7033 break; 7034 case BTC_WLINK_2G_NAN: 7035 _action_wl_2g_nan(rtwdev); 7036 break; 7037 default: 7038 _action_wl_other(rtwdev); 7039 break; 7040 } 7041 7042 exit: 7043 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 7044 if (ver->fcxctrl == 7) 7045 btc->ctrl.ctrl_v7.igno_bt = igno_bt; 7046 else 7047 btc->ctrl.ctrl.igno_bt = igno_bt; 7048 _action_common(rtwdev); 7049 } 7050 7051 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 7052 { 7053 struct rtw89_btc *btc = &rtwdev->btc; 7054 7055 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 7056 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 7057 } 7058 7059 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 7060 { 7061 struct rtw89_btc *btc = &rtwdev->btc; 7062 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7063 7064 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 7065 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 7066 7067 btc->cx.wl.status.map.rf_off = 1; 7068 btc->cx.wl.status.map.busy = 0; 7069 wl->status.map.lps = BTC_LPS_OFF; 7070 7071 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 7072 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 7073 7074 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 7075 7076 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 7077 } 7078 7079 static void _set_init_info(struct rtw89_dev *rtwdev) 7080 { 7081 const struct rtw89_chip_info *chip = rtwdev->chip; 7082 struct rtw89_btc *btc = &rtwdev->btc; 7083 const struct rtw89_btc_ver *ver = btc->ver; 7084 struct rtw89_btc_dm *dm = &btc->dm; 7085 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7086 7087 if (ver->fcxinit == 7) { 7088 dm->init_info.init_v7.wl_only = (u8)dm->wl_only; 7089 dm->init_info.init_v7.bt_only = (u8)dm->bt_only; 7090 dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok; 7091 dm->init_info.init_v7.cx_other = btc->cx.other.type; 7092 dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch; 7093 dm->init_info.init_v7.module = btc->mdinfo.md_v7; 7094 } else { 7095 dm->init_info.init.wl_only = (u8)dm->wl_only; 7096 dm->init_info.init.bt_only = (u8)dm->bt_only; 7097 dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok; 7098 dm->init_info.init.dbcc_en = rtwdev->dbcc_en; 7099 dm->init_info.init.cx_other = btc->cx.other.type; 7100 dm->init_info.init.wl_guard_ch = chip->afh_guard_ch; 7101 dm->init_info.init.module = btc->mdinfo.md; 7102 } 7103 } 7104 7105 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 7106 { 7107 struct rtw89_btc *btc = &rtwdev->btc; 7108 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7109 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7110 const struct rtw89_chip_info *chip = rtwdev->chip; 7111 const struct rtw89_btc_ver *ver = btc->ver; 7112 7113 _reset_btc_var(rtwdev, BTC_RESET_ALL); 7114 btc->dm.run_reason = BTC_RSN_NONE; 7115 btc->dm.run_action = BTC_ACT_NONE; 7116 if (ver->fcxctrl == 7) 7117 btc->ctrl.ctrl_v7.igno_bt = true; 7118 else 7119 btc->ctrl.ctrl.igno_bt = true; 7120 7121 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7122 "[BTC], %s(): mode=%d\n", __func__, mode); 7123 7124 wl->coex_mode = mode; 7125 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 7126 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 7127 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 7128 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 7129 7130 chip->ops->btc_set_rfe(rtwdev); 7131 chip->ops->btc_init_cfg(rtwdev); 7132 7133 if (!wl->status.map.init_ok) { 7134 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7135 "[BTC], %s(): return for WL init fail!!\n", 7136 __func__); 7137 dm->error.map.init = true; 7138 return; 7139 } 7140 7141 _write_scbd(rtwdev, 7142 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 7143 _update_bt_scbd(rtwdev, true); 7144 if (rtw89_mac_get_ctrl_path(rtwdev)) { 7145 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7146 "[BTC], %s(): PTA owner warning!!\n", 7147 __func__); 7148 dm->error.map.pta_owner = true; 7149 } 7150 7151 _set_init_info(rtwdev); 7152 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR); 7153 btc_fw_set_monreg(rtwdev); 7154 rtw89_btc_fw_set_slots(rtwdev); 7155 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 7156 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 7157 7158 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 7159 } 7160 7161 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 7162 { 7163 struct rtw89_btc *btc = &rtwdev->btc; 7164 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7165 7166 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7167 "[BTC], %s(): phy_idx=%d, band=%d\n", 7168 __func__, phy_idx, band); 7169 7170 if (phy_idx >= RTW89_PHY_NUM) 7171 return; 7172 7173 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 7174 wl->status.map.scan = true; 7175 wl->scan_info.band[phy_idx] = band; 7176 wl->scan_info.phy_map |= BIT(phy_idx); 7177 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 7178 7179 if (rtwdev->dbcc_en) { 7180 wl->dbcc_info.scan_band[phy_idx] = band; 7181 _update_dbcc_band(rtwdev, phy_idx); 7182 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 7183 } 7184 7185 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 7186 } 7187 7188 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 7189 { 7190 struct rtw89_btc *btc = &rtwdev->btc; 7191 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7192 7193 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7194 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 7195 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 7196 7197 wl->status.map.scan = false; 7198 wl->scan_info.phy_map &= ~BIT(phy_idx); 7199 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 7200 7201 if (rtwdev->dbcc_en) { 7202 _update_dbcc_band(rtwdev, phy_idx); 7203 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 7204 } 7205 7206 btc->dm.tdma_instant_excute = 1; 7207 7208 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 7209 } 7210 7211 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 7212 { 7213 struct rtw89_btc *btc = &rtwdev->btc; 7214 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7215 7216 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7217 "[BTC], %s(): phy_idx=%d, band=%d\n", 7218 __func__, phy_idx, band); 7219 7220 if (phy_idx >= RTW89_PHY_NUM) 7221 return; 7222 7223 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 7224 7225 if (rtwdev->dbcc_en) { 7226 wl->dbcc_info.scan_band[phy_idx] = band; 7227 _update_dbcc_band(rtwdev, phy_idx); 7228 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 7229 } 7230 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 7231 } 7232 7233 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 7234 enum btc_pkt_type pkt_type) 7235 { 7236 struct rtw89_btc *btc = &rtwdev->btc; 7237 struct rtw89_btc_cx *cx = &btc->cx; 7238 struct rtw89_btc_wl_info *wl = &cx->wl; 7239 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info; 7240 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 7241 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 7242 u32 cnt; 7243 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 7244 bool delay_work = false; 7245 7246 switch (pkt_type) { 7247 case PACKET_DHCP: 7248 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP]; 7249 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7250 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 7251 wl->status.map.connecting = true; 7252 delay_work = true; 7253 break; 7254 case PACKET_EAPOL: 7255 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 7256 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7257 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 7258 wl->status.map._4way = true; 7259 delay_work = true; 7260 if (hfp->exist || hid->exist) 7261 delay /= 2; 7262 break; 7263 case PACKET_EAPOL_END: 7264 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 7265 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7266 "[BTC], %s(): EAPOL_End cnt=%d\n", 7267 __func__, cnt); 7268 wl->status.map._4way = false; 7269 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 7270 break; 7271 case PACKET_ARP: 7272 cnt = ++cx->cnt_wl[BTC_WCNT_ARP]; 7273 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7274 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 7275 return; 7276 case PACKET_ICMP: 7277 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7278 "[BTC], %s(): ICMP pkt\n", __func__); 7279 return; 7280 default: 7281 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7282 "[BTC], %s(): unknown packet type %d\n", 7283 __func__, pkt_type); 7284 return; 7285 } 7286 7287 if (delay_work) { 7288 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 7289 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 7290 &rtwdev->coex_act1_work, delay); 7291 } 7292 7293 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 7294 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 7295 } 7296 7297 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7298 { 7299 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7300 btc.eapol_notify_work); 7301 7302 lockdep_assert_wiphy(wiphy); 7303 7304 rtw89_leave_ps_mode(rtwdev); 7305 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 7306 } 7307 7308 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7309 { 7310 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7311 btc.arp_notify_work); 7312 7313 lockdep_assert_wiphy(wiphy); 7314 7315 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 7316 } 7317 7318 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7319 { 7320 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7321 btc.dhcp_notify_work); 7322 7323 lockdep_assert_wiphy(wiphy); 7324 7325 rtw89_leave_ps_mode(rtwdev); 7326 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 7327 } 7328 7329 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7330 { 7331 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7332 btc.icmp_notify_work); 7333 7334 lockdep_assert_wiphy(wiphy); 7335 7336 rtw89_leave_ps_mode(rtwdev); 7337 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 7338 } 7339 7340 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi) 7341 { 7342 const struct rtw89_chip_info *chip = rtwdev->chip; 7343 struct rtw89_btc *btc = &rtwdev->btc; 7344 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7345 u8 *rssi_st, rssi_th, rssi_level = 0; 7346 u8 i; 7347 7348 /* for rssi locate in which {40, 36, 31, 28} 7349 * if rssi >= 40% (-60dBm) --> rssi_level = 4 7350 * if 36% <= rssi < 40% --> rssi_level = 3 7351 * if 31% <= rssi < 36% --> rssi_level = 2 7352 * if 28% <= rssi < 31% --> rssi_level = 1 7353 * if rssi < 28% --> rssi_level = 0 7354 */ 7355 7356 /* check if rssi across bt_rssi_thres boundary */ 7357 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) { 7358 rssi_th = chip->bt_rssi_thres[i]; 7359 rssi_st = &bt->link_info.rssi_state[i]; 7360 7361 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th); 7362 7363 if (BTC_RSSI_HIGH(*rssi_st)) { 7364 rssi_level = BTC_BT_RSSI_THMAX - i; 7365 break; 7366 } 7367 } 7368 return rssi_level; 7369 } 7370 7371 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev) 7372 { 7373 u8 mode = rtwdev->btc.cx.wl.role_info.link_mode; 7374 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a; 7375 7376 if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) { 7377 zb_tbl0 = 0xffffffff; 7378 zb_tbl1 = 0xffffffff; 7379 } else if (mode == BTC_WLINK_25G_MCC) { 7380 zb_tbl0 = 0xffffffff; /* for E5G slot */ 7381 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */ 7382 } 7383 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0); 7384 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1); 7385 } 7386 7387 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4) 7388 7389 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 7390 { 7391 const struct rtw89_chip_info *chip = rtwdev->chip; 7392 struct rtw89_btc *btc = &rtwdev->btc; 7393 struct rtw89_btc_cx *cx = &btc->cx; 7394 struct rtw89_btc_bt_info *bt = &cx->bt; 7395 struct rtw89_btc_bt_link_info *b = &bt->link_info; 7396 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 7397 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 7398 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 7399 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 7400 union btc_btinfo btinfo; 7401 7402 if (buf[BTC_BTINFO_L1] != 6) 7403 return; 7404 7405 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) { 7406 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7407 "[BTC], %s(): return by bt-info duplicate!!\n", 7408 __func__); 7409 cx->cnt_bt[BTC_BCNT_INFOSAME]++; 7410 return; 7411 } 7412 7413 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX); 7414 7415 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7416 "[BTC], %s(): bt_info[2]=0x%02x\n", 7417 __func__, bt->raw_info[2]); 7418 7419 b->profile_cnt.last = b->profile_cnt.now; 7420 b->profile_cnt.now = 0; 7421 hid->type = 0; 7422 7423 /* parse raw info low-Byte2 */ 7424 btinfo.val = bt->raw_info[BTC_BTINFO_L2]; 7425 b->status.map.connect = btinfo.lb2.connect; 7426 b->status.map.sco_busy = btinfo.lb2.sco_busy; 7427 b->status.map.acl_busy = btinfo.lb2.acl_busy; 7428 b->status.map.inq_pag = btinfo.lb2.inq_pag; 7429 bt->inq_pag.now = btinfo.lb2.inq_pag; 7430 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 7431 7432 hfp->exist = btinfo.lb2.hfp; 7433 b->profile_cnt.now += (u8)hfp->exist; 7434 hid->exist = btinfo.lb2.hid; 7435 b->profile_cnt.now += (u8)hid->exist; 7436 a2dp->exist = btinfo.lb2.a2dp; 7437 b->profile_cnt.now += (u8)a2dp->exist; 7438 pan->exist = btinfo.lb2.pan; 7439 b->profile_cnt.now += (u8)pan->exist; 7440 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 7441 7442 /* parse raw info low-Byte3 */ 7443 btinfo.val = bt->raw_info[BTC_BTINFO_L3]; 7444 if (btinfo.lb3.retry != 0) 7445 cx->cnt_bt[BTC_BCNT_RETRY]++; 7446 b->cqddr = btinfo.lb3.cqddr; 7447 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 7448 bt->inq = btinfo.lb3.inq; 7449 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 7450 bt->pag = btinfo.lb3.pag; 7451 7452 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 7453 /* parse raw info high-Byte0 */ 7454 btinfo.val = bt->raw_info[BTC_BTINFO_H0]; 7455 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 7456 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 7457 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi); 7458 btc->dm.trx_info.bt_rssi = bt->rssi_level; 7459 7460 /* parse raw info high-Byte1 */ 7461 btinfo.val = bt->raw_info[BTC_BTINFO_H1]; 7462 b->status.map.ble_connect = btinfo.hb1.ble_connect; 7463 if (btinfo.hb1.ble_connect) { 7464 if (hid->exist) 7465 hid->type |= BTC_HID_BLE; 7466 else if (btinfo.hb1.voice) 7467 hid->type |= BTC_HID_RCU_VOICE; 7468 else 7469 hid->type |= BTC_HID_RCU; 7470 } 7471 7472 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 7473 bt->reinit = btinfo.hb1.reinit; 7474 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 7475 b->relink.now = btinfo.hb1.relink; 7476 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 7477 bt->igno_wl = btinfo.hb1.igno_wl; 7478 7479 if (bt->igno_wl && !cx->wl.status.map.rf_off) 7480 _set_bt_ignore_wlan_act(rtwdev, false); 7481 7482 bt->ble_scan_en = btinfo.hb1.ble_scan; 7483 7484 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 7485 b->role_sw = btinfo.hb1.role_sw; 7486 7487 b->multi_link.now = btinfo.hb1.multi_link; 7488 7489 /* parse raw info high-Byte2 */ 7490 btinfo.val = bt->raw_info[BTC_BTINFO_H2]; 7491 pan->active = !!btinfo.hb2.pan_active; 7492 7493 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 7494 b->afh_update = btinfo.hb2.afh_update; 7495 a2dp->active = btinfo.hb2.a2dp_active; 7496 b->slave_role = btinfo.hb2.slave; 7497 hid->slot_info = btinfo.hb2.hid_slot; 7498 hid->pair_cnt = btinfo.hb2.hid_cnt; 7499 if (!b->status.map.ble_connect || hid->pair_cnt > 1) 7500 hid->type |= (hid->slot_info == BTC_HID_218 ? 7501 BTC_HID_218 : BTC_HID_418); 7502 /* parse raw info high-Byte3 */ 7503 btinfo.val = bt->raw_info[BTC_BTINFO_H3]; 7504 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 7505 7506 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 7507 cx->cnt_bt[BTC_BCNT_RATECHG]++; 7508 b->tx_3m = (u32)btinfo.hb3.tx_3m; 7509 7510 a2dp->sink = btinfo.hb3.a2dp_sink; 7511 7512 if (!a2dp->exist_last && a2dp->exist) { 7513 a2dp->vendor_id = 0; 7514 a2dp->flush_time = 0; 7515 a2dp->play_latency = 1; 7516 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 7517 &rtwdev->coex_bt_devinfo_work, 7518 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 7519 } 7520 7521 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 7522 } 7523 7524 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, 7525 struct rtw89_vif_link *rtwvif_link, 7526 struct rtw89_sta_link *rtwsta_link, 7527 enum btc_role_state state) 7528 { 7529 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, 7530 rtwvif_link->chanctx_idx); 7531 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); 7532 struct ieee80211_bss_conf *bss_conf; 7533 struct ieee80211_link_sta *link_sta; 7534 struct rtw89_btc *btc = &rtwdev->btc; 7535 const struct rtw89_btc_ver *ver = btc->ver; 7536 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7537 struct rtw89_btc_wl_link_info r = {0}; 7538 struct rtw89_btc_wl_link_info *wlinfo = NULL; 7539 u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type; 7540 7541 rcu_read_lock(); 7542 7543 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); 7544 7545 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 7546 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7547 "[BTC], role is STA=%d\n", 7548 vif->type == NL80211_IFTYPE_STATION); 7549 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); 7550 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 7551 chan->band_type, chan->channel, chan->band_width); 7552 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 7553 state == BTC_ROLE_MSTS_STA_CONN_END); 7554 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7555 "[BTC], bcn_period=%d dtim_period=%d\n", 7556 bss_conf->beacon_int, bss_conf->dtim_period); 7557 7558 if (rtwsta_link) { 7559 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); 7560 7561 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 7562 rtwsta_link->mac_id); 7563 7564 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7565 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 7566 link_sta->he_cap.has_he, 7567 link_sta->vht_cap.vht_supported, 7568 link_sta->ht_cap.ht_supported); 7569 if (link_sta->he_cap.has_he) 7570 mode |= BIT(BTC_WL_MODE_HE); 7571 if (link_sta->vht_cap.vht_supported) 7572 mode |= BIT(BTC_WL_MODE_VHT); 7573 if (link_sta->ht_cap.ht_supported) 7574 mode |= BIT(BTC_WL_MODE_HT); 7575 7576 r.mode = mode; 7577 } 7578 7579 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { 7580 rcu_read_unlock(); 7581 return; 7582 } 7583 7584 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7585 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); 7586 7587 r.role = rtwvif_link->wifi_role; 7588 r.phy = rtwvif_link->phy_idx; 7589 r.pid = rtwvif_link->port; 7590 r.active = true; 7591 r.connected = MLME_LINKED; 7592 r.bcn_period = bss_conf->beacon_int; 7593 r.dtim_period = bss_conf->dtim_period; 7594 r.band = chan->band_type; 7595 r.ch = chan->channel; 7596 r.bw = chan->band_width; 7597 r.chdef.band = chan->band_type; 7598 r.chdef.center_ch = chan->channel; 7599 r.chdef.bw = chan->band_width; 7600 r.chdef.chan = chan->primary_channel; 7601 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); 7602 7603 rcu_read_unlock(); 7604 7605 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) 7606 r.mac_id = rtwsta_link->mac_id; 7607 7608 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 7609 7610 wlinfo = &wl->link_info[r.pid]; 7611 7612 rlink_id = 0; /* to do */ 7613 if (ver->fwlrole == 0) { 7614 *wlinfo = r; 7615 _update_wl_info(rtwdev); 7616 } else if (ver->fwlrole == 1) { 7617 *wlinfo = r; 7618 _update_wl_info_v1(rtwdev); 7619 } else if (ver->fwlrole == 2) { 7620 *wlinfo = r; 7621 _update_wl_info_v2(rtwdev); 7622 } else if (ver->fwlrole == 7) { 7623 *wlinfo = r; 7624 _update_wl_info_v7(rtwdev, r.pid); 7625 } else if (ver->fwlrole == 8) { 7626 wlinfo = &wl->rlink_info[r.pid][rlink_id]; 7627 *wlinfo = r; 7628 link_mode_ori = wl->role_info_v8.link_mode; 7629 pta_req_mac_ori = wl->pta_req_mac; 7630 _update_wl_info_v8(rtwdev, r.pid, rlink_id, state); 7631 7632 if (wl->role_info_v8.link_mode != link_mode_ori) { 7633 wl->role_info_v8.link_mode_chg = 1; 7634 if (ver->fcxinit == 7) 7635 wa_type = btc->mdinfo.md_v7.wa_type; 7636 else 7637 wa_type = btc->mdinfo.md.wa_type; 7638 7639 if (wa_type & BTC_WA_HFP_ZB) 7640 _update_zb_coex_tbl(rtwdev); 7641 } 7642 7643 if (wl->pta_req_mac != pta_req_mac_ori) 7644 wl->pta_reg_mac_chg = 1; 7645 } 7646 7647 if (wlinfo->role == RTW89_WIFI_ROLE_STATION && 7648 wlinfo->connected == MLME_NO_LINK) 7649 btc->dm.leak_ap = 0; 7650 7651 if (state == BTC_ROLE_MSTS_STA_CONN_START) 7652 wl->status.map.connecting = 1; 7653 else 7654 wl->status.map.connecting = 0; 7655 7656 if (state == BTC_ROLE_MSTS_STA_DIS_CONN || 7657 state == BTC_ROLE_MSTS_STA_CONN_END) 7658 wl->status.map._4way = false; 7659 7660 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 7661 } 7662 7663 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 7664 { 7665 const struct rtw89_chip_info *chip = rtwdev->chip; 7666 struct rtw89_btc *btc = &rtwdev->btc; 7667 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7668 u32 val; 7669 7670 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 7671 __func__, rf_state); 7672 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 7673 7674 switch (rf_state) { 7675 case BTC_RFCTRL_WL_OFF: 7676 wl->status.map.rf_off = 1; 7677 wl->status.map.lps = BTC_LPS_OFF; 7678 wl->status.map.busy = 0; 7679 break; 7680 case BTC_RFCTRL_FW_CTRL: 7681 wl->status.map.rf_off = 0; 7682 wl->status.map.lps = BTC_LPS_RF_OFF; 7683 wl->status.map.busy = 0; 7684 break; 7685 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */ 7686 wl->status.map.rf_off = 0; 7687 wl->status.map.lps = BTC_LPS_RF_ON; 7688 wl->status.map.busy = 0; 7689 break; 7690 case BTC_RFCTRL_WL_ON: 7691 default: 7692 wl->status.map.rf_off = 0; 7693 wl->status.map.lps = BTC_LPS_OFF; 7694 break; 7695 } 7696 7697 if (rf_state == BTC_RFCTRL_WL_ON) { 7698 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true); 7699 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 7700 _write_scbd(rtwdev, val, true); 7701 _update_bt_scbd(rtwdev, true); 7702 chip->ops->btc_init_cfg(rtwdev); 7703 } else { 7704 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false); 7705 if (rf_state == BTC_RFCTRL_FW_CTRL) 7706 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false); 7707 else if (rf_state == BTC_RFCTRL_WL_OFF) 7708 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 7709 else 7710 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false); 7711 7712 if (rf_state == BTC_RFCTRL_LPS_WL_ON && 7713 wl->status.map.lps_pre != BTC_LPS_OFF) 7714 _update_bt_scbd(rtwdev, true); 7715 } 7716 7717 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 7718 btc->dm.tdma_instant_excute = 1; 7719 7720 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 7721 wl->status.map.rf_off_pre = wl->status.map.rf_off; 7722 wl->status.map.lps_pre = wl->status.map.lps; 7723 } 7724 7725 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 7726 enum btc_wl_rfk_type type, 7727 enum btc_wl_rfk_state state) 7728 { 7729 struct rtw89_btc *btc = &rtwdev->btc; 7730 struct rtw89_btc_cx *cx = &btc->cx; 7731 struct rtw89_btc_wl_info *wl = &cx->wl; 7732 bool result = BTC_WRFK_REJECT; 7733 7734 wl->rfk_info.type = type; 7735 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 7736 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 7737 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 7738 7739 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7740 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 7741 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 7742 type, state); 7743 7744 switch (state) { 7745 case BTC_WRFK_START: 7746 result = _chk_wl_rfk_request(rtwdev); 7747 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP; 7748 7749 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result); 7750 7751 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 7752 break; 7753 case BTC_WRFK_ONESHOT_START: 7754 case BTC_WRFK_ONESHOT_STOP: 7755 if (wl->rfk_info.state == BTC_WRFK_STOP) { 7756 result = BTC_WRFK_REJECT; 7757 } else { 7758 result = BTC_WRFK_ALLOW; 7759 wl->rfk_info.state = state; 7760 } 7761 break; 7762 case BTC_WRFK_STOP: 7763 result = BTC_WRFK_ALLOW; 7764 wl->rfk_info.state = BTC_WRFK_STOP; 7765 7766 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 7767 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work); 7768 break; 7769 default: 7770 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7771 "[BTC], %s() warning state=%d\n", __func__, state); 7772 break; 7773 } 7774 7775 if (result == BTC_WRFK_ALLOW) { 7776 if (wl->rfk_info.state == BTC_WRFK_START || 7777 wl->rfk_info.state == BTC_WRFK_STOP) 7778 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 7779 7780 if (wl->rfk_info.state == BTC_WRFK_START) 7781 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 7782 &rtwdev->coex_rfk_chk_work, 7783 RTW89_COEX_RFK_CHK_WORK_PERIOD); 7784 } 7785 7786 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7787 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 7788 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 7789 7790 return result == BTC_WRFK_ALLOW; 7791 } 7792 7793 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 7794 enum btc_wl_rfk_type type, 7795 enum btc_wl_rfk_state state) 7796 { 7797 u8 band; 7798 bool allow; 7799 int ret; 7800 7801 lockdep_assert_wiphy(rtwdev->hw->wiphy); 7802 7803 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 7804 7805 rtw89_debug(rtwdev, RTW89_DBG_RFK, 7806 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 7807 band == RTW89_BAND_2G ? "2G" : 7808 band == RTW89_BAND_5G ? "5G" : "6G", 7809 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 7810 type, 7811 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 7812 state == BTC_WRFK_STOP ? "RFK_STOP" : 7813 state == BTC_WRFK_START ? "RFK_START" : 7814 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 7815 "ONE-SHOT_STOP"); 7816 7817 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 7818 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 7819 return; 7820 } 7821 7822 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 7823 rtwdev, phy_map, type, state); 7824 if (ret) { 7825 rtw89_warn(rtwdev, "RFK notify timeout\n"); 7826 rtwdev->is_bt_iqk_timeout = true; 7827 } 7828 } 7829 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 7830 7831 struct rtw89_btc_wl_sta_iter_data { 7832 struct rtw89_dev *rtwdev; 7833 u8 busy_all; 7834 u8 dir_all; 7835 u8 rssi_map_all; 7836 bool is_sta_change; 7837 bool is_traffic_change; 7838 }; 7839 7840 static 7841 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, 7842 struct rtw89_sta_link *rtwsta_link, 7843 struct rtw89_btc_wl_sta_iter_data *iter_data) 7844 { 7845 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 7846 struct rtw89_dev *rtwdev = iter_data->rtwdev; 7847 struct rtw89_btc *btc = &rtwdev->btc; 7848 struct rtw89_btc_dm *dm = &btc->dm; 7849 const struct rtw89_btc_ver *ver = btc->ver; 7850 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7851 struct rtw89_btc_wl_link_info *link_info = NULL; 7852 struct rtw89_traffic_stats *link_info_t = NULL; 7853 struct rtw89_traffic_stats *stats = &rtwvif->stats; 7854 const struct rtw89_chip_info *chip = rtwdev->chip; 7855 struct rtw89_btc_wl_role_info *r; 7856 struct rtw89_btc_wl_role_info_v1 *r1; 7857 u32 last_tx_rate, last_rx_rate; 7858 u16 last_tx_lvl, last_rx_lvl; 7859 u8 port = rtwvif_link->port; 7860 u8 rssi; 7861 u8 busy = 0; 7862 u8 dir = 0; 7863 u8 rssi_map = 0; 7864 u8 i = 0; 7865 bool is_sta_change = false, is_traffic_change = false; 7866 7867 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; 7868 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 7869 7870 link_info = &wl->link_info[port]; 7871 link_info->stat.traffic = *stats; 7872 link_info_t = &link_info->stat.traffic; 7873 7874 if (link_info->connected == MLME_NO_LINK) { 7875 link_info->rx_rate_drop_cnt = 0; 7876 return; 7877 } 7878 7879 link_info->stat.rssi = rssi; 7880 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 7881 link_info->rssi_state[i] = 7882 _update_rssi_state(rtwdev, 7883 link_info->rssi_state[i], 7884 link_info->stat.rssi, 7885 chip->wl_rssi_thres[i]); 7886 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 7887 rssi_map |= BIT(i); 7888 7889 if (btc->ant_type == BTC_ANT_DEDICATED && 7890 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 7891 is_sta_change = true; 7892 } 7893 iter_data->rssi_map_all |= rssi_map; 7894 7895 last_tx_rate = link_info_t->tx_rate; 7896 last_rx_rate = link_info_t->rx_rate; 7897 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 7898 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 7899 7900 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 7901 stats->rx_tfc_lv != RTW89_TFC_IDLE) 7902 busy = 1; 7903 7904 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 7905 dir = RTW89_TFC_UL; 7906 else 7907 dir = RTW89_TFC_DL; 7908 7909 link_info = &wl->link_info[port]; 7910 if (link_info->busy != busy || link_info->dir != dir) { 7911 is_sta_change = true; 7912 link_info->busy = busy; 7913 link_info->dir = dir; 7914 } 7915 7916 iter_data->busy_all |= busy; 7917 iter_data->dir_all |= BIT(dir); 7918 7919 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 7920 last_rx_rate > RTW89_HW_RATE_CCK2 && 7921 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 7922 link_info->rx_rate_drop_cnt++; 7923 7924 if (last_tx_rate != rtwsta_link->ra_report.hw_rate || 7925 last_rx_rate != rtwsta_link->rx_hw_rate || 7926 last_tx_lvl != link_info_t->tx_tfc_lv || 7927 last_rx_lvl != link_info_t->rx_tfc_lv) 7928 is_traffic_change = true; 7929 7930 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; 7931 link_info_t->rx_rate = rtwsta_link->rx_hw_rate; 7932 7933 if (link_info->role == RTW89_WIFI_ROLE_STATION || 7934 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { 7935 dm->trx_info.tx_rate = link_info_t->tx_rate; 7936 dm->trx_info.rx_rate = link_info_t->rx_rate; 7937 } 7938 7939 if (ver->fwlrole == 0) { 7940 r = &wl->role_info; 7941 r->active_role[port].tx_lvl = stats->tx_tfc_lv; 7942 r->active_role[port].rx_lvl = stats->rx_tfc_lv; 7943 r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate; 7944 r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate; 7945 } else if (ver->fwlrole == 1) { 7946 r1 = &wl->role_info_v1; 7947 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; 7948 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; 7949 r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate; 7950 r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate; 7951 } else if (ver->fwlrole == 2) { 7952 dm->trx_info.tx_lvl = stats->tx_tfc_lv; 7953 dm->trx_info.rx_lvl = stats->rx_tfc_lv; 7954 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; 7955 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; 7956 } 7957 7958 dm->trx_info.tx_tp = link_info_t->tx_throughput; 7959 dm->trx_info.rx_tp = link_info_t->rx_throughput; 7960 7961 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */ 7962 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx && 7963 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) || 7964 (dm->wl_pre_agc_rb != dm->wl_pre_agc && 7965 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND)) 7966 iter_data->is_sta_change = true; 7967 7968 if (is_sta_change) 7969 iter_data->is_sta_change = true; 7970 7971 if (is_traffic_change) 7972 iter_data->is_traffic_change = true; 7973 } 7974 7975 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 7976 { 7977 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 7978 struct rtw89_btc_wl_sta_iter_data *iter_data = 7979 (struct rtw89_btc_wl_sta_iter_data *)data; 7980 struct rtw89_vif_link *rtwvif_link; 7981 struct rtw89_sta_link *rtwsta_link; 7982 unsigned int link_id; 7983 7984 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 7985 rtwvif_link = rtwsta_link->rtwvif_link; 7986 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); 7987 } 7988 } 7989 7990 #define BTC_NHM_CHK_INTVL 20 7991 7992 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 7993 { 7994 struct rtw89_btc *btc = &rtwdev->btc; 7995 struct rtw89_btc_dm *dm = &btc->dm; 7996 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7997 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 7998 u8 i; 7999 8000 ieee80211_iterate_stations_atomic(rtwdev->hw, 8001 rtw89_btc_ntfy_wl_sta_iter, 8002 &data); 8003 8004 wl->rssi_level = 0; 8005 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 8006 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 8007 /* set RSSI level 4 ~ 0 if rssi bit map match */ 8008 if (data.rssi_map_all & BIT(i - 1)) { 8009 wl->rssi_level = i; 8010 break; 8011 } 8012 } 8013 8014 if (dm->trx_info.wl_rssi != wl->rssi_level) 8015 dm->trx_info.wl_rssi = wl->rssi_level; 8016 8017 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 8018 __func__, !!wl->status.map.busy); 8019 8020 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 8021 8022 if (data.is_traffic_change) 8023 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 8024 if (data.is_sta_change) { 8025 wl->status.map.busy = data.busy_all; 8026 wl->status.map.traffic_dir = data.dir_all; 8027 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 8028 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 8029 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 8030 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 8031 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 8032 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 8033 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 8034 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 8035 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 8036 } 8037 } 8038 8039 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) 8040 { 8041 struct rtw89_btc *btc = &rtwdev->btc; 8042 const struct rtw89_btc_ver *ver = btc->ver; 8043 8044 switch (func) { 8045 case BTF_EVNT_RPT: 8046 case BTF_EVNT_BT_INFO: 8047 case BTF_EVNT_BT_SCBD: 8048 case BTF_EVNT_BT_REG: 8049 case BTF_EVNT_CX_RUNINFO: 8050 case BTF_EVNT_BT_PSD: 8051 return func; 8052 case BTF_EVNT_BT_DEV_INFO: 8053 if (ver->fwc2hfunc == 0) 8054 return BTF_EVNT_BUF_OVERFLOW; 8055 else 8056 return BTF_EVNT_BT_DEV_INFO; 8057 case BTF_EVNT_BT_LEAUDIO_INFO: 8058 if (ver->fwc2hfunc == 0) 8059 return BTF_EVNT_C2H_LOOPBACK; 8060 else if (ver->fwc2hfunc == 1) 8061 return BTF_EVNT_BUF_OVERFLOW; 8062 else if (ver->fwc2hfunc == 2) 8063 return func; 8064 else 8065 return BTF_EVNT_MAX; 8066 case BTF_EVNT_BUF_OVERFLOW: 8067 if (ver->fwc2hfunc == 0) 8068 return BTF_EVNT_MAX; 8069 else if (ver->fwc2hfunc == 1) 8070 return BTF_EVNT_C2H_LOOPBACK; 8071 else if (ver->fwc2hfunc == 2) 8072 return func; 8073 else 8074 return BTF_EVNT_MAX; 8075 case BTF_EVNT_C2H_LOOPBACK: 8076 if (ver->fwc2hfunc == 2) 8077 return func; 8078 else 8079 return BTF_EVNT_MAX; 8080 case BTF_EVNT_MAX: 8081 default: 8082 return BTF_EVNT_MAX; 8083 } 8084 } 8085 8086 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 8087 u32 len, u8 class, u8 func) 8088 { 8089 struct rtw89_btc *btc = &rtwdev->btc; 8090 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8091 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 8092 8093 len -= RTW89_C2H_HEADER_LEN; 8094 8095 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8096 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 8097 __func__, len, class, func); 8098 8099 if (class != BTFC_FW_EVENT) 8100 return; 8101 8102 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); 8103 8104 switch (func) { 8105 case BTF_EVNT_BUF_OVERFLOW: 8106 pfwinfo->event[func]++; 8107 break; 8108 case BTF_EVNT_RPT: 8109 pfwinfo->event[func]++; 8110 /* Don't need rtw89_leave_ps_mode() */ 8111 btc_fw_event(rtwdev, func, buf, len); 8112 break; 8113 case BTF_EVNT_BT_INFO: 8114 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8115 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 8116 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++; 8117 _update_bt_info(rtwdev, buf, len); 8118 break; 8119 case BTF_EVNT_BT_SCBD: 8120 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8121 "[BTC], handle C2H BT SCBD with data %8ph\n", buf); 8122 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++; 8123 _update_bt_scbd(rtwdev, false); 8124 break; 8125 case BTF_EVNT_BT_PSD: 8126 break; 8127 case BTF_EVNT_BT_REG: 8128 btc->dbg.rb_done = true; 8129 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 8130 8131 break; 8132 case BTF_EVNT_C2H_LOOPBACK: 8133 btc->dbg.rb_done = true; 8134 btc->dbg.rb_val = buf[0]; 8135 break; 8136 case BTF_EVNT_CX_RUNINFO: 8137 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 8138 break; 8139 } 8140 } 8141 8142 #define BTC_CX_FW_OFFLOAD 0 8143 8144 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8145 { 8146 union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; 8147 const struct rtw89_chip_info *chip = rtwdev->chip; 8148 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 8149 struct rtw89_hal *hal = &rtwdev->hal; 8150 struct rtw89_btc *btc = &rtwdev->btc; 8151 struct rtw89_btc_dm *dm = &btc->dm; 8152 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 8153 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8154 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 8155 u8 cv, rfe, iso, ant_num, ant_single_pos; 8156 char *p = buf, *end = buf + bufsz; 8157 8158 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 8159 return 0; 8160 8161 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 8162 8163 p += scnprintf(p, end - p, 8164 "========== [BTC COEX INFO (%d)] ==========\n", 8165 chip->chip_id); 8166 8167 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 8168 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 8169 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 8170 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 8171 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ", 8172 "[coex_version]", ver_main, ver_sub, ver_hotfix, 8173 id_branch); 8174 8175 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 8176 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 8177 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 8178 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 8179 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)", 8180 ver_main, ver_sub, ver_hotfix, id_branch); 8181 8182 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 8183 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 8184 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 8185 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ", 8186 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 8187 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 8188 8189 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n", 8190 bt->ver_info.fw_coex, 8191 (bt->ver_info.fw_coex >= chip->btcx_desired ? 8192 "Match" : "Mismatch"), chip->btcx_desired); 8193 8194 if (bt->enable.now && bt->ver_info.fw == 0) 8195 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 8196 else 8197 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 8198 8199 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 8200 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 8201 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 8202 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 8203 p += scnprintf(p, end - p, 8204 " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n", 8205 "[sub_module]", 8206 ver_main, ver_sub, ver_hotfix, id_branch, 8207 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 8208 8209 if (ver->fcxinit == 7) { 8210 cv = md->md_v7.kt_ver; 8211 rfe = md->md_v7.rfe_type; 8212 iso = md->md_v7.ant.isolation; 8213 ant_num = md->md_v7.ant.num; 8214 ant_single_pos = md->md_v7.ant.single_pos; 8215 } else { 8216 cv = md->md.cv; 8217 rfe = md->md.rfe_type; 8218 iso = md->md.ant.isolation; 8219 ant_num = md->md.ant.num; 8220 ant_single_pos = md->md.ant.single_pos; 8221 } 8222 8223 p += scnprintf(p, end - p, 8224 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 8225 "[hw_info]", cv, rfe, iso, ant_num, 8226 ant_num > 1 ? "" : 8227 ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, "); 8228 8229 p += scnprintf(p, end - p, 8230 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 8231 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, 8232 hal->rx_nss); 8233 8234 return p - buf; 8235 } 8236 8237 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8238 { 8239 struct rtw89_btc *btc = &rtwdev->btc; 8240 struct rtw89_btc_wl_link_info *plink = NULL; 8241 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8242 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 8243 struct rtw89_traffic_stats *t; 8244 char *p = buf, *end = buf + bufsz; 8245 u8 i; 8246 8247 if (rtwdev->dbcc_en) { 8248 p += scnprintf(p, end - p, 8249 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ", 8250 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0], 8251 wl_dinfo->scan_band[RTW89_PHY_0], 8252 wl_dinfo->real_band[RTW89_PHY_0]); 8253 p += scnprintf(p, end - p, 8254 "PHY1_band(op:%d/scan:%d/real:%d)\n", 8255 wl_dinfo->op_band[RTW89_PHY_1], 8256 wl_dinfo->scan_band[RTW89_PHY_1], 8257 wl_dinfo->real_band[RTW89_PHY_1]); 8258 } 8259 8260 for (i = 0; i < RTW89_PORT_NUM; i++) { 8261 if (btc->ver->fwlrole == 8) 8262 plink = &btc->cx.wl.rlink_info[i][0]; 8263 else 8264 plink = &btc->cx.wl.link_info[i]; 8265 8266 if (!plink->active) 8267 continue; 8268 8269 p += scnprintf(p, end - p, 8270 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 8271 plink->pid, (u32)plink->role, plink->phy, 8272 (u32)plink->connected, plink->client_cnt - 1, 8273 (u32)plink->mode, plink->ch, (u32)plink->bw); 8274 8275 if (plink->connected == MLME_NO_LINK) 8276 continue; 8277 8278 p += scnprintf(p, end - p, 8279 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 8280 plink->mac_id, plink->tx_time, plink->tx_retry); 8281 8282 p += scnprintf(p, end - p, 8283 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 8284 plink->pid, 110 - plink->stat.rssi, 8285 plink->stat.rssi, plink->busy, 8286 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 8287 8288 t = &plink->stat.traffic; 8289 8290 p += scnprintf(p, end - p, 8291 "tx[rate:%d/busy_level:%d], ", 8292 (u32)t->tx_rate, t->tx_tfc_lv); 8293 8294 p += scnprintf(p, end - p, 8295 "rx[rate:%d/busy_level:%d/drop:%d]\n", 8296 (u32)t->rx_rate, 8297 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 8298 } 8299 8300 return p - buf; 8301 } 8302 8303 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8304 { 8305 struct rtw89_btc *btc = &rtwdev->btc; 8306 const struct rtw89_btc_ver *ver = btc->ver; 8307 struct rtw89_btc_cx *cx = &btc->cx; 8308 struct rtw89_btc_wl_info *wl = &cx->wl; 8309 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 8310 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 8311 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 8312 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 8313 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 8314 char *p = buf, *end = buf + bufsz; 8315 u8 mode; 8316 8317 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 8318 return 0; 8319 8320 p += scnprintf(p, end - p, "========== [WL Status] ==========\n"); 8321 8322 if (ver->fwlrole == 0) 8323 mode = wl_rinfo->link_mode; 8324 else if (ver->fwlrole == 1) 8325 mode = wl_rinfo_v1->link_mode; 8326 else if (ver->fwlrole == 2) 8327 mode = wl_rinfo_v2->link_mode; 8328 else if (ver->fwlrole == 7) 8329 mode = wl_rinfo_v7->link_mode; 8330 else if (ver->fwlrole == 8) 8331 mode = wl_rinfo_v8->link_mode; 8332 else 8333 goto out; 8334 8335 p += scnprintf(p, end - p, " %-15s : link_mode:%d, ", "[status]", 8336 mode); 8337 8338 p += scnprintf(p, end - p, 8339 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 8340 wl->status.map.rf_off, wl->status.map.lps, 8341 wl->status.map.scan ? "Y" : "N", 8342 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 8343 8344 p += scnprintf(p, end - p, 8345 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n", 8346 wl->status.map.connecting ? "Y" : "N", 8347 wl->status.map.roaming ? "Y" : "N", 8348 wl->status.map._4way ? "Y" : "N", 8349 wl->status.map.init_ok ? "Y" : "N"); 8350 8351 p += _show_wl_role_info(rtwdev, p, end - p); 8352 8353 out: 8354 return p - buf; 8355 } 8356 8357 enum btc_bt_a2dp_type { 8358 BTC_A2DP_LEGACY = 0, 8359 BTC_A2DP_TWS_SNIFF = 1, 8360 BTC_A2DP_TWS_RELAY = 2, 8361 }; 8362 8363 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8364 { 8365 struct rtw89_btc *btc = &rtwdev->btc; 8366 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 8367 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 8368 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 8369 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 8370 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 8371 char *p = buf, *end = buf + bufsz; 8372 8373 if (hfp.exist) { 8374 p += scnprintf(p, end - p, 8375 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 8376 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 8377 bt_linfo->sut_pwr_level[0], 8378 bt_linfo->golden_rx_shift[0]); 8379 } 8380 8381 if (hid.exist) { 8382 p += scnprintf(p, end - p, 8383 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 8384 "[HID]", 8385 hid.type & BTC_HID_218 ? "2/18," : "", 8386 hid.type & BTC_HID_418 ? "4/18," : "", 8387 hid.type & BTC_HID_BLE ? "BLE," : "", 8388 hid.type & BTC_HID_RCU ? "RCU," : "", 8389 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 8390 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 8391 bt_linfo->golden_rx_shift[1]); 8392 } 8393 8394 if (a2dp.exist) { 8395 p += scnprintf(p, end - p, 8396 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 8397 "[A2DP]", 8398 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 8399 a2dp.bitpool, a2dp.flush_time); 8400 8401 p += scnprintf(p, end - p, 8402 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 8403 a2dp.vendor_id, a2dp.device_name, 8404 bt_linfo->sut_pwr_level[2], 8405 bt_linfo->golden_rx_shift[2]); 8406 } 8407 8408 if (pan.exist) { 8409 p += scnprintf(p, end - p, 8410 " %-15s : sut_pwr:%d, golden-rx:%d\n", 8411 "[PAN]", 8412 bt_linfo->sut_pwr_level[3], 8413 bt_linfo->golden_rx_shift[3]); 8414 } 8415 8416 return p - buf; 8417 } 8418 8419 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8420 { 8421 struct rtw89_btc *btc = &rtwdev->btc; 8422 const struct rtw89_btc_ver *ver = btc->ver; 8423 struct rtw89_btc_cx *cx = &btc->cx; 8424 struct rtw89_btc_bt_info *bt = &cx->bt; 8425 struct rtw89_btc_wl_info *wl = &cx->wl; 8426 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 8427 union rtw89_btc_module_info *md = &btc->mdinfo; 8428 char *p = buf, *end = buf + bufsz; 8429 u8 *afh = bt_linfo->afh_map; 8430 u8 *afh_le = bt_linfo->afh_map_le; 8431 u8 bt_pos; 8432 8433 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 8434 return 0; 8435 8436 if (ver->fcxinit == 7) 8437 bt_pos = md->md_v7.bt_pos; 8438 else 8439 bt_pos = md->md.bt_pos; 8440 8441 p += scnprintf(p, end - p, "========== [BT Status] ==========\n"); 8442 8443 p += scnprintf(p, end - p, 8444 " %-15s : enable:%s, btg:%s%s, connect:%s, ", 8445 "[status]", bt->enable.now ? "Y" : "N", 8446 bt->btg_type ? "Y" : "N", 8447 (bt->enable.now && (bt->btg_type != bt_pos) ? 8448 "(efuse-mismatch!!)" : ""), 8449 (bt_linfo->status.map.connect ? "Y" : "N")); 8450 8451 p += scnprintf(p, end - p, 8452 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 8453 bt->igno_wl ? "Y" : "N", 8454 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 8455 8456 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ", 8457 "[profile]", 8458 (bt_linfo->profile_cnt.now == 0) ? "None," : "", 8459 bt_linfo->hfp_desc.exist ? "HFP," : "", 8460 bt_linfo->hid_desc.exist ? "HID," : "", 8461 bt_linfo->a2dp_desc.exist ? 8462 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 8463 bt_linfo->pan_desc.exist ? "PAN," : ""); 8464 8465 p += scnprintf(p, end - p, 8466 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 8467 bt_linfo->multi_link.now ? "Y" : "N", 8468 bt_linfo->slave_role ? "Slave" : "Master", 8469 bt_linfo->status.map.ble_connect ? "Y" : "N", 8470 bt_linfo->cqddr ? "Y" : "N", 8471 bt_linfo->a2dp_desc.active ? "Y" : "N", 8472 bt_linfo->pan_desc.active ? "Y" : "N"); 8473 8474 p += scnprintf(p, end - p, 8475 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s", 8476 "[link]", bt_linfo->rssi - 100, 8477 bt->rssi_level, 8478 bt_linfo->tx_3m ? 3 : 2, 8479 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 8480 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 8481 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 8482 8483 p += scnprintf(p, end - p, 8484 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 8485 bt_linfo->relink.now ? " ReLink!!" : "", 8486 afh[0], afh[1], afh[2], afh[3], afh[4], 8487 afh[5], afh[6], afh[7], afh[8], afh[9]); 8488 8489 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 8490 p += scnprintf(p, end - p, 8491 "LE[%02x%02x_%02x_%02x%02x]", 8492 afh_le[0], afh_le[1], afh_le[2], 8493 afh_le[3], afh_le[4]); 8494 8495 p += scnprintf(p, end - p, "wl_ch_map[en:%d/ch:%d/bw:%d]\n", 8496 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw); 8497 8498 p += scnprintf(p, end - p, 8499 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 8500 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY], 8501 cx->cnt_bt[BTC_BCNT_RELINK], 8502 cx->cnt_bt[BTC_BCNT_RATECHG], 8503 cx->cnt_bt[BTC_BCNT_REINIT], 8504 cx->cnt_bt[BTC_BCNT_REENABLE]); 8505 8506 p += scnprintf(p, end - p, 8507 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 8508 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH], 8509 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ], 8510 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]); 8511 8512 p += _show_bt_profile_info(rtwdev, p, end - p); 8513 8514 p += scnprintf(p, end - p, 8515 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 8516 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 8517 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 8518 bt->raw_info[7], 8519 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 8520 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 8521 cx->cnt_bt[BTC_BCNT_INFOSAME]); 8522 8523 p += scnprintf(p, end - p, 8524 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)", 8525 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX], 8526 cx->cnt_bt[BTC_BCNT_HIPRI_TX], 8527 cx->cnt_bt[BTC_BCNT_LOPRI_RX], 8528 cx->cnt_bt[BTC_BCNT_LOPRI_TX], 8529 cx->cnt_bt[BTC_BCNT_POLUT]); 8530 8531 if (!bt->scan_info_update) { 8532 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true); 8533 p += scnprintf(p, end - p, "\n"); 8534 } else { 8535 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false); 8536 if (ver->fcxbtscan == 1) { 8537 p += scnprintf(p, end - p, 8538 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)", 8539 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win), 8540 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl), 8541 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win), 8542 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl), 8543 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win), 8544 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl), 8545 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win), 8546 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl)); 8547 } else if (ver->fcxbtscan == 2) { 8548 p += scnprintf(p, end - p, 8549 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)", 8550 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win), 8551 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl), 8552 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win), 8553 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl), 8554 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win), 8555 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl)); 8556 } 8557 p += scnprintf(p, end - p, "\n"); 8558 } 8559 8560 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect) 8561 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true); 8562 else 8563 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false); 8564 8565 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 8566 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true); 8567 else 8568 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false); 8569 8570 if (bt_linfo->a2dp_desc.exist && 8571 (bt_linfo->a2dp_desc.flush_time == 0 || 8572 bt_linfo->a2dp_desc.vendor_id == 0 || 8573 bt_linfo->a2dp_desc.play_latency == 1)) 8574 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true); 8575 else 8576 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false); 8577 8578 return p - buf; 8579 } 8580 8581 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 8582 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 8583 #define CASE_BTC_POLICY_STR(e) \ 8584 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 8585 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 8586 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e 8587 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e 8588 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e 8589 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e 8590 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e 8591 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e 8592 8593 static const char *id_to_polut(u32 id) 8594 { 8595 switch (id) { 8596 CASE_BTC_POLUT_STR(NONE); 8597 CASE_BTC_POLUT_STR(GNT_BT_TX); 8598 CASE_BTC_POLUT_STR(GNT_BT_RX); 8599 CASE_BTC_POLUT_STR(GNT_WL); 8600 CASE_BTC_POLUT_STR(BT); 8601 CASE_BTC_POLUT_STR(ALL); 8602 default: 8603 return "unknown"; 8604 } 8605 } 8606 8607 static const char *id_to_regtype(u32 id) 8608 { 8609 switch (id) { 8610 CASE_BTC_REGTYPE_STR(MAC); 8611 CASE_BTC_REGTYPE_STR(BB); 8612 CASE_BTC_REGTYPE_STR(RF); 8613 CASE_BTC_REGTYPE_STR(BT_RF); 8614 CASE_BTC_REGTYPE_STR(BT_MODEM); 8615 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE); 8616 CASE_BTC_REGTYPE_STR(BT_VENDOR); 8617 CASE_BTC_REGTYPE_STR(BT_LE); 8618 default: 8619 return "unknown"; 8620 } 8621 } 8622 8623 static const char *id_to_gdbg(u32 id) 8624 { 8625 switch (id) { 8626 CASE_BTC_GDBG_STR(GNT_BT); 8627 CASE_BTC_GDBG_STR(GNT_WL); 8628 CASE_BTC_GDBG_STR(BCN_EARLY); 8629 CASE_BTC_GDBG_STR(WL_NULL0); 8630 CASE_BTC_GDBG_STR(WL_NULL1); 8631 CASE_BTC_GDBG_STR(WL_RXISR); 8632 CASE_BTC_GDBG_STR(TDMA_ENTRY); 8633 CASE_BTC_GDBG_STR(A2DP_EMPTY); 8634 CASE_BTC_GDBG_STR(BT_RETRY); 8635 CASE_BTC_GDBG_STR(BT_RELINK); 8636 CASE_BTC_GDBG_STR(SLOT_WL); 8637 CASE_BTC_GDBG_STR(SLOT_BT); 8638 CASE_BTC_GDBG_STR(WL_ERR); 8639 CASE_BTC_GDBG_STR(WL_OK); 8640 CASE_BTC_GDBG_STR(SLOT_B2W); 8641 CASE_BTC_GDBG_STR(SLOT_W1); 8642 CASE_BTC_GDBG_STR(SLOT_W2); 8643 CASE_BTC_GDBG_STR(SLOT_W2B); 8644 CASE_BTC_GDBG_STR(SLOT_B1); 8645 CASE_BTC_GDBG_STR(SLOT_B2); 8646 CASE_BTC_GDBG_STR(SLOT_B3); 8647 CASE_BTC_GDBG_STR(SLOT_B4); 8648 CASE_BTC_GDBG_STR(SLOT_LK); 8649 CASE_BTC_GDBG_STR(SLOT_E2G); 8650 CASE_BTC_GDBG_STR(SLOT_E5G); 8651 CASE_BTC_GDBG_STR(SLOT_EBT); 8652 CASE_BTC_GDBG_STR(SLOT_WLK); 8653 CASE_BTC_GDBG_STR(SLOT_B1FDD); 8654 CASE_BTC_GDBG_STR(BT_CHANGE); 8655 CASE_BTC_GDBG_STR(WL_CCA); 8656 CASE_BTC_GDBG_STR(BT_LEAUDIO); 8657 CASE_BTC_GDBG_STR(USER_DEF); 8658 default: 8659 return "unknown"; 8660 } 8661 } 8662 8663 static const char *steps_to_str(u16 step) 8664 { 8665 switch (step) { 8666 CASE_BTC_RSN_STR(NONE); 8667 CASE_BTC_RSN_STR(NTFY_INIT); 8668 CASE_BTC_RSN_STR(NTFY_SWBAND); 8669 CASE_BTC_RSN_STR(NTFY_WL_STA); 8670 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 8671 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 8672 CASE_BTC_RSN_STR(NTFY_WL_RFK); 8673 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 8674 CASE_BTC_RSN_STR(NTFY_SCAN_START); 8675 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 8676 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 8677 CASE_BTC_RSN_STR(NTFY_POWEROFF); 8678 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 8679 CASE_BTC_RSN_STR(CMD_SET_COEX); 8680 CASE_BTC_RSN_STR(ACT1_WORK); 8681 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 8682 CASE_BTC_RSN_STR(RFK_CHK_WORK); 8683 8684 CASE_BTC_ACT_STR(NONE); 8685 CASE_BTC_ACT_STR(WL_ONLY); 8686 CASE_BTC_ACT_STR(WL_5G); 8687 CASE_BTC_ACT_STR(WL_OTHER); 8688 CASE_BTC_ACT_STR(WL_IDLE); 8689 CASE_BTC_ACT_STR(WL_NC); 8690 CASE_BTC_ACT_STR(WL_RFK); 8691 CASE_BTC_ACT_STR(WL_INIT); 8692 CASE_BTC_ACT_STR(WL_OFF); 8693 CASE_BTC_ACT_STR(FREERUN); 8694 CASE_BTC_ACT_STR(BT_WHQL); 8695 CASE_BTC_ACT_STR(BT_RFK); 8696 CASE_BTC_ACT_STR(BT_OFF); 8697 CASE_BTC_ACT_STR(BT_IDLE); 8698 CASE_BTC_ACT_STR(BT_HFP); 8699 CASE_BTC_ACT_STR(BT_HID); 8700 CASE_BTC_ACT_STR(BT_A2DP); 8701 CASE_BTC_ACT_STR(BT_A2DPSINK); 8702 CASE_BTC_ACT_STR(BT_PAN); 8703 CASE_BTC_ACT_STR(BT_A2DP_HID); 8704 CASE_BTC_ACT_STR(BT_A2DP_PAN); 8705 CASE_BTC_ACT_STR(BT_PAN_HID); 8706 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 8707 CASE_BTC_ACT_STR(WL_25G_MCC); 8708 CASE_BTC_ACT_STR(WL_2G_MCC); 8709 CASE_BTC_ACT_STR(WL_2G_SCC); 8710 CASE_BTC_ACT_STR(WL_2G_AP); 8711 CASE_BTC_ACT_STR(WL_2G_GO); 8712 CASE_BTC_ACT_STR(WL_2G_GC); 8713 CASE_BTC_ACT_STR(WL_2G_NAN); 8714 8715 CASE_BTC_POLICY_STR(OFF_BT); 8716 CASE_BTC_POLICY_STR(OFF_WL); 8717 CASE_BTC_POLICY_STR(OFF_EQ0); 8718 CASE_BTC_POLICY_STR(OFF_EQ1); 8719 CASE_BTC_POLICY_STR(OFF_EQ2); 8720 CASE_BTC_POLICY_STR(OFF_EQ3); 8721 CASE_BTC_POLICY_STR(OFF_EQ4); 8722 CASE_BTC_POLICY_STR(OFF_EQ5); 8723 CASE_BTC_POLICY_STR(OFF_BWB0); 8724 CASE_BTC_POLICY_STR(OFF_BWB1); 8725 CASE_BTC_POLICY_STR(OFF_BWB2); 8726 CASE_BTC_POLICY_STR(OFF_BWB3); 8727 CASE_BTC_POLICY_STR(OFF_WL2); 8728 CASE_BTC_POLICY_STR(OFFB_BWB0); 8729 CASE_BTC_POLICY_STR(OFFE_DEF); 8730 CASE_BTC_POLICY_STR(OFFE_DEF2); 8731 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 8732 CASE_BTC_POLICY_STR(OFFE_2GISOB); 8733 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 8734 CASE_BTC_POLICY_STR(OFFE_WL); 8735 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 8736 CASE_BTC_POLICY_STR(FIX_TD3030); 8737 CASE_BTC_POLICY_STR(FIX_TD5050); 8738 CASE_BTC_POLICY_STR(FIX_TD2030); 8739 CASE_BTC_POLICY_STR(FIX_TD4010); 8740 CASE_BTC_POLICY_STR(FIX_TD7010); 8741 CASE_BTC_POLICY_STR(FIX_TD2060); 8742 CASE_BTC_POLICY_STR(FIX_TD3060); 8743 CASE_BTC_POLICY_STR(FIX_TD2080); 8744 CASE_BTC_POLICY_STR(FIX_TDW1B1); 8745 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 8746 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL); 8747 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL); 8748 CASE_BTC_POLICY_STR(PFIX_TD3030); 8749 CASE_BTC_POLICY_STR(PFIX_TD5050); 8750 CASE_BTC_POLICY_STR(PFIX_TD2030); 8751 CASE_BTC_POLICY_STR(PFIX_TD2060); 8752 CASE_BTC_POLICY_STR(PFIX_TD3070); 8753 CASE_BTC_POLICY_STR(PFIX_TD2080); 8754 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 8755 CASE_BTC_POLICY_STR(AUTO_TD50B1); 8756 CASE_BTC_POLICY_STR(AUTO_TD60B1); 8757 CASE_BTC_POLICY_STR(AUTO_TD20B1); 8758 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 8759 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 8760 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 8761 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 8762 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 8763 CASE_BTC_POLICY_STR(AUTO2_TD3050); 8764 CASE_BTC_POLICY_STR(AUTO2_TD3070); 8765 CASE_BTC_POLICY_STR(AUTO2_TD5050); 8766 CASE_BTC_POLICY_STR(AUTO2_TD6060); 8767 CASE_BTC_POLICY_STR(AUTO2_TD2080); 8768 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 8769 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 8770 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 8771 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 8772 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 8773 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 8774 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 8775 default: 8776 return "unknown step"; 8777 } 8778 } 8779 8780 static const char *id_to_slot(u32 id) 8781 { 8782 switch (id) { 8783 CASE_BTC_SLOT_STR(OFF); 8784 CASE_BTC_SLOT_STR(B2W); 8785 CASE_BTC_SLOT_STR(W1); 8786 CASE_BTC_SLOT_STR(W2); 8787 CASE_BTC_SLOT_STR(W2B); 8788 CASE_BTC_SLOT_STR(B1); 8789 CASE_BTC_SLOT_STR(B2); 8790 CASE_BTC_SLOT_STR(B3); 8791 CASE_BTC_SLOT_STR(B4); 8792 CASE_BTC_SLOT_STR(LK); 8793 CASE_BTC_SLOT_STR(BLK); 8794 CASE_BTC_SLOT_STR(E2G); 8795 CASE_BTC_SLOT_STR(E5G); 8796 CASE_BTC_SLOT_STR(EBT); 8797 CASE_BTC_SLOT_STR(ENULL); 8798 CASE_BTC_SLOT_STR(WLK); 8799 CASE_BTC_SLOT_STR(W1FDD); 8800 CASE_BTC_SLOT_STR(B1FDD); 8801 default: 8802 return "unknown"; 8803 } 8804 } 8805 8806 static const char *id_to_evt(u32 id) 8807 { 8808 switch (id) { 8809 CASE_BTC_EVT_STR(TDMA_ENTRY); 8810 CASE_BTC_EVT_STR(WL_TMR); 8811 CASE_BTC_EVT_STR(B1_TMR); 8812 CASE_BTC_EVT_STR(B2_TMR); 8813 CASE_BTC_EVT_STR(B3_TMR); 8814 CASE_BTC_EVT_STR(B4_TMR); 8815 CASE_BTC_EVT_STR(W2B_TMR); 8816 CASE_BTC_EVT_STR(B2W_TMR); 8817 CASE_BTC_EVT_STR(BCN_EARLY); 8818 CASE_BTC_EVT_STR(A2DP_EMPTY); 8819 CASE_BTC_EVT_STR(LK_END); 8820 CASE_BTC_EVT_STR(RX_ISR); 8821 CASE_BTC_EVT_STR(RX_FC0); 8822 CASE_BTC_EVT_STR(RX_FC1); 8823 CASE_BTC_EVT_STR(BT_RELINK); 8824 CASE_BTC_EVT_STR(BT_RETRY); 8825 CASE_BTC_EVT_STR(E2G); 8826 CASE_BTC_EVT_STR(E5G); 8827 CASE_BTC_EVT_STR(EBT); 8828 CASE_BTC_EVT_STR(ENULL); 8829 CASE_BTC_EVT_STR(DRV_WLK); 8830 CASE_BTC_EVT_STR(BCN_OK); 8831 CASE_BTC_EVT_STR(BT_CHANGE); 8832 CASE_BTC_EVT_STR(EBT_EXTEND); 8833 CASE_BTC_EVT_STR(E2G_NULL1); 8834 CASE_BTC_EVT_STR(B1FDD_TMR); 8835 default: 8836 return "unknown"; 8837 } 8838 } 8839 8840 static const char *id_to_mode(u8 id) 8841 { 8842 switch (id) { 8843 CASE_BTC_INIT(NORMAL); 8844 CASE_BTC_INIT(WL); 8845 CASE_BTC_INIT(BT); 8846 CASE_BTC_INIT(WLOFF); 8847 default: 8848 return "unknown"; 8849 } 8850 } 8851 8852 static const char *id_to_ant(u32 id) 8853 { 8854 switch (id) { 8855 CASE_BTC_ANTPATH_STR(WPOWERON); 8856 CASE_BTC_ANTPATH_STR(WINIT); 8857 CASE_BTC_ANTPATH_STR(WONLY); 8858 CASE_BTC_ANTPATH_STR(WOFF); 8859 CASE_BTC_ANTPATH_STR(W2G); 8860 CASE_BTC_ANTPATH_STR(W5G); 8861 CASE_BTC_ANTPATH_STR(W25G); 8862 CASE_BTC_ANTPATH_STR(FREERUN); 8863 CASE_BTC_ANTPATH_STR(WRFK); 8864 CASE_BTC_ANTPATH_STR(BRFK); 8865 CASE_BTC_ANTPATH_STR(MAX); 8866 default: 8867 return "unknown"; 8868 } 8869 } 8870 8871 static 8872 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data, 8873 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 8874 { 8875 char *p = buf, *end = buf + bufsz; 8876 u8 cur_index; 8877 u8 i; 8878 8879 for (i = 0; i < len ; i++) { 8880 if ((i % seg_len) == 0) 8881 p += scnprintf(p, end - p, " %-15s : ", prefix); 8882 cur_index = (start_idx + i) % ring_len; 8883 if (i % 3 == 0) 8884 p += scnprintf(p, end - p, "-> %-20s", 8885 steps_to_str(*(data + cur_index))); 8886 else if (i % 3 == 1) 8887 p += scnprintf(p, end - p, "-> %-15s", 8888 steps_to_str(*(data + cur_index))); 8889 else 8890 p += scnprintf(p, end - p, "-> %-13s", 8891 steps_to_str(*(data + cur_index))); 8892 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 8893 p += scnprintf(p, end - p, "\n"); 8894 } 8895 8896 return p - buf; 8897 } 8898 8899 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8900 { 8901 struct rtw89_btc *btc = &rtwdev->btc; 8902 struct rtw89_btc_dm *dm = &btc->dm; 8903 char *p = buf, *end = buf + bufsz; 8904 u8 start_idx; 8905 u8 len; 8906 8907 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 8908 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 8909 8910 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len, 8911 6, start_idx, ARRAY_SIZE(dm->dm_step.step)); 8912 8913 return p - buf; 8914 } 8915 8916 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8917 { 8918 struct rtw89_btc *btc = &rtwdev->btc; 8919 const struct rtw89_btc_ver *ver = btc->ver; 8920 struct rtw89_btc_dm *dm = &btc->dm; 8921 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8922 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 8923 char *p = buf, *end = buf + bufsz; 8924 u8 igno_bt; 8925 8926 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 8927 return 0; 8928 8929 p += scnprintf(p, end - p, 8930 "========== [Mechanism Status %s] ==========\n", 8931 (btc->manual_ctrl ? "(Manual)" : "(Auto)")); 8932 8933 p += scnprintf(p, end - p, 8934 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n", 8935 "[status]", 8936 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated", 8937 steps_to_str(dm->run_reason), 8938 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 8939 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)), 8940 id_to_mode(wl->coex_mode), 8941 dm->cnt_dm[BTC_DCNT_RUN]); 8942 8943 p += _show_dm_step(rtwdev, p, end - p); 8944 8945 if (ver->fcxctrl == 7) 8946 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 8947 else 8948 igno_bt = btc->ctrl.ctrl.igno_bt; 8949 8950 p += scnprintf(p, end - p, 8951 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 8952 "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt, 8953 dm->freerun, btc->lps, dm->wl_mimo_ps); 8954 8955 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n", 8956 dm->leak_ap, 8957 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 8958 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 8959 "" : "(Mismatch!!)")); 8960 8961 if (dm->rf_trx_para.wl_tx_power == 0xff) 8962 p += scnprintf(p, end - p, 8963 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ", 8964 "[trx_ctrl]", wl->rssi_level, 8965 dm->trx_para_level); 8966 8967 else 8968 p += scnprintf(p, end - p, 8969 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ", 8970 "[trx_ctrl]", wl->rssi_level, 8971 dm->trx_para_level, 8972 dm->rf_trx_para.wl_tx_power); 8973 8974 p += scnprintf(p, end - p, 8975 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n", 8976 dm->rf_trx_para.wl_rx_gain, 8977 dm->rf_trx_para.bt_tx_power, 8978 dm->rf_trx_para.bt_rx_gain, 8979 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx); 8980 8981 p += scnprintf(p, end - p, 8982 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 8983 "[dm_ctrl]", dm->wl_tx_limit.enable, 8984 dm->wl_tx_limit.tx_time, 8985 dm->wl_tx_limit.tx_retry, btc->bt_req_len, 8986 bt->scan_rx_low_pri); 8987 8988 return p - buf; 8989 } 8990 8991 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8992 { 8993 struct rtw89_btc *btc = &rtwdev->btc; 8994 const struct rtw89_btc_ver *ver = btc->ver; 8995 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8996 union rtw89_btc_fbtc_cysta_info *pcysta; 8997 char *p = buf, *end = buf + bufsz; 8998 u32 except_cnt, exception_map; 8999 9000 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 9001 if (ver->fcxcysta == 2) { 9002 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 9003 except_cnt = le32_to_cpu(pcysta->v2.except_cnt); 9004 exception_map = le32_to_cpu(pcysta->v2.exception); 9005 } else if (ver->fcxcysta == 3) { 9006 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 9007 except_cnt = le32_to_cpu(pcysta->v3.except_cnt); 9008 exception_map = le32_to_cpu(pcysta->v3.except_map); 9009 } else if (ver->fcxcysta == 4) { 9010 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 9011 except_cnt = pcysta->v4.except_cnt; 9012 exception_map = le32_to_cpu(pcysta->v4.except_map); 9013 } else if (ver->fcxcysta == 5) { 9014 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 9015 except_cnt = pcysta->v5.except_cnt; 9016 exception_map = le32_to_cpu(pcysta->v5.except_map); 9017 } else if (ver->fcxcysta == 7) { 9018 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 9019 except_cnt = pcysta->v7.except_cnt; 9020 exception_map = le32_to_cpu(pcysta->v7.except_map); 9021 } else { 9022 return 0; 9023 } 9024 9025 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 9026 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 9027 return 0; 9028 9029 p += scnprintf(p, end - p, " %-15s : ", "[error]"); 9030 9031 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 9032 p += scnprintf(p, end - p, 9033 "overflow-cnt: %d, ", 9034 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 9035 } 9036 9037 if (pfwinfo->len_mismch) { 9038 p += scnprintf(p, end - p, 9039 "len-mismatch: 0x%x, ", 9040 pfwinfo->len_mismch); 9041 } 9042 9043 if (pfwinfo->fver_mismch) { 9044 p += scnprintf(p, end - p, 9045 "fver-mismatch: 0x%x, ", 9046 pfwinfo->fver_mismch); 9047 } 9048 9049 /* cycle statistics exceptions */ 9050 if (exception_map || except_cnt) { 9051 p += scnprintf(p, end - p, 9052 "exception-type: 0x%x, exception-cnt = %d", 9053 exception_map, except_cnt); 9054 } 9055 p += scnprintf(p, end - p, "\n"); 9056 9057 return p - buf; 9058 } 9059 9060 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9061 { 9062 struct rtw89_btc *btc = &rtwdev->btc; 9063 const struct rtw89_btc_ver *ver = btc->ver; 9064 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9065 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 9066 struct rtw89_btc_fbtc_tdma *t = NULL; 9067 char *p = buf, *end = buf + bufsz; 9068 9069 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 9070 if (!pcinfo->valid) 9071 return 0; 9072 9073 if (ver->fcxtdma == 1) 9074 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 9075 else 9076 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma; 9077 9078 p += scnprintf(p, end - p, 9079 " %-15s : ", "[tdma_policy]"); 9080 p += scnprintf(p, end - p, 9081 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ", 9082 (u32)t->type, 9083 t->rxflctrl, t->txpause); 9084 9085 p += scnprintf(p, end - p, 9086 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ", 9087 t->wtgle_n, t->leak_n, t->ext_ctrl); 9088 9089 p += scnprintf(p, end - p, 9090 "policy_type:%d", 9091 (u32)btc->policy_type); 9092 9093 p += scnprintf(p, end - p, "\n"); 9094 9095 return p - buf; 9096 } 9097 9098 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9099 { 9100 struct rtw89_btc *btc = &rtwdev->btc; 9101 struct rtw89_btc_dm *dm = &btc->dm; 9102 char *p = buf, *end = buf + bufsz; 9103 u16 dur, cxtype; 9104 u32 tbl; 9105 u8 i = 0; 9106 9107 for (i = 0; i < CXST_MAX; i++) { 9108 if (btc->ver->fcxslots == 1) { 9109 dur = le16_to_cpu(dm->slot_now.v1[i].dur); 9110 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl); 9111 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype); 9112 } else if (btc->ver->fcxslots == 7) { 9113 dur = le16_to_cpu(dm->slot_now.v7[i].dur); 9114 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl); 9115 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype); 9116 } else { 9117 return 0; 9118 } 9119 9120 if (i % 5 == 0) 9121 p += scnprintf(p, end - p, 9122 " %-15s : %5s[%03d/0x%x/%d]", 9123 "[slot_list]", 9124 id_to_slot((u32)i), 9125 dur, tbl, cxtype); 9126 else 9127 p += scnprintf(p, end - p, 9128 ", %5s[%03d/0x%x/%d]", 9129 id_to_slot((u32)i), 9130 dur, tbl, cxtype); 9131 9132 if (i % 5 == 4) 9133 p += scnprintf(p, end - p, "\n"); 9134 } 9135 p += scnprintf(p, end - p, "\n"); 9136 9137 return p - buf; 9138 } 9139 9140 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9141 { 9142 struct rtw89_btc *btc = &rtwdev->btc; 9143 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9144 struct rtw89_btc_dm *dm = &btc->dm; 9145 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 9146 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 9147 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL; 9148 union rtw89_btc_fbtc_rxflct r; 9149 u16 cycle, c_begin, c_end, store_index; 9150 char *p = buf, *end = buf + bufsz; 9151 u8 i, cnt = 0, slot_pair; 9152 9153 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9154 if (!pcinfo->valid) 9155 return 0; 9156 9157 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 9158 p += scnprintf(p, end - p, 9159 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 9160 "[cycle_cnt]", 9161 le16_to_cpu(pcysta_le32->cycles), 9162 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]), 9163 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]), 9164 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]), 9165 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK])); 9166 9167 for (i = 0; i < CXST_MAX; i++) { 9168 if (!le32_to_cpu(pcysta_le32->slot_cnt[i])) 9169 continue; 9170 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i), 9171 le32_to_cpu(pcysta_le32->slot_cnt[i])); 9172 } 9173 9174 if (dm->tdma_now.rxflctrl) { 9175 p += scnprintf(p, end - p, ", leak_rx:%d", 9176 le32_to_cpu(pcysta_le32->leakrx_cnt)); 9177 } 9178 9179 if (le32_to_cpu(pcysta_le32->collision_cnt)) { 9180 p += scnprintf(p, end - p, ", collision:%d", 9181 le32_to_cpu(pcysta_le32->collision_cnt)); 9182 } 9183 9184 if (le32_to_cpu(pcysta_le32->skip_cnt)) { 9185 p += scnprintf(p, end - p, ", skip:%d", 9186 le32_to_cpu(pcysta_le32->skip_cnt)); 9187 } 9188 p += scnprintf(p, end - p, "\n"); 9189 9190 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9191 "[cycle_time]", 9192 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]), 9193 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]), 9194 le16_to_cpu(pcysta_le32->tavg_lk) / 1000, 9195 le16_to_cpu(pcysta_le32->tavg_lk) % 1000); 9196 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 9197 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]), 9198 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]), 9199 le16_to_cpu(pcysta_le32->tmax_lk) / 1000, 9200 le16_to_cpu(pcysta_le32->tmax_lk) % 1000); 9201 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n", 9202 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]), 9203 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT])); 9204 9205 if (le16_to_cpu(pcysta_le32->cycles) <= 1) 9206 goto out; 9207 9208 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 9209 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 9210 9211 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair) 9212 c_begin = 1; 9213 else 9214 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1; 9215 9216 c_end = le16_to_cpu(pcysta_le32->cycles); 9217 9218 for (cycle = c_begin; cycle <= c_end; cycle++) { 9219 cnt++; 9220 store_index = ((cycle - 1) % slot_pair) * 2; 9221 9222 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 9223 p += scnprintf(p, end - p, 9224 " %-15s : ->b%02d->w%02d", 9225 "[cycle_step]", 9226 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 9227 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 9228 else 9229 p += scnprintf(p, end - p, 9230 "->b%02d->w%02d", 9231 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 9232 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 9233 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 9234 p += scnprintf(p, end - p, "\n"); 9235 } 9236 9237 if (a2dp->exist) { 9238 p += scnprintf(p, end - p, 9239 " %-15s : a2dp_ept:%d, a2dp_late:%d", 9240 "[a2dp_t_sta]", 9241 le16_to_cpu(pcysta_le32->a2dpept), 9242 le16_to_cpu(pcysta_le32->a2dpeptto)); 9243 9244 p += scnprintf(p, end - p, 9245 ", avg_t:%d, max_t:%d", 9246 le16_to_cpu(pcysta_le32->tavg_a2dpept), 9247 le16_to_cpu(pcysta_le32->tmax_a2dpept)); 9248 r.val = dm->tdma_now.rxflctrl; 9249 9250 if (r.type && r.tgln_n) { 9251 p += scnprintf(p, end - p, 9252 ", cycle[PSTDMA:%d/TDMA:%d], ", 9253 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]), 9254 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF])); 9255 9256 p += scnprintf(p, end - p, 9257 "avg_t[PSTDMA:%d/TDMA:%d], ", 9258 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]), 9259 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF])); 9260 9261 p += scnprintf(p, end - p, 9262 "max_t[PSTDMA:%d/TDMA:%d]", 9263 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]), 9264 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF])); 9265 } 9266 p += scnprintf(p, end - p, "\n"); 9267 } 9268 9269 out: 9270 return p - buf; 9271 } 9272 9273 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9274 { 9275 struct rtw89_btc *btc = &rtwdev->btc; 9276 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 9277 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9278 struct rtw89_btc_dm *dm = &btc->dm; 9279 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 9280 struct rtw89_btc_fbtc_cysta_v3 *pcysta; 9281 struct rtw89_btc_rpt_cmn_info *pcinfo; 9282 u8 i, cnt = 0, slot_pair, divide_cnt; 9283 u16 cycle, c_begin, c_end, store_index; 9284 char *p = buf, *end = buf + bufsz; 9285 9286 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9287 if (!pcinfo->valid) 9288 return 0; 9289 9290 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 9291 p += scnprintf(p, end - p, 9292 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 9293 "[cycle_cnt]", 9294 le16_to_cpu(pcysta->cycles), 9295 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 9296 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 9297 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 9298 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 9299 9300 for (i = 0; i < CXST_MAX; i++) { 9301 if (!le32_to_cpu(pcysta->slot_cnt[i])) 9302 continue; 9303 9304 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 9305 le32_to_cpu(pcysta->slot_cnt[i])); 9306 } 9307 9308 if (dm->tdma_now.rxflctrl) 9309 p += scnprintf(p, end - p, ", leak_rx:%d", 9310 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 9311 9312 if (le32_to_cpu(pcysta->collision_cnt)) 9313 p += scnprintf(p, end - p, ", collision:%d", 9314 le32_to_cpu(pcysta->collision_cnt)); 9315 9316 if (le32_to_cpu(pcysta->skip_cnt)) 9317 p += scnprintf(p, end - p, ", skip:%d", 9318 le32_to_cpu(pcysta->skip_cnt)); 9319 9320 p += scnprintf(p, end - p, "\n"); 9321 9322 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9323 "[cycle_time]", 9324 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 9325 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 9326 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 9327 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 9328 p += scnprintf(p, end - p, 9329 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 9330 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 9331 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 9332 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 9333 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 9334 p += scnprintf(p, end - p, 9335 ", maxdiff_t[wl:%d/bt:%d]\n", 9336 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 9337 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 9338 9339 cycle = le16_to_cpu(pcysta->cycles); 9340 if (cycle <= 1) 9341 goto out; 9342 9343 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 9344 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 9345 9346 if (cycle <= slot_pair) 9347 c_begin = 1; 9348 else 9349 c_begin = cycle - slot_pair + 1; 9350 9351 c_end = cycle; 9352 9353 if (a2dp->exist) 9354 divide_cnt = 3; 9355 else 9356 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 9357 9358 for (cycle = c_begin; cycle <= c_end; cycle++) { 9359 cnt++; 9360 store_index = ((cycle - 1) % slot_pair) * 2; 9361 9362 if (cnt % divide_cnt == 1) 9363 p += scnprintf(p, end - p, " %-15s : ", 9364 "[cycle_step]"); 9365 9366 p += scnprintf(p, end - p, "->b%02d", 9367 le16_to_cpu(pcysta->slot_step_time[store_index])); 9368 if (a2dp->exist) { 9369 a2dp_trx = &pcysta->a2dp_trx[store_index]; 9370 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 9371 a2dp_trx->empty_cnt, 9372 a2dp_trx->retry_cnt, 9373 a2dp_trx->tx_rate ? 3 : 2, 9374 a2dp_trx->tx_cnt, 9375 a2dp_trx->ack_cnt, 9376 a2dp_trx->nack_cnt); 9377 } 9378 p += scnprintf(p, end - p, "->w%02d", 9379 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 9380 if (a2dp->exist) { 9381 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 9382 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 9383 a2dp_trx->empty_cnt, 9384 a2dp_trx->retry_cnt, 9385 a2dp_trx->tx_rate ? 3 : 2, 9386 a2dp_trx->tx_cnt, 9387 a2dp_trx->ack_cnt, 9388 a2dp_trx->nack_cnt); 9389 } 9390 if (cnt % divide_cnt == 0 || cnt == c_end) 9391 p += scnprintf(p, end - p, "\n"); 9392 } 9393 9394 if (a2dp->exist) { 9395 p += scnprintf(p, end - p, 9396 " %-15s : a2dp_ept:%d, a2dp_late:%d", 9397 "[a2dp_t_sta]", 9398 le16_to_cpu(pcysta->a2dp_ept.cnt), 9399 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 9400 9401 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 9402 le16_to_cpu(pcysta->a2dp_ept.tavg), 9403 le16_to_cpu(pcysta->a2dp_ept.tmax)); 9404 9405 p += scnprintf(p, end - p, "\n"); 9406 } 9407 9408 out: 9409 return p - buf; 9410 } 9411 9412 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9413 { 9414 struct rtw89_btc *btc = &rtwdev->btc; 9415 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 9416 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9417 struct rtw89_btc_dm *dm = &btc->dm; 9418 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 9419 struct rtw89_btc_fbtc_cysta_v4 *pcysta; 9420 struct rtw89_btc_rpt_cmn_info *pcinfo; 9421 u8 i, cnt = 0, slot_pair, divide_cnt; 9422 u16 cycle, c_begin, c_end, store_index; 9423 char *p = buf, *end = buf + bufsz; 9424 9425 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9426 if (!pcinfo->valid) 9427 return 0; 9428 9429 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 9430 p += scnprintf(p, end - p, 9431 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 9432 "[cycle_cnt]", 9433 le16_to_cpu(pcysta->cycles), 9434 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 9435 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 9436 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 9437 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 9438 9439 for (i = 0; i < CXST_MAX; i++) { 9440 if (!le16_to_cpu(pcysta->slot_cnt[i])) 9441 continue; 9442 9443 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 9444 le16_to_cpu(pcysta->slot_cnt[i])); 9445 } 9446 9447 if (dm->tdma_now.rxflctrl) 9448 p += scnprintf(p, end - p, ", leak_rx:%d", 9449 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 9450 9451 if (pcysta->collision_cnt) 9452 p += scnprintf(p, end - p, ", collision:%d", 9453 pcysta->collision_cnt); 9454 9455 if (le16_to_cpu(pcysta->skip_cnt)) 9456 p += scnprintf(p, end - p, ", skip:%d", 9457 le16_to_cpu(pcysta->skip_cnt)); 9458 9459 p += scnprintf(p, end - p, "\n"); 9460 9461 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9462 "[cycle_time]", 9463 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 9464 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 9465 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 9466 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 9467 p += scnprintf(p, end - p, 9468 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 9469 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 9470 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 9471 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 9472 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 9473 p += scnprintf(p, end - p, 9474 ", maxdiff_t[wl:%d/bt:%d]\n", 9475 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 9476 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 9477 9478 cycle = le16_to_cpu(pcysta->cycles); 9479 if (cycle <= 1) 9480 goto out; 9481 9482 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 9483 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 9484 9485 if (cycle <= slot_pair) 9486 c_begin = 1; 9487 else 9488 c_begin = cycle - slot_pair + 1; 9489 9490 c_end = cycle; 9491 9492 if (a2dp->exist) 9493 divide_cnt = 3; 9494 else 9495 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 9496 9497 for (cycle = c_begin; cycle <= c_end; cycle++) { 9498 cnt++; 9499 store_index = ((cycle - 1) % slot_pair) * 2; 9500 9501 if (cnt % divide_cnt == 1) 9502 p += scnprintf(p, end - p, " %-15s : ", 9503 "[cycle_step]"); 9504 9505 p += scnprintf(p, end - p, "->b%02d", 9506 le16_to_cpu(pcysta->slot_step_time[store_index])); 9507 if (a2dp->exist) { 9508 a2dp_trx = &pcysta->a2dp_trx[store_index]; 9509 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 9510 a2dp_trx->empty_cnt, 9511 a2dp_trx->retry_cnt, 9512 a2dp_trx->tx_rate ? 3 : 2, 9513 a2dp_trx->tx_cnt, 9514 a2dp_trx->ack_cnt, 9515 a2dp_trx->nack_cnt); 9516 } 9517 p += scnprintf(p, end - p, "->w%02d", 9518 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 9519 if (a2dp->exist) { 9520 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 9521 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 9522 a2dp_trx->empty_cnt, 9523 a2dp_trx->retry_cnt, 9524 a2dp_trx->tx_rate ? 3 : 2, 9525 a2dp_trx->tx_cnt, 9526 a2dp_trx->ack_cnt, 9527 a2dp_trx->nack_cnt); 9528 } 9529 if (cnt % divide_cnt == 0 || cnt == c_end) 9530 p += scnprintf(p, end - p, "\n"); 9531 } 9532 9533 if (a2dp->exist) { 9534 p += scnprintf(p, end - p, 9535 " %-15s : a2dp_ept:%d, a2dp_late:%d", 9536 "[a2dp_t_sta]", 9537 le16_to_cpu(pcysta->a2dp_ept.cnt), 9538 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 9539 9540 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 9541 le16_to_cpu(pcysta->a2dp_ept.tavg), 9542 le16_to_cpu(pcysta->a2dp_ept.tmax)); 9543 9544 p += scnprintf(p, end - p, "\n"); 9545 } 9546 9547 out: 9548 return p - buf; 9549 } 9550 9551 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9552 { 9553 struct rtw89_btc *btc = &rtwdev->btc; 9554 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 9555 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9556 struct rtw89_btc_dm *dm = &btc->dm; 9557 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 9558 struct rtw89_btc_fbtc_cysta_v5 *pcysta; 9559 struct rtw89_btc_rpt_cmn_info *pcinfo; 9560 u8 i, cnt = 0, slot_pair, divide_cnt; 9561 u16 cycle, c_begin, c_end, store_index; 9562 char *p = buf, *end = buf + bufsz; 9563 9564 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9565 if (!pcinfo->valid) 9566 return 0; 9567 9568 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 9569 p += scnprintf(p, end - p, 9570 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 9571 "[cycle_cnt]", 9572 le16_to_cpu(pcysta->cycles), 9573 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 9574 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 9575 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 9576 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 9577 9578 for (i = 0; i < CXST_MAX; i++) { 9579 if (!le16_to_cpu(pcysta->slot_cnt[i])) 9580 continue; 9581 9582 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 9583 le16_to_cpu(pcysta->slot_cnt[i])); 9584 } 9585 9586 if (dm->tdma_now.rxflctrl) 9587 p += scnprintf(p, end - p, ", leak_rx:%d", 9588 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 9589 9590 if (pcysta->collision_cnt) 9591 p += scnprintf(p, end - p, ", collision:%d", 9592 pcysta->collision_cnt); 9593 9594 if (le16_to_cpu(pcysta->skip_cnt)) 9595 p += scnprintf(p, end - p, ", skip:%d", 9596 le16_to_cpu(pcysta->skip_cnt)); 9597 9598 p += scnprintf(p, end - p, "\n"); 9599 9600 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9601 "[cycle_time]", 9602 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 9603 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 9604 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 9605 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 9606 p += scnprintf(p, end - p, 9607 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 9608 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 9609 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 9610 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 9611 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 9612 9613 cycle = le16_to_cpu(pcysta->cycles); 9614 if (cycle <= 1) 9615 goto out; 9616 9617 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 9618 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 9619 9620 if (cycle <= slot_pair) 9621 c_begin = 1; 9622 else 9623 c_begin = cycle - slot_pair + 1; 9624 9625 c_end = cycle; 9626 9627 if (a2dp->exist) 9628 divide_cnt = 3; 9629 else 9630 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 9631 9632 if (c_begin > c_end) 9633 goto out; 9634 9635 for (cycle = c_begin; cycle <= c_end; cycle++) { 9636 cnt++; 9637 store_index = ((cycle - 1) % slot_pair) * 2; 9638 9639 if (cnt % divide_cnt == 1) 9640 p += scnprintf(p, end - p, " %-15s : ", 9641 "[cycle_step]"); 9642 9643 p += scnprintf(p, end - p, "->b%02d", 9644 le16_to_cpu(pcysta->slot_step_time[store_index])); 9645 if (a2dp->exist) { 9646 a2dp_trx = &pcysta->a2dp_trx[store_index]; 9647 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 9648 a2dp_trx->empty_cnt, 9649 a2dp_trx->retry_cnt, 9650 a2dp_trx->tx_rate ? 3 : 2, 9651 a2dp_trx->tx_cnt, 9652 a2dp_trx->ack_cnt, 9653 a2dp_trx->nack_cnt); 9654 } 9655 p += scnprintf(p, end - p, "->w%02d", 9656 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 9657 if (a2dp->exist) { 9658 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 9659 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 9660 a2dp_trx->empty_cnt, 9661 a2dp_trx->retry_cnt, 9662 a2dp_trx->tx_rate ? 3 : 2, 9663 a2dp_trx->tx_cnt, 9664 a2dp_trx->ack_cnt, 9665 a2dp_trx->nack_cnt); 9666 } 9667 if (cnt % divide_cnt == 0 || cnt == c_end) 9668 p += scnprintf(p, end - p, "\n"); 9669 } 9670 9671 if (a2dp->exist) { 9672 p += scnprintf(p, end - p, 9673 " %-15s : a2dp_ept:%d, a2dp_late:%d", 9674 "[a2dp_t_sta]", 9675 le16_to_cpu(pcysta->a2dp_ept.cnt), 9676 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 9677 9678 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 9679 le16_to_cpu(pcysta->a2dp_ept.tavg), 9680 le16_to_cpu(pcysta->a2dp_ept.tmax)); 9681 9682 p += scnprintf(p, end - p, "\n"); 9683 } 9684 9685 out: 9686 return p - buf; 9687 } 9688 9689 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9690 { 9691 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt; 9692 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc; 9693 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 9694 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL; 9695 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 9696 struct rtw89_btc_rpt_cmn_info *pcinfo; 9697 char *p = buf, *end = buf + bufsz; 9698 u16 cycle, c_begin, c_end, s_id; 9699 u8 i, cnt = 0, divide_cnt; 9700 u8 slot_pair; 9701 9702 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9703 if (!pcinfo->valid) 9704 return 0; 9705 9706 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 9707 p += scnprintf(p, end - p, "\n\r %-15s : cycle:%d", "[slot_stat]", 9708 le16_to_cpu(pcysta->cycles)); 9709 9710 for (i = 0; i < CXST_MAX; i++) { 9711 if (!le16_to_cpu(pcysta->slot_cnt[i])) 9712 continue; 9713 p += scnprintf(p, end - p, ", %s:%d", 9714 id_to_slot(i), 9715 le16_to_cpu(pcysta->slot_cnt[i])); 9716 } 9717 9718 if (dm->tdma_now.rxflctrl) 9719 p += scnprintf(p, end - p, ", leak_rx:%d", 9720 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 9721 9722 if (pcysta->collision_cnt) 9723 p += scnprintf(p, end - p, ", collision:%d", 9724 pcysta->collision_cnt); 9725 9726 if (pcysta->skip_cnt) 9727 p += scnprintf(p, end - p, ", skip:%d", 9728 le16_to_cpu(pcysta->skip_cnt)); 9729 9730 p += scnprintf(p, end - p, 9731 "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9732 "[cycle_stat]", 9733 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 9734 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 9735 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 9736 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 9737 p += scnprintf(p, end - p, 9738 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]", 9739 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 9740 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 9741 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD], 9742 le16_to_cpu(pcysta->leak_slot.tamx) / 1000, 9743 le16_to_cpu(pcysta->leak_slot.tamx) % 1000); 9744 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]", 9745 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 9746 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 9747 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 9748 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 9749 9750 if (a2dp->exist) { 9751 p += scnprintf(p, end - p, 9752 "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", 9753 "[a2dp_stat]", 9754 le16_to_cpu(pcysta->a2dp_ept.cnt), 9755 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout), 9756 a2dp->no_empty_streak_2s, 9757 a2dp->no_empty_streak_max); 9758 9759 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 9760 le16_to_cpu(pcysta->a2dp_ept.tavg), 9761 le16_to_cpu(pcysta->a2dp_ept.tmax)); 9762 } 9763 9764 if (le16_to_cpu(pcysta->cycles) <= 1) 9765 goto out; 9766 9767 /* 1 cycle = 1 wl-slot + 1 bt-slot */ 9768 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 9769 9770 if (le16_to_cpu(pcysta->cycles) <= slot_pair) 9771 c_begin = 1; 9772 else 9773 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1; 9774 9775 c_end = le16_to_cpu(pcysta->cycles); 9776 9777 if (a2dp->exist) 9778 divide_cnt = 2; 9779 else 9780 divide_cnt = 6; 9781 9782 if (c_begin > c_end) 9783 goto out; 9784 9785 for (cycle = c_begin; cycle <= c_end; cycle++) { 9786 cnt++; 9787 s_id = ((cycle - 1) % slot_pair) * 2; 9788 9789 if (cnt % divide_cnt == 1) { 9790 if (a2dp->exist) 9791 p += scnprintf(p, end - p, "\n\r %-15s : ", 9792 "[slotT_wermtan]"); 9793 else 9794 p += scnprintf(p, end - p, "\n\r %-15s : ", 9795 "[slotT_rxerr]"); 9796 } 9797 9798 p += scnprintf(p, end - p, "->b%d", 9799 le16_to_cpu(pcysta->slot_step_time[s_id])); 9800 9801 if (a2dp->exist) 9802 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 9803 pcysta->wl_rx_err_ratio[s_id], 9804 pcysta->a2dp_trx[s_id].empty_cnt, 9805 pcysta->a2dp_trx[s_id].retry_cnt, 9806 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2), 9807 pcysta->a2dp_trx[s_id].tx_cnt, 9808 pcysta->a2dp_trx[s_id].ack_cnt, 9809 pcysta->a2dp_trx[s_id].nack_cnt); 9810 else 9811 p += scnprintf(p, end - p, "(%d)", 9812 pcysta->wl_rx_err_ratio[s_id]); 9813 9814 p += scnprintf(p, end - p, "->w%d", 9815 le16_to_cpu(pcysta->slot_step_time[s_id + 1])); 9816 9817 if (a2dp->exist) 9818 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 9819 pcysta->wl_rx_err_ratio[s_id + 1], 9820 pcysta->a2dp_trx[s_id + 1].empty_cnt, 9821 pcysta->a2dp_trx[s_id + 1].retry_cnt, 9822 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2), 9823 pcysta->a2dp_trx[s_id + 1].tx_cnt, 9824 pcysta->a2dp_trx[s_id + 1].ack_cnt, 9825 pcysta->a2dp_trx[s_id + 1].nack_cnt); 9826 else 9827 p += scnprintf(p, end - p, "(%d)", 9828 pcysta->wl_rx_err_ratio[s_id + 1]); 9829 } 9830 9831 out: 9832 return p - buf; 9833 } 9834 9835 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9836 { 9837 struct rtw89_btc *btc = &rtwdev->btc; 9838 const struct rtw89_btc_ver *ver = btc->ver; 9839 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9840 struct rtw89_btc_rpt_cmn_info *pcinfo; 9841 union rtw89_btc_fbtc_cynullsta_info *ns; 9842 char *p = buf, *end = buf + bufsz; 9843 u8 i = 0; 9844 9845 if (!btc->dm.tdma_now.rxflctrl) 9846 return 0; 9847 9848 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 9849 if (!pcinfo->valid) 9850 return 0; 9851 9852 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 9853 if (ver->fcxnullsta == 1) { 9854 for (i = 0; i < 2; i++) { 9855 p += scnprintf(p, end - p, " %-15s : ", "[NULL-STA]"); 9856 p += scnprintf(p, end - p, "null-%d", i); 9857 p += scnprintf(p, end - p, "[ok:%d/", 9858 le32_to_cpu(ns->v1.result[i][1])); 9859 p += scnprintf(p, end - p, "fail:%d/", 9860 le32_to_cpu(ns->v1.result[i][0])); 9861 p += scnprintf(p, end - p, "on_time:%d/", 9862 le32_to_cpu(ns->v1.result[i][2])); 9863 p += scnprintf(p, end - p, "retry:%d/", 9864 le32_to_cpu(ns->v1.result[i][3])); 9865 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 9866 le32_to_cpu(ns->v1.avg_t[i]) / 1000, 9867 le32_to_cpu(ns->v1.avg_t[i]) % 1000); 9868 p += scnprintf(p, end - p, "max_t:%d.%03d]\n", 9869 le32_to_cpu(ns->v1.max_t[i]) / 1000, 9870 le32_to_cpu(ns->v1.max_t[i]) % 1000); 9871 } 9872 } else if (ver->fcxnullsta == 7) { 9873 for (i = 0; i < 2; i++) { 9874 p += scnprintf(p, end - p, " %-15s : ", "[NULL-STA]"); 9875 p += scnprintf(p, end - p, "null-%d", i); 9876 p += scnprintf(p, end - p, "[Tx:%d/", 9877 le32_to_cpu(ns->v7.result[i][4])); 9878 p += scnprintf(p, end - p, "[ok:%d/", 9879 le32_to_cpu(ns->v7.result[i][1])); 9880 p += scnprintf(p, end - p, "fail:%d/", 9881 le32_to_cpu(ns->v7.result[i][0])); 9882 p += scnprintf(p, end - p, "on_time:%d/", 9883 le32_to_cpu(ns->v7.result[i][2])); 9884 p += scnprintf(p, end - p, "retry:%d/", 9885 le32_to_cpu(ns->v7.result[i][3])); 9886 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 9887 le32_to_cpu(ns->v7.tavg[i]) / 1000, 9888 le32_to_cpu(ns->v7.tavg[i]) % 1000); 9889 p += scnprintf(p, end - p, "max_t:%d.%03d]\n", 9890 le32_to_cpu(ns->v7.tmax[i]) / 1000, 9891 le32_to_cpu(ns->v7.tmax[i]) % 1000); 9892 } 9893 } else { 9894 for (i = 0; i < 2; i++) { 9895 p += scnprintf(p, end - p, " %-15s : ", "[NULL-STA]"); 9896 p += scnprintf(p, end - p, "null-%d", i); 9897 p += scnprintf(p, end - p, "[Tx:%d/", 9898 le32_to_cpu(ns->v2.result[i][4])); 9899 p += scnprintf(p, end - p, "[ok:%d/", 9900 le32_to_cpu(ns->v2.result[i][1])); 9901 p += scnprintf(p, end - p, "fail:%d/", 9902 le32_to_cpu(ns->v2.result[i][0])); 9903 p += scnprintf(p, end - p, "on_time:%d/", 9904 le32_to_cpu(ns->v2.result[i][2])); 9905 p += scnprintf(p, end - p, "retry:%d/", 9906 le32_to_cpu(ns->v2.result[i][3])); 9907 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 9908 le32_to_cpu(ns->v2.avg_t[i]) / 1000, 9909 le32_to_cpu(ns->v2.avg_t[i]) % 1000); 9910 p += scnprintf(p, end - p, "max_t:%d.%03d]\n", 9911 le32_to_cpu(ns->v2.max_t[i]) / 1000, 9912 le32_to_cpu(ns->v2.max_t[i]) % 1000); 9913 } 9914 } 9915 9916 return p - buf; 9917 } 9918 9919 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9920 { 9921 struct rtw89_btc *btc = &rtwdev->btc; 9922 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9923 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 9924 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL; 9925 const struct rtw89_btc_ver *ver = btc->ver; 9926 char *p = buf, *end = buf + bufsz; 9927 u8 type, val, cnt = 0, state = 0; 9928 bool outloop = false; 9929 u16 i, diff_t, n_start = 0, n_stop = 0; 9930 u16 pos_old, pos_new, trace_step; 9931 9932 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 9933 if (!pcinfo->valid) 9934 return 0; 9935 9936 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2; 9937 pos_old = le16_to_cpu(pstep->pos_old); 9938 pos_new = le16_to_cpu(pstep->pos_new); 9939 9940 if (pcinfo->req_fver != pstep->fver) 9941 return 0; 9942 9943 /* store step info by using ring instead of FIFO*/ 9944 do { 9945 switch (state) { 9946 case 0: 9947 if (ver->fcxctrl == 7 || ver->fcxctrl == 1) 9948 trace_step = 50; 9949 else 9950 trace_step = btc->ctrl.ctrl.trace_step; 9951 9952 n_start = pos_old; 9953 if (pos_new >= pos_old) 9954 n_stop = pos_new; 9955 else 9956 n_stop = trace_step - 1; 9957 9958 state = 1; 9959 break; 9960 case 1: 9961 for (i = n_start; i <= n_stop; i++) { 9962 type = pstep->step[i].type; 9963 val = pstep->step[i].val; 9964 diff_t = le16_to_cpu(pstep->step[i].difft); 9965 9966 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 9967 continue; 9968 9969 if (cnt % 10 == 0) 9970 p += scnprintf(p, end - p, 9971 " %-15s : ", "[steps]"); 9972 9973 p += scnprintf(p, end - p, 9974 "-> %s(%02d)(%02d)", 9975 (type == CXSTEP_SLOT ? "SLT" : 9976 "EVT"), (u32)val, diff_t); 9977 if (cnt % 10 == 9) 9978 p += scnprintf(p, end - p, "\n"); 9979 cnt++; 9980 } 9981 9982 state = 2; 9983 break; 9984 case 2: 9985 if (pos_new < pos_old && n_start != 0) { 9986 n_start = 0; 9987 n_stop = pos_new; 9988 state = 1; 9989 } else { 9990 outloop = true; 9991 } 9992 break; 9993 } 9994 } while (!outloop); 9995 9996 return p - buf; 9997 } 9998 9999 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10000 { 10001 struct rtw89_btc *btc = &rtwdev->btc; 10002 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10003 struct rtw89_btc_rpt_cmn_info *pcinfo; 10004 struct rtw89_btc_fbtc_steps_v3 *pstep; 10005 u32 i, n_begin, n_end, array_idx, cnt = 0; 10006 char *p = buf, *end = buf + bufsz; 10007 u8 type, val; 10008 u16 diff_t; 10009 10010 if ((pfwinfo->rpt_en_map & 10011 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0) 10012 return 0; 10013 10014 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 10015 if (!pcinfo->valid) 10016 return 0; 10017 10018 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3; 10019 if (pcinfo->req_fver != pstep->fver) 10020 return 0; 10021 10022 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP) 10023 n_begin = 1; 10024 else 10025 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1; 10026 10027 n_end = le32_to_cpu(pstep->cnt); 10028 10029 if (n_begin > n_end) 10030 return 0; 10031 10032 /* restore step info by using ring instead of FIFO */ 10033 for (i = n_begin; i <= n_end; i++) { 10034 array_idx = (i - 1) % FCXDEF_STEP; 10035 type = pstep->step[array_idx].type; 10036 val = pstep->step[array_idx].val; 10037 diff_t = le16_to_cpu(pstep->step[array_idx].difft); 10038 10039 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 10040 continue; 10041 10042 if (cnt % 10 == 0) 10043 p += scnprintf(p, end - p, " %-15s : ", "[steps]"); 10044 10045 p += scnprintf(p, end - p, "-> %s(%02d)", 10046 (type == CXSTEP_SLOT ? 10047 id_to_slot((u32)val) : 10048 id_to_evt((u32)val)), diff_t); 10049 10050 if (cnt % 10 == 9) 10051 p += scnprintf(p, end - p, "\n"); 10052 10053 cnt++; 10054 } 10055 10056 return p - buf; 10057 } 10058 10059 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10060 { 10061 struct rtw89_btc *btc = &rtwdev->btc; 10062 const struct rtw89_btc_ver *ver = btc->ver; 10063 char *p = buf, *end = buf + bufsz; 10064 10065 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 10066 goto out; 10067 10068 p += _show_error(rtwdev, p, end - p); 10069 p += _show_fbtc_tdma(rtwdev, p, end - p); 10070 p += _show_fbtc_slots(rtwdev, p, end - p); 10071 10072 if (ver->fcxcysta == 2) 10073 p += _show_fbtc_cysta_v2(rtwdev, p, end - p); 10074 else if (ver->fcxcysta == 3) 10075 p += _show_fbtc_cysta_v3(rtwdev, p, end - p); 10076 else if (ver->fcxcysta == 4) 10077 p += _show_fbtc_cysta_v4(rtwdev, p, end - p); 10078 else if (ver->fcxcysta == 5) 10079 p += _show_fbtc_cysta_v5(rtwdev, p, end - p); 10080 else if (ver->fcxcysta == 7) 10081 p += _show_fbtc_cysta_v7(rtwdev, p, end - p); 10082 10083 p += _show_fbtc_nullsta(rtwdev, p, end - p); 10084 10085 if (ver->fcxstep == 2) 10086 p += _show_fbtc_step_v2(rtwdev, p, end - p); 10087 else if (ver->fcxstep == 3) 10088 p += _show_fbtc_step_v3(rtwdev, p, end - p); 10089 10090 out: 10091 return p - buf; 10092 } 10093 10094 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 10095 { 10096 const struct rtw89_chip_info *chip = rtwdev->chip; 10097 struct rtw89_mac_ax_gnt *gnt; 10098 u32 val, status; 10099 10100 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || 10101 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) { 10102 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 10103 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 10104 10105 gnt = &gnt_cfg->band[0]; 10106 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 10107 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 10108 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 10109 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 10110 10111 gnt = &gnt_cfg->band[1]; 10112 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 10113 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 10114 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 10115 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 10116 } else if (chip->chip_id == RTL8852C) { 10117 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 10118 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 10119 10120 gnt = &gnt_cfg->band[0]; 10121 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 10122 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 10123 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 10124 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 10125 10126 gnt = &gnt_cfg->band[1]; 10127 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 10128 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 10129 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 10130 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 10131 } else { 10132 return; 10133 } 10134 } 10135 10136 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10137 { 10138 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 10139 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 10140 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10141 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 10142 char *p = buf, *end = buf + bufsz; 10143 u8 *gpio_map, i; 10144 u32 en_map; 10145 10146 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 10147 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo; 10148 if (!pcinfo->valid) { 10149 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10150 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 10151 __func__); 10152 p += scnprintf(p, end - p, "\n"); 10153 goto out; 10154 } 10155 10156 if (ver->fcxgpiodbg == 7) { 10157 en_map = le32_to_cpu(gdbg->v7.en_map); 10158 gpio_map = gdbg->v7.gpio_map; 10159 } else { 10160 en_map = le32_to_cpu(gdbg->v1.en_map); 10161 gpio_map = gdbg->v1.gpio_map; 10162 } 10163 10164 if (!en_map) 10165 goto out; 10166 10167 p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x", 10168 "[gpio_dbg]", en_map); 10169 10170 for (i = 0; i < BTC_DBG_MAX1; i++) { 10171 if (!(en_map & BIT(i))) 10172 continue; 10173 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i), 10174 gpio_map[i]); 10175 } 10176 p += scnprintf(p, end - p, "\n"); 10177 10178 out: 10179 return p - buf; 10180 } 10181 10182 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10183 { 10184 const struct rtw89_chip_info *chip = rtwdev->chip; 10185 struct rtw89_btc *btc = &rtwdev->btc; 10186 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10187 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10188 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL; 10189 struct rtw89_btc_cx *cx = &btc->cx; 10190 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10191 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 10192 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 10193 struct rtw89_mac_ax_gnt gnt; 10194 char *p = buf, *end = buf + bufsz; 10195 u8 i = 0, type = 0, cnt = 0; 10196 u32 val, offset; 10197 10198 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 10199 return 0; 10200 10201 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 10202 10203 p += scnprintf(p, end - p, 10204 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 10205 "[scoreboard]", wl->scbd, 10206 cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 10207 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 10208 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 10209 10210 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 10211 _get_gnt(rtwdev, &gnt_cfg); 10212 10213 gnt = gnt_cfg.band[0]; 10214 p += scnprintf(p, end - p, 10215 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 10216 "[gnt_status]", 10217 chip->chip_id == RTL8852C ? "HW" : 10218 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 10219 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 10220 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 10221 10222 gnt = gnt_cfg.band[1]; 10223 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 10224 gnt.gnt_wl_sw_en ? "SW" : "HW", 10225 gnt.gnt_wl, 10226 gnt.gnt_bt_sw_en ? "SW" : "HW", 10227 gnt.gnt_bt); 10228 10229 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 10230 if (!pcinfo->valid) { 10231 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10232 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 10233 __func__); 10234 goto out; 10235 } 10236 10237 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 10238 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10239 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 10240 __func__, pmreg->reg_num); 10241 10242 for (i = 0; i < pmreg->reg_num; i++) { 10243 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 10244 offset = le32_to_cpu(chip->mon_reg[i].offset); 10245 val = le32_to_cpu(pmreg->mreg_val[i]); 10246 10247 if (cnt % 6 == 0) 10248 p += scnprintf(p, end - p, 10249 " %-15s : %d_0x%04x=0x%08x", 10250 "[reg]", (u32)type, offset, val); 10251 else 10252 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 10253 (u32)type, 10254 offset, val); 10255 if (cnt % 6 == 5) 10256 p += scnprintf(p, end - p, "\n"); 10257 cnt++; 10258 10259 if (i >= pmreg->reg_num) 10260 p += scnprintf(p, end - p, "\n"); 10261 } 10262 10263 out: 10264 return p - buf; 10265 } 10266 10267 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10268 { 10269 const struct rtw89_chip_info *chip = rtwdev->chip; 10270 struct rtw89_btc *btc = &rtwdev->btc; 10271 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10272 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10273 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL; 10274 struct rtw89_btc_cx *cx = &btc->cx; 10275 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10276 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 10277 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 10278 struct rtw89_mac_ax_gnt gnt; 10279 char *p = buf, *end = buf + bufsz; 10280 u8 i = 0, type = 0, cnt = 0; 10281 u32 val, offset; 10282 10283 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 10284 return 0; 10285 10286 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 10287 10288 p += scnprintf(p, end - p, 10289 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 10290 "[scoreboard]", wl->scbd, 10291 cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 10292 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 10293 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 10294 10295 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 10296 _get_gnt(rtwdev, &gnt_cfg); 10297 10298 gnt = gnt_cfg.band[0]; 10299 p += scnprintf(p, end - p, 10300 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s", 10301 "[gnt_status]", 10302 chip->chip_id == RTL8852C ? "HW" : 10303 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 10304 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 10305 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt, 10306 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 10307 10308 gnt = gnt_cfg.band[1]; 10309 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 10310 gnt.gnt_wl_sw_en ? "SW" : "HW", 10311 gnt.gnt_wl, 10312 gnt.gnt_bt_sw_en ? "SW" : "HW", 10313 gnt.gnt_bt); 10314 10315 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 10316 if (!pcinfo->valid) { 10317 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10318 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 10319 __func__); 10320 goto out; 10321 } 10322 10323 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 10324 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10325 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 10326 __func__, pmreg->reg_num); 10327 10328 for (i = 0; i < pmreg->reg_num; i++) { 10329 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 10330 offset = le32_to_cpu(chip->mon_reg[i].offset); 10331 val = le32_to_cpu(pmreg->mreg_val[i]); 10332 10333 if (cnt % 6 == 0) 10334 p += scnprintf(p, end - p, 10335 " %-15s : %d_0x%04x=0x%08x", 10336 "[reg]", (u32)type, offset, val); 10337 else 10338 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 10339 (u32)type, 10340 offset, val); 10341 if (cnt % 6 == 5) 10342 p += scnprintf(p, end - p, "\n"); 10343 cnt++; 10344 10345 if (i >= pmreg->reg_num) 10346 p += scnprintf(p, end - p, "\n"); 10347 } 10348 10349 out: 10350 return p - buf; 10351 } 10352 10353 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10354 { 10355 struct rtw89_btc *btc = &rtwdev->btc; 10356 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10357 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL; 10358 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10359 struct rtw89_btc_cx *cx = &btc->cx; 10360 struct rtw89_btc_wl_info *wl = &cx->wl; 10361 struct rtw89_btc_bt_info *bt = &cx->bt; 10362 struct rtw89_mac_ax_gnt *gnt = NULL; 10363 struct rtw89_btc_dm *dm = &btc->dm; 10364 char *p = buf, *end = buf + bufsz; 10365 u8 i, type, cnt = 0; 10366 u32 val, offset; 10367 10368 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG)) 10369 return 0; 10370 10371 p += scnprintf(p, end - p, "\n\r========== [HW Status] =========="); 10372 10373 p += scnprintf(p, end - p, 10374 "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)", 10375 "[scoreboard]", wl->scbd, 10376 cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 10377 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 10378 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 10379 10380 /* To avoid I/O if WL LPS or power-off */ 10381 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 10382 10383 p += scnprintf(p, end - p, 10384 "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s", 10385 "[gnt_status]", 10386 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" : 10387 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 10388 wl->pta_req_mac, 10389 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 10390 10391 gnt = &dm->gnt.band[RTW89_PHY_0]; 10392 10393 p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]", 10394 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl, 10395 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt); 10396 10397 if (rtwdev->dbcc_en) { 10398 gnt = &dm->gnt.band[RTW89_PHY_1]; 10399 p += scnprintf(p, end - p, 10400 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]", 10401 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl, 10402 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt); 10403 } 10404 10405 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 10406 if (!pcinfo->valid) 10407 goto out; 10408 10409 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 10410 10411 for (i = 0; i < pmreg->reg_num; i++) { 10412 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type); 10413 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset); 10414 val = le32_to_cpu(pmreg->mreg_val[i]); 10415 10416 if (cnt % 6 == 0) 10417 p += scnprintf(p, end - p, 10418 "\n\r %-15s : %s_0x%x=0x%x", "[reg]", 10419 id_to_regtype(type), offset, val); 10420 else 10421 p += scnprintf(p, end - p, ", %s_0x%x=0x%x", 10422 id_to_regtype(type), offset, val); 10423 cnt++; 10424 } 10425 p += scnprintf(p, end - p, "\n"); 10426 10427 out: 10428 return p - buf; 10429 } 10430 10431 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10432 { 10433 struct rtw89_btc *btc = &rtwdev->btc; 10434 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10435 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10436 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL; 10437 struct rtw89_btc_cx *cx = &btc->cx; 10438 struct rtw89_btc_dm *dm = &btc->dm; 10439 struct rtw89_btc_wl_info *wl = &cx->wl; 10440 struct rtw89_btc_bt_info *bt = &cx->bt; 10441 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 10442 char *p = buf, *end = buf + bufsz; 10443 u8 i; 10444 10445 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 10446 return 0; 10447 10448 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 10449 10450 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 10451 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 10452 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1; 10453 10454 p += scnprintf(p, end - p, 10455 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 10456 "[summary]", pfwinfo->cnt_h2c, 10457 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 10458 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 10459 10460 p += scnprintf(p, end - p, 10461 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 10462 pfwinfo->event[BTF_EVNT_RPT], 10463 prptctrl->rpt_cnt, 10464 prptctrl->rpt_enable, dm->error.val); 10465 10466 if (dm->error.map.wl_fw_hang) 10467 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 10468 p += scnprintf(p, end - p, "\n"); 10469 p += scnprintf(p, end - p, 10470 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 10471 "[mailbox]", prptctrl->mb_send_ok_cnt, 10472 prptctrl->mb_send_fail_cnt, 10473 prptctrl->mb_recv_cnt); 10474 10475 p += scnprintf(p, end - p, 10476 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 10477 prptctrl->mb_a2dp_empty_cnt, 10478 prptctrl->mb_a2dp_flct_cnt, 10479 prptctrl->mb_a2dp_full_cnt); 10480 10481 p += scnprintf(p, end - p, 10482 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 10483 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 10484 cx->cnt_wl[BTC_WCNT_RFK_GO], 10485 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 10486 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 10487 10488 p += scnprintf(p, end - p, 10489 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 10490 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 10491 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 10492 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 10493 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 10494 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 10495 10496 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 10497 bt->rfk_info.map.timeout = 1; 10498 else 10499 bt->rfk_info.map.timeout = 0; 10500 10501 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 10502 } else { 10503 p += scnprintf(p, end - p, 10504 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 10505 "[summary]", pfwinfo->cnt_h2c, 10506 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 10507 pfwinfo->event[BTF_EVNT_RPT], 10508 btc->fwinfo.rpt_en_map); 10509 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 10510 } 10511 10512 for (i = 0; i < BTC_NCNT_NUM; i++) 10513 cnt_sum += dm->cnt_notify[i]; 10514 10515 p += scnprintf(p, end - p, 10516 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 10517 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 10518 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 10519 10520 p += scnprintf(p, end - p, 10521 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 10522 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 10523 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 10524 cnt[BTC_NCNT_WL_STA]); 10525 10526 p += scnprintf(p, end - p, 10527 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 10528 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 10529 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 10530 cnt[BTC_NCNT_SPECIAL_PACKET]); 10531 10532 p += scnprintf(p, end - p, 10533 "timer=%d, control=%d, customerize=%d\n", 10534 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 10535 cnt[BTC_NCNT_CUSTOMERIZE]); 10536 10537 return p - buf; 10538 } 10539 10540 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10541 { 10542 struct rtw89_btc *btc = &rtwdev->btc; 10543 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10544 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl; 10545 struct rtw89_btc_rpt_cmn_info *pcinfo; 10546 struct rtw89_btc_cx *cx = &btc->cx; 10547 struct rtw89_btc_dm *dm = &btc->dm; 10548 struct rtw89_btc_wl_info *wl = &cx->wl; 10549 struct rtw89_btc_bt_info *bt = &cx->bt; 10550 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 10551 char *p = buf, *end = buf + bufsz; 10552 u8 i; 10553 10554 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 10555 return 0; 10556 10557 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 10558 10559 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 10560 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 10561 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4; 10562 10563 p += scnprintf(p, end - p, 10564 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 10565 "[summary]", pfwinfo->cnt_h2c, 10566 pfwinfo->cnt_h2c_fail, 10567 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 10568 pfwinfo->cnt_c2h, 10569 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 10570 10571 p += scnprintf(p, end - p, 10572 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 10573 pfwinfo->event[BTF_EVNT_RPT], 10574 le32_to_cpu(prptctrl->rpt_info.cnt), 10575 le32_to_cpu(prptctrl->rpt_info.en), 10576 dm->error.val); 10577 10578 if (dm->error.map.wl_fw_hang) 10579 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 10580 p += scnprintf(p, end - p, "\n"); 10581 p += scnprintf(p, end - p, 10582 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 10583 "[mailbox]", 10584 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 10585 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 10586 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 10587 10588 p += scnprintf(p, end - p, 10589 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 10590 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 10591 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 10592 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 10593 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 10594 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 10595 10596 p += scnprintf(p, end - p, 10597 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 10598 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 10599 cx->cnt_wl[BTC_WCNT_RFK_GO], 10600 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 10601 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 10602 10603 p += scnprintf(p, end - p, 10604 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 10605 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 10606 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 10607 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 10608 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 10609 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 10610 10611 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 10612 bt->rfk_info.map.timeout = 1; 10613 else 10614 bt->rfk_info.map.timeout = 0; 10615 10616 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 10617 } else { 10618 p += scnprintf(p, end - p, 10619 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 10620 "[summary]", pfwinfo->cnt_h2c, 10621 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 10622 pfwinfo->event[BTF_EVNT_RPT], 10623 btc->fwinfo.rpt_en_map); 10624 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 10625 } 10626 10627 for (i = 0; i < BTC_NCNT_NUM; i++) 10628 cnt_sum += dm->cnt_notify[i]; 10629 10630 p += scnprintf(p, end - p, 10631 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 10632 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 10633 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 10634 10635 p += scnprintf(p, end - p, 10636 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 10637 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 10638 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 10639 cnt[BTC_NCNT_WL_STA]); 10640 10641 p += scnprintf(p, end - p, 10642 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 10643 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 10644 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 10645 cnt[BTC_NCNT_SPECIAL_PACKET]); 10646 10647 p += scnprintf(p, end - p, 10648 "timer=%d, control=%d, customerize=%d\n", 10649 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 10650 cnt[BTC_NCNT_CUSTOMERIZE]); 10651 10652 return p - buf; 10653 } 10654 10655 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10656 { 10657 struct rtw89_btc *btc = &rtwdev->btc; 10658 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10659 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl; 10660 struct rtw89_btc_rpt_cmn_info *pcinfo; 10661 struct rtw89_btc_cx *cx = &btc->cx; 10662 struct rtw89_btc_dm *dm = &btc->dm; 10663 struct rtw89_btc_wl_info *wl = &cx->wl; 10664 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 10665 char *p = buf, *end = buf + bufsz; 10666 u8 i; 10667 10668 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 10669 return 0; 10670 10671 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 10672 10673 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 10674 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 10675 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5; 10676 10677 p += scnprintf(p, end - p, 10678 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 10679 "[summary]", pfwinfo->cnt_h2c, 10680 pfwinfo->cnt_h2c_fail, 10681 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 10682 pfwinfo->cnt_c2h, 10683 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 10684 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 10685 10686 p += scnprintf(p, end - p, 10687 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 10688 pfwinfo->event[BTF_EVNT_RPT], 10689 le16_to_cpu(prptctrl->rpt_info.cnt), 10690 le32_to_cpu(prptctrl->rpt_info.en)); 10691 10692 if (dm->error.map.wl_fw_hang) 10693 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 10694 p += scnprintf(p, end - p, "\n"); 10695 p += scnprintf(p, end - p, 10696 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 10697 "[mailbox]", 10698 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 10699 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 10700 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 10701 10702 p += scnprintf(p, end - p, 10703 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 10704 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 10705 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 10706 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 10707 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 10708 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 10709 10710 p += scnprintf(p, end - p, 10711 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 10712 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 10713 cx->cnt_wl[BTC_WCNT_RFK_GO], 10714 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 10715 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 10716 10717 p += scnprintf(p, end - p, 10718 ", bt_rfk[req:%d]", 10719 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 10720 10721 p += scnprintf(p, end - p, 10722 ", AOAC[RF_on:%d/RF_off:%d]", 10723 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 10724 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 10725 } else { 10726 p += scnprintf(p, end - p, 10727 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 10728 "[summary]", pfwinfo->cnt_h2c, 10729 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 10730 } 10731 10732 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 10733 pfwinfo->err[BTFRE_EXCEPTION]) { 10734 p += scnprintf(p, end - p, "\n"); 10735 p += scnprintf(p, end - p, 10736 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 10737 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 10738 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 10739 pfwinfo->fver_mismch, 10740 pfwinfo->err[BTFRE_EXCEPTION], 10741 wl->status.map.lps, wl->status.map.rf_off); 10742 } 10743 10744 for (i = 0; i < BTC_NCNT_NUM; i++) 10745 cnt_sum += dm->cnt_notify[i]; 10746 10747 p += scnprintf(p, end - p, "\n"); 10748 p += scnprintf(p, end - p, 10749 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 10750 "[notify_cnt]", 10751 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 10752 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 10753 10754 p += scnprintf(p, end - p, 10755 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 10756 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 10757 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 10758 cnt[BTC_NCNT_WL_STA]); 10759 10760 p += scnprintf(p, end - p, "\n"); 10761 p += scnprintf(p, end - p, 10762 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 10763 "[notify_cnt]", 10764 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 10765 cnt[BTC_NCNT_SWITCH_BAND], 10766 cnt[BTC_NCNT_SPECIAL_PACKET]); 10767 10768 p += scnprintf(p, end - p, 10769 "timer=%d, control=%d, customerize=%d", 10770 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 10771 cnt[BTC_NCNT_CUSTOMERIZE]); 10772 10773 return p - buf; 10774 } 10775 10776 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10777 { 10778 struct rtw89_btc *btc = &rtwdev->btc; 10779 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10780 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl; 10781 struct rtw89_btc_rpt_cmn_info *pcinfo; 10782 struct rtw89_btc_cx *cx = &btc->cx; 10783 struct rtw89_btc_dm *dm = &btc->dm; 10784 struct rtw89_btc_wl_info *wl = &cx->wl; 10785 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 10786 char *p = buf, *end = buf + bufsz; 10787 u8 i; 10788 10789 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 10790 return 0; 10791 10792 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 10793 10794 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 10795 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 10796 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105; 10797 10798 p += scnprintf(p, end - p, 10799 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 10800 "[summary]", pfwinfo->cnt_h2c, 10801 pfwinfo->cnt_h2c_fail, 10802 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 10803 pfwinfo->cnt_c2h, 10804 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 10805 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 10806 10807 p += scnprintf(p, end - p, 10808 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 10809 pfwinfo->event[BTF_EVNT_RPT], 10810 le16_to_cpu(prptctrl->rpt_info.cnt), 10811 le32_to_cpu(prptctrl->rpt_info.en)); 10812 10813 if (dm->error.map.wl_fw_hang) 10814 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 10815 p += scnprintf(p, end - p, "\n"); 10816 p += scnprintf(p, end - p, 10817 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 10818 "[mailbox]", 10819 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 10820 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 10821 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 10822 10823 p += scnprintf(p, end - p, 10824 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 10825 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 10826 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 10827 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 10828 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 10829 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 10830 10831 p += scnprintf(p, end - p, 10832 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 10833 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 10834 cx->cnt_wl[BTC_WCNT_RFK_GO], 10835 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 10836 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 10837 10838 p += scnprintf(p, end - p, 10839 ", bt_rfk[req:%d]", 10840 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 10841 10842 p += scnprintf(p, end - p, 10843 ", AOAC[RF_on:%d/RF_off:%d]", 10844 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 10845 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 10846 } else { 10847 p += scnprintf(p, end - p, 10848 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 10849 "[summary]", pfwinfo->cnt_h2c, 10850 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 10851 } 10852 10853 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 10854 pfwinfo->err[BTFRE_EXCEPTION]) { 10855 p += scnprintf(p, end - p, "\n"); 10856 p += scnprintf(p, end - p, 10857 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 10858 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 10859 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 10860 pfwinfo->fver_mismch, 10861 pfwinfo->err[BTFRE_EXCEPTION], 10862 wl->status.map.lps, wl->status.map.rf_off); 10863 } 10864 10865 for (i = 0; i < BTC_NCNT_NUM; i++) 10866 cnt_sum += dm->cnt_notify[i]; 10867 10868 p += scnprintf(p, end - p, "\n"); 10869 p += scnprintf(p, end - p, 10870 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 10871 "[notify_cnt]", 10872 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 10873 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 10874 10875 p += scnprintf(p, end - p, 10876 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 10877 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 10878 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 10879 cnt[BTC_NCNT_WL_STA]); 10880 10881 p += scnprintf(p, end - p, "\n"); 10882 p += scnprintf(p, end - p, 10883 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 10884 "[notify_cnt]", 10885 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 10886 cnt[BTC_NCNT_SWITCH_BAND], 10887 cnt[BTC_NCNT_SPECIAL_PACKET]); 10888 10889 p += scnprintf(p, end - p, 10890 "timer=%d, control=%d, customerize=%d", 10891 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 10892 cnt[BTC_NCNT_CUSTOMERIZE]); 10893 10894 return p - buf; 10895 } 10896 10897 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10898 { 10899 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 10900 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL; 10901 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10902 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 10903 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 10904 struct rtw89_btc_wl_info *wl = &cx->wl; 10905 u32 *cnt = rtwdev->btc.dm.cnt_notify; 10906 char *p = buf, *end = buf + bufsz; 10907 u32 cnt_sum = 0; 10908 u8 i; 10909 10910 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 10911 return 0; 10912 10913 p += scnprintf(p, end - p, "%s", 10914 "\n\r========== [Statistics] =========="); 10915 10916 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 10917 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 10918 !wl->status.map.rf_off) { 10919 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7; 10920 10921 p += scnprintf(p, end - p, 10922 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d)," 10923 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ", 10924 "[summary]", pfwinfo->cnt_h2c, 10925 pfwinfo->cnt_h2c_fail, 10926 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 10927 pfwinfo->cnt_c2h, 10928 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 10929 le16_to_cpu(prptctrl->rpt_info.len_c2h), 10930 rtwdev->btc.ver->info_buf); 10931 10932 p += scnprintf(p, end - p, 10933 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 10934 pfwinfo->event[BTF_EVNT_RPT], 10935 le16_to_cpu(prptctrl->rpt_info.cnt), 10936 le32_to_cpu(prptctrl->rpt_info.en)); 10937 10938 if (dm->error.map.wl_fw_hang) 10939 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 10940 10941 p += scnprintf(p, end - p, 10942 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 10943 "[mailbox]", 10944 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 10945 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 10946 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 10947 10948 p += scnprintf(p, end - p, 10949 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", 10950 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 10951 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 10952 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 10953 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 10954 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 10955 10956 p += scnprintf(p, end - p, 10957 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 10958 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 10959 cx->cnt_wl[BTC_WCNT_RFK_GO], 10960 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 10961 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT], 10962 wl->rfk_info.proc_time); 10963 10964 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 10965 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 10966 10967 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", 10968 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 10969 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 10970 } else { 10971 p += scnprintf(p, end - p, 10972 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", 10973 "[summary]", 10974 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 10975 pfwinfo->cnt_c2h, 10976 wl->status.map.lps, wl->status.map.rf_off); 10977 } 10978 10979 for (i = 0; i < BTC_NCNT_NUM; i++) 10980 cnt_sum += dm->cnt_notify[i]; 10981 10982 p += scnprintf(p, end - p, 10983 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 10984 "[notify_cnt]", 10985 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 10986 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 10987 10988 p += scnprintf(p, end - p, 10989 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 10990 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 10991 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 10992 cnt[BTC_NCNT_WL_STA]); 10993 10994 p += scnprintf(p, end - p, 10995 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 10996 "[notify_cnt]", 10997 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 10998 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 10999 cnt[BTC_NCNT_SPECIAL_PACKET]); 11000 11001 p += scnprintf(p, end - p, 11002 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 11003 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 11004 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 11005 cnt[BTC_NCNT_COUNTRYCODE]); 11006 11007 return p - buf; 11008 } 11009 11010 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11011 { 11012 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 11013 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11014 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL; 11015 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 11016 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 11017 struct rtw89_btc_wl_info *wl = &cx->wl; 11018 u32 *cnt = rtwdev->btc.dm.cnt_notify; 11019 char *p = buf, *end = buf + bufsz; 11020 u32 cnt_sum = 0; 11021 u8 i; 11022 11023 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11024 return 0; 11025 11026 p += scnprintf(p, end - p, "%s", 11027 "\n\r========== [Statistics] =========="); 11028 11029 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11030 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 11031 !wl->status.map.rf_off) { 11032 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8; 11033 11034 p += scnprintf(p, end - p, 11035 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", 11036 "[summary]", pfwinfo->cnt_h2c, 11037 pfwinfo->cnt_h2c_fail, 11038 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 11039 pfwinfo->cnt_c2h, 11040 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 11041 le16_to_cpu(prptctrl->rpt_info.len_c2h), 11042 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l, 11043 rtwdev->btc.ver->info_buf); 11044 11045 p += scnprintf(p, end - p, 11046 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 11047 pfwinfo->event[BTF_EVNT_RPT], 11048 le16_to_cpu(prptctrl->rpt_info.cnt), 11049 le32_to_cpu(prptctrl->rpt_info.en)); 11050 11051 if (dm->error.map.wl_fw_hang) 11052 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11053 11054 p += scnprintf(p, end - p, 11055 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 11056 "[mailbox]", 11057 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 11058 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 11059 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 11060 11061 p += scnprintf(p, end - p, 11062 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", 11063 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 11064 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 11065 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 11066 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 11067 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 11068 11069 p += scnprintf(p, end - p, 11070 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 11071 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11072 cx->cnt_wl[BTC_WCNT_RFK_GO], 11073 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11074 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT], 11075 wl->rfk_info.proc_time); 11076 11077 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 11078 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 11079 11080 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", 11081 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 11082 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 11083 } else { 11084 p += scnprintf(p, end - p, 11085 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", 11086 "[summary]", 11087 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 11088 pfwinfo->cnt_c2h, 11089 wl->status.map.lps, wl->status.map.rf_off); 11090 } 11091 11092 for (i = 0; i < BTC_NCNT_NUM; i++) 11093 cnt_sum += dm->cnt_notify[i]; 11094 11095 p += scnprintf(p, end - p, 11096 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11097 "[notify_cnt]", 11098 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11099 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11100 11101 p += scnprintf(p, end - p, 11102 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 11103 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11104 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11105 cnt[BTC_NCNT_WL_STA]); 11106 11107 p += scnprintf(p, end - p, 11108 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 11109 "[notify_cnt]", 11110 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 11111 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 11112 cnt[BTC_NCNT_SPECIAL_PACKET]); 11113 11114 p += scnprintf(p, end - p, 11115 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 11116 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 11117 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 11118 cnt[BTC_NCNT_COUNTRYCODE]); 11119 11120 return p - buf; 11121 } 11122 11123 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11124 { 11125 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal; 11126 struct rtw89_btc *btc = &rtwdev->btc; 11127 const struct rtw89_btc_ver *ver = btc->ver; 11128 struct rtw89_btc_cx *cx = &btc->cx; 11129 struct rtw89_btc_bt_info *bt = &cx->bt; 11130 char *p = buf, *end = buf + bufsz; 11131 11132 p += scnprintf(p, end - p, 11133 "=========================================\n"); 11134 p += scnprintf(p, end - p, 11135 "WL FW / BT FW %d.%d.%d.%d / NA\n", 11136 fw_suit->major_ver, fw_suit->minor_ver, 11137 fw_suit->sub_ver, fw_suit->sub_idex); 11138 p += scnprintf(p, end - p, "manual %d\n", 11139 btc->manual_ctrl); 11140 11141 p += scnprintf(p, end - p, 11142 "=========================================\n"); 11143 11144 p += scnprintf(p, end - p, 11145 "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)", 11146 "[bt_info]", 11147 bt->raw_info[2], bt->raw_info[3], 11148 bt->raw_info[4], bt->raw_info[5], 11149 bt->raw_info[6], bt->raw_info[7], 11150 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 11151 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 11152 cx->cnt_bt[BTC_BCNT_INFOSAME]); 11153 11154 p += scnprintf(p, end - p, 11155 "\n=========================================\n"); 11156 11157 p += _show_cx_info(rtwdev, p, end - p); 11158 p += _show_wl_info(rtwdev, p, end - p); 11159 p += _show_bt_info(rtwdev, p, end - p); 11160 p += _show_dm_info(rtwdev, p, end - p); 11161 p += _show_fw_dm_msg(rtwdev, p, end - p); 11162 11163 if (ver->fcxmreg == 1) 11164 p += _show_mreg_v1(rtwdev, p, end - p); 11165 else if (ver->fcxmreg == 2) 11166 p += _show_mreg_v2(rtwdev, p, end - p); 11167 else if (ver->fcxmreg == 7) 11168 p += _show_mreg_v7(rtwdev, p, end - p); 11169 11170 p += _show_gpio_dbg(rtwdev, p, end - p); 11171 11172 if (ver->fcxbtcrpt == 1) 11173 p += _show_summary_v1(rtwdev, p, end - p); 11174 else if (ver->fcxbtcrpt == 4) 11175 p += _show_summary_v4(rtwdev, p, end - p); 11176 else if (ver->fcxbtcrpt == 5) 11177 p += _show_summary_v5(rtwdev, p, end - p); 11178 else if (ver->fcxbtcrpt == 105) 11179 p += _show_summary_v105(rtwdev, p, end - p); 11180 else if (ver->fcxbtcrpt == 7) 11181 p += _show_summary_v7(rtwdev, p, end - p); 11182 else if (ver->fcxbtcrpt == 8) 11183 p += _show_summary_v8(rtwdev, p, end - p); 11184 11185 return p - buf; 11186 } 11187 11188 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) 11189 { 11190 const struct rtw89_chip_info *chip = rtwdev->chip; 11191 struct rtw89_btc *btc = &rtwdev->btc; 11192 const struct rtw89_btc_ver *btc_ver_def; 11193 const struct rtw89_fw_suit *fw_suit; 11194 u32 suit_ver_code; 11195 int i; 11196 11197 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); 11198 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); 11199 11200 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) { 11201 btc_ver_def = &rtw89_btc_ver_defs[i]; 11202 11203 if (chip->chip_id != btc_ver_def->chip_id) 11204 continue; 11205 11206 if (suit_ver_code >= btc_ver_def->fw_ver_code) { 11207 btc->ver = btc_ver_def; 11208 goto out; 11209 } 11210 } 11211 11212 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX]; 11213 11214 out: 11215 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", 11216 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); 11217 } 11218 11219 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms) 11220 { 11221 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info; 11222 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 11223 11224 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) 11225 return; 11226 11227 if (!a2dp.exist) 11228 return; 11229 11230 fsleep(ms * 1000); 11231 } 11232 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time); 11233 11234 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state) 11235 { 11236 rtwdev->btc.cx.wl.rfk_info.con_rfk = state; 11237 } 11238 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk); 11239