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