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