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 "ps.h" 10 #include "reg.h" 11 12 #define RTW89_COEX_VERSION 0x07000113 13 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/ 14 15 enum btc_fbtc_tdma_template { 16 CXTD_OFF = 0x0, 17 CXTD_OFF_B2, 18 CXTD_OFF_EXT, 19 CXTD_FIX, 20 CXTD_PFIX, 21 CXTD_AUTO, 22 CXTD_PAUTO, 23 CXTD_AUTO2, 24 CXTD_PAUTO2, 25 CXTD_MAX, 26 }; 27 28 enum btc_fbtc_tdma_type { 29 CXTDMA_OFF = 0x0, 30 CXTDMA_FIX = 0x1, 31 CXTDMA_AUTO = 0x2, 32 CXTDMA_AUTO2 = 0x3, 33 CXTDMA_MAX 34 }; 35 36 enum btc_fbtc_tdma_rx_flow_ctrl { 37 CXFLC_OFF = 0x0, 38 CXFLC_NULLP = 0x1, 39 CXFLC_QOSNULL = 0x2, 40 CXFLC_CTS = 0x3, 41 CXFLC_MAX 42 }; 43 44 enum btc_fbtc_tdma_wlan_tx_pause { 45 CXTPS_OFF = 0x0, /* no wl tx pause*/ 46 CXTPS_ON = 0x1, 47 CXTPS_MAX 48 }; 49 50 enum btc_mlme_state { 51 MLME_NO_LINK, 52 MLME_LINKING, 53 MLME_LINKED, 54 }; 55 56 #define FCXONESLOT_VER 1 57 struct btc_fbtc_1slot { 58 u8 fver; 59 u8 sid; /* slot id */ 60 struct rtw89_btc_fbtc_slot slot; 61 } __packed; 62 63 static const struct rtw89_btc_fbtc_tdma t_def[] = { 64 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 65 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0}, 66 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0}, 67 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 68 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 69 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 70 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 71 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 72 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0} 73 }; 74 75 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \ 76 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \ 77 .cxtype = cpu_to_le16(__cxtype),} 78 79 static const struct rtw89_btc_fbtc_slot s_def[] = { 80 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX), 81 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO), 82 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO), 83 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 84 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 85 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX), 86 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX), 87 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 88 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX), 89 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO), 90 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX), 91 [CXST_E2G] = __DEF_FBTC_SLOT(0, 0xea5a5a5a, SLOT_MIX), 92 [CXST_E5G] = __DEF_FBTC_SLOT(0, 0xffffffff, SLOT_ISO), 93 [CXST_EBT] = __DEF_FBTC_SLOT(0, 0xe5555555, SLOT_MIX), 94 [CXST_ENULL] = __DEF_FBTC_SLOT(0, 0xaaaaaaaa, SLOT_ISO), 95 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), 96 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), 97 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), 98 }; 99 100 static const u32 cxtbl[] = { 101 0xffffffff, /* 0 */ 102 0xaaaaaaaa, /* 1 */ 103 0xe5555555, /* 2 */ 104 0xee555555, /* 3 */ 105 0xd5555555, /* 4 */ 106 0x5a5a5a5a, /* 5 */ 107 0xfa5a5a5a, /* 6 */ 108 0xda5a5a5a, /* 7 */ 109 0xea5a5a5a, /* 8 */ 110 0x6a5a5aaa, /* 9 */ 111 0x6a5a6a5a, /* 10 */ 112 0x6a5a6aaa, /* 11 */ 113 0x6afa5afa, /* 12 */ 114 0xaaaa5aaa, /* 13 */ 115 0xaaffffaa, /* 14 */ 116 0xaa5555aa, /* 15 */ 117 0xfafafafa, /* 16 */ 118 0xffffddff, /* 17 */ 119 0xdaffdaff, /* 18 */ 120 0xfafadafa, /* 19 */ 121 0xea6a6a6a, /* 20 */ 122 0xea55556a, /* 21 */ 123 0xaafafafa, /* 22 */ 124 0xfafaaafa, /* 23 */ 125 0xfafffaff /* 24 */ 126 }; 127 128 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { 129 /* firmware version must be in decreasing order for each chip */ 130 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), 131 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 132 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 133 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 134 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, 135 .info_buf = 1800, .max_role_num = 6, 136 }, 137 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), 138 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 139 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 140 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 141 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, 142 .info_buf = 1280, .max_role_num = 5, 143 }, 144 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), 145 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 146 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 147 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 148 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, 149 .info_buf = 1280, .max_role_num = 5, 150 }, 151 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), 152 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 153 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 154 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 155 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, 156 .info_buf = 1280, .max_role_num = 5, 157 }, 158 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), 159 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 160 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 161 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 162 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, 163 .info_buf = 1800, .max_role_num = 6, 164 }, 165 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), 166 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, 167 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 168 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 169 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, 170 .info_buf = 1800, .max_role_num = 6, 171 }, 172 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), 173 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 174 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 175 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 176 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, 177 .info_buf = 1280, .max_role_num = 5, 178 }, 179 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), 180 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 181 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 182 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 183 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, 184 .info_buf = 1280, .max_role_num = 5, 185 }, 186 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), 187 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 188 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 189 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 190 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, 191 .info_buf = 1024, .max_role_num = 5, 192 }, 193 194 /* keep it to be the last as default entry */ 195 {0, RTW89_FW_VER_CODE(0, 0, 0, 0), 196 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 197 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 198 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 199 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, 200 .info_buf = 1024, .max_role_num = 5, 201 }, 202 }; 203 204 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1) 205 206 struct rtw89_btc_btf_tlv { 207 u8 type; 208 u8 len; 209 u8 val[]; 210 } __packed; 211 212 enum btc_btf_set_report_en { 213 RPT_EN_TDMA, 214 RPT_EN_CYCLE, 215 RPT_EN_MREG, 216 RPT_EN_BT_VER_INFO, 217 RPT_EN_BT_SCAN_INFO, 218 RPT_EN_BT_DEVICE_INFO, 219 RPT_EN_BT_AFH_MAP, 220 RPT_EN_BT_AFH_MAP_LE, 221 RPT_EN_FW_STEP_INFO, 222 RPT_EN_TEST, 223 RPT_EN_WL_ALL, 224 RPT_EN_BT_ALL, 225 RPT_EN_ALL, 226 RPT_EN_MONITER, 227 }; 228 229 #define BTF_SET_REPORT_VER 1 230 struct rtw89_btc_btf_set_report { 231 u8 fver; 232 __le32 enable; 233 __le32 para; 234 } __packed; 235 236 #define BTF_SET_SLOT_TABLE_VER 1 237 struct rtw89_btc_btf_set_slot_table { 238 u8 fver; 239 u8 tbl_num; 240 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num); 241 } __packed; 242 243 struct rtw89_btc_btf_set_mon_reg { 244 u8 fver; 245 u8 reg_num; 246 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num); 247 } __packed; 248 249 enum btc_btf_set_cx_policy { 250 CXPOLICY_TDMA = 0x0, 251 CXPOLICY_SLOT = 0x1, 252 CXPOLICY_TYPE = 0x2, 253 CXPOLICY_MAX, 254 }; 255 256 enum btc_b2w_scoreboard { 257 BTC_BSCB_ACT = BIT(0), 258 BTC_BSCB_ON = BIT(1), 259 BTC_BSCB_WHQL = BIT(2), 260 BTC_BSCB_BT_S1 = BIT(3), 261 BTC_BSCB_A2DP_ACT = BIT(4), 262 BTC_BSCB_RFK_RUN = BIT(5), 263 BTC_BSCB_RFK_REQ = BIT(6), 264 BTC_BSCB_LPS = BIT(7), 265 BTC_BSCB_WLRFK = BIT(11), 266 BTC_BSCB_BT_HILNA = BIT(13), 267 BTC_BSCB_BT_CONNECT = BIT(16), 268 BTC_BSCB_PATCH_CODE = BIT(30), 269 BTC_BSCB_ALL = GENMASK(30, 0), 270 }; 271 272 enum btc_phymap { 273 BTC_PHY_0 = BIT(0), 274 BTC_PHY_1 = BIT(1), 275 BTC_PHY_ALL = BIT(0) | BIT(1), 276 }; 277 278 enum btc_cx_state_map { 279 BTC_WIDLE = 0, 280 BTC_WBUSY_BNOSCAN, 281 BTC_WBUSY_BSCAN, 282 BTC_WSCAN_BNOSCAN, 283 BTC_WSCAN_BSCAN, 284 BTC_WLINKING 285 }; 286 287 enum btc_ant_phase { 288 BTC_ANT_WPOWERON = 0, 289 BTC_ANT_WINIT, 290 BTC_ANT_WONLY, 291 BTC_ANT_WOFF, 292 BTC_ANT_W2G, 293 BTC_ANT_W5G, 294 BTC_ANT_W25G, 295 BTC_ANT_FREERUN, 296 BTC_ANT_WRFK, 297 BTC_ANT_BRFK, 298 BTC_ANT_MAX 299 }; 300 301 enum btc_plt { 302 BTC_PLT_NONE = 0, 303 BTC_PLT_LTE_RX = BIT(0), 304 BTC_PLT_GNT_BT_TX = BIT(1), 305 BTC_PLT_GNT_BT_RX = BIT(2), 306 BTC_PLT_GNT_WL = BIT(3), 307 BTC_PLT_BT = BIT(1) | BIT(2), 308 BTC_PLT_ALL = 0xf 309 }; 310 311 enum btc_cx_poicy_main_type { 312 BTC_CXP_OFF = 0, 313 BTC_CXP_OFFB, 314 BTC_CXP_OFFE, 315 BTC_CXP_FIX, 316 BTC_CXP_PFIX, 317 BTC_CXP_AUTO, 318 BTC_CXP_PAUTO, 319 BTC_CXP_AUTO2, 320 BTC_CXP_PAUTO2, 321 BTC_CXP_MANUAL, 322 BTC_CXP_USERDEF0, 323 BTC_CXP_MAIN_MAX 324 }; 325 326 enum btc_cx_poicy_type { 327 /* TDMA off + pri: BT > WL */ 328 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0, 329 330 /* TDMA off + pri: WL > BT */ 331 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1, 332 333 /* TDMA off + pri: BT = WL */ 334 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2, 335 336 /* TDMA off + pri: BT = WL > BT_Lo */ 337 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3, 338 339 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */ 340 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4, 341 342 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 343 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5, 344 345 /* TDMA off + pri: BT_Hi > WL > BT_Lo */ 346 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 6, 347 348 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 349 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 7, 350 351 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 352 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 8, 353 354 /* TDMA off + pri: WL_Hi-Tx = BT */ 355 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 9, 356 357 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/ 358 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0, 359 360 /* TDMA off + Ext-Ctrl + pri: default */ 361 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0, 362 363 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 364 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1, 365 366 /* TDMA off + Ext-Ctrl + pri: default */ 367 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2, 368 369 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 370 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3, 371 372 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */ 373 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4, 374 375 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */ 376 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5, 377 378 /* TDMA off + Ext-Ctrl + pri: default */ 379 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6, 380 381 /* TDMA Fix slot-0: W1:B1 = 30:30 */ 382 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0, 383 384 /* TDMA Fix slot-1: W1:B1 = 50:50 */ 385 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1, 386 387 /* TDMA Fix slot-2: W1:B1 = 20:30 */ 388 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2, 389 390 /* TDMA Fix slot-3: W1:B1 = 40:10 */ 391 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3, 392 393 /* TDMA Fix slot-4: W1:B1 = 70:10 */ 394 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4, 395 396 /* TDMA Fix slot-5: W1:B1 = 20:60 */ 397 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5, 398 399 /* TDMA Fix slot-6: W1:B1 = 30:60 */ 400 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6, 401 402 /* TDMA Fix slot-7: W1:B1 = 20:80 */ 403 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7, 404 405 /* TDMA Fix slot-8: W1:B1 = user-define */ 406 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8, 407 408 /* TDMA Fix slot-9: W1:B1 = 40:20 */ 409 BTC_CXP_FIX_TD4020 = (BTC_CXP_FIX << 8) | 9, 410 411 /* TDMA Fix slot-9: W1:B1 = 40:10 */ 412 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 10, 413 414 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */ 415 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0, 416 417 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */ 418 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1, 419 420 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */ 421 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2, 422 423 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */ 424 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3, 425 426 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */ 427 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4, 428 429 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */ 430 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5, 431 432 /* PS-TDMA Fix slot-6: W1:B1 = user-define */ 433 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6, 434 435 /* TDMA Auto slot-0: W1:B1 = 50:200 */ 436 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0, 437 438 /* TDMA Auto slot-1: W1:B1 = 60:200 */ 439 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1, 440 441 /* TDMA Auto slot-2: W1:B1 = 20:200 */ 442 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2, 443 444 /* TDMA Auto slot-3: W1:B1 = user-define */ 445 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3, 446 447 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */ 448 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0, 449 450 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */ 451 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1, 452 453 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */ 454 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2, 455 456 /* PS-TDMA Auto slot-3: W1:B1 = user-define */ 457 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3, 458 459 /* TDMA Auto slot2-0: W1:B4 = 30:50 */ 460 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0, 461 462 /* TDMA Auto slot2-1: W1:B4 = 30:70 */ 463 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1, 464 465 /* TDMA Auto slot2-2: W1:B4 = 50:50 */ 466 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2, 467 468 /* TDMA Auto slot2-3: W1:B4 = 60:60 */ 469 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3, 470 471 /* TDMA Auto slot2-4: W1:B4 = 20:80 */ 472 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4, 473 474 /* TDMA Auto slot2-5: W1:B4 = user-define */ 475 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5, 476 477 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */ 478 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0, 479 480 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */ 481 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1, 482 483 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */ 484 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2, 485 486 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */ 487 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3, 488 489 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */ 490 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4, 491 492 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */ 493 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5, 494 495 BTC_CXP_MAX = 0xffff 496 }; 497 498 enum btc_wl_rfk_result { 499 BTC_WRFK_REJECT = 0, 500 BTC_WRFK_ALLOW = 1, 501 }; 502 503 enum btc_coex_info_map_en { 504 BTC_COEX_INFO_CX = BIT(0), 505 BTC_COEX_INFO_WL = BIT(1), 506 BTC_COEX_INFO_BT = BIT(2), 507 BTC_COEX_INFO_DM = BIT(3), 508 BTC_COEX_INFO_MREG = BIT(4), 509 BTC_COEX_INFO_SUMMARY = BIT(5), 510 BTC_COEX_INFO_ALL = GENMASK(7, 0), 511 }; 512 513 #define BTC_CXP_MASK GENMASK(15, 8) 514 515 enum btc_w2b_scoreboard { 516 BTC_WSCB_ACTIVE = BIT(0), 517 BTC_WSCB_ON = BIT(1), 518 BTC_WSCB_SCAN = BIT(2), 519 BTC_WSCB_UNDERTEST = BIT(3), 520 BTC_WSCB_RXGAIN = BIT(4), 521 BTC_WSCB_WLBUSY = BIT(7), 522 BTC_WSCB_EXTFEM = BIT(8), 523 BTC_WSCB_TDMA = BIT(9), 524 BTC_WSCB_FIX2M = BIT(10), 525 BTC_WSCB_WLRFK = BIT(11), 526 BTC_WSCB_RXSCAN_PRI = BIT(12), 527 BTC_WSCB_BT_HILNA = BIT(13), 528 BTC_WSCB_BTLOG = BIT(14), 529 BTC_WSCB_ALL = GENMASK(23, 0), 530 }; 531 532 enum btc_wl_link_mode { 533 BTC_WLINK_NOLINK = 0x0, 534 BTC_WLINK_2G_STA, 535 BTC_WLINK_2G_AP, 536 BTC_WLINK_2G_GO, 537 BTC_WLINK_2G_GC, 538 BTC_WLINK_2G_SCC, 539 BTC_WLINK_2G_MCC, 540 BTC_WLINK_25G_MCC, 541 BTC_WLINK_25G_DBCC, 542 BTC_WLINK_5G, 543 BTC_WLINK_2G_NAN, 544 BTC_WLINK_OTHER, 545 BTC_WLINK_MAX 546 }; 547 548 enum btc_wl_mrole_type { 549 BTC_WLMROLE_NONE = 0x0, 550 BTC_WLMROLE_STA_GC, 551 BTC_WLMROLE_STA_GC_NOA, 552 BTC_WLMROLE_STA_GO, 553 BTC_WLMROLE_STA_GO_NOA, 554 BTC_WLMROLE_STA_STA, 555 BTC_WLMROLE_MAX 556 }; 557 558 enum btc_bt_hid_type { 559 BTC_HID_218 = BIT(0), 560 BTC_HID_418 = BIT(1), 561 BTC_HID_BLE = BIT(2), 562 BTC_HID_RCU = BIT(3), 563 BTC_HID_RCU_VOICE = BIT(4), 564 BTC_HID_OTHER_LEGACY = BIT(5) 565 }; 566 567 enum btc_reset_module { 568 BTC_RESET_CX = BIT(0), 569 BTC_RESET_DM = BIT(1), 570 BTC_RESET_CTRL = BIT(2), 571 BTC_RESET_CXDM = BIT(0) | BIT(1), 572 BTC_RESET_BTINFO = BIT(3), 573 BTC_RESET_MDINFO = BIT(4), 574 BTC_RESET_ALL = GENMASK(7, 0), 575 }; 576 577 enum btc_gnt_state { 578 BTC_GNT_HW = 0, 579 BTC_GNT_SW_LO, 580 BTC_GNT_SW_HI, 581 BTC_GNT_MAX 582 }; 583 584 enum btc_ctr_path { 585 BTC_CTRL_BY_BT = 0, 586 BTC_CTRL_BY_WL 587 }; 588 589 enum btc_wl_max_tx_time { 590 BTC_MAX_TX_TIME_L1 = 500, 591 BTC_MAX_TX_TIME_L2 = 1000, 592 BTC_MAX_TX_TIME_L3 = 2000, 593 BTC_MAX_TX_TIME_DEF = 5280 594 }; 595 596 enum btc_wl_max_tx_retry { 597 BTC_MAX_TX_RETRY_L1 = 7, 598 BTC_MAX_TX_RETRY_L2 = 15, 599 BTC_MAX_TX_RETRY_DEF = 31, 600 }; 601 602 enum btc_reason_and_action { 603 BTC_RSN_NONE, 604 BTC_RSN_NTFY_INIT, 605 BTC_RSN_NTFY_SWBAND, 606 BTC_RSN_NTFY_WL_STA, 607 BTC_RSN_NTFY_RADIO_STATE, 608 BTC_RSN_UPDATE_BT_SCBD, 609 BTC_RSN_NTFY_WL_RFK, 610 BTC_RSN_UPDATE_BT_INFO, 611 BTC_RSN_NTFY_SCAN_START, 612 BTC_RSN_NTFY_SCAN_FINISH, 613 BTC_RSN_NTFY_SPECIFIC_PACKET, 614 BTC_RSN_NTFY_POWEROFF, 615 BTC_RSN_NTFY_ROLE_INFO, 616 BTC_RSN_CMD_SET_COEX, 617 BTC_RSN_ACT1_WORK, 618 BTC_RSN_BT_DEVINFO_WORK, 619 BTC_RSN_RFK_CHK_WORK, 620 BTC_RSN_NUM, 621 BTC_ACT_NONE = 100, 622 BTC_ACT_WL_ONLY, 623 BTC_ACT_WL_5G, 624 BTC_ACT_WL_OTHER, 625 BTC_ACT_WL_IDLE, 626 BTC_ACT_WL_NC, 627 BTC_ACT_WL_RFK, 628 BTC_ACT_WL_INIT, 629 BTC_ACT_WL_OFF, 630 BTC_ACT_FREERUN, 631 BTC_ACT_BT_WHQL, 632 BTC_ACT_BT_RFK, 633 BTC_ACT_BT_OFF, 634 BTC_ACT_BT_IDLE, 635 BTC_ACT_BT_HFP, 636 BTC_ACT_BT_HID, 637 BTC_ACT_BT_A2DP, 638 BTC_ACT_BT_A2DPSINK, 639 BTC_ACT_BT_PAN, 640 BTC_ACT_BT_A2DP_HID, 641 BTC_ACT_BT_A2DP_PAN, 642 BTC_ACT_BT_PAN_HID, 643 BTC_ACT_BT_A2DP_PAN_HID, 644 BTC_ACT_WL_25G_MCC, 645 BTC_ACT_WL_2G_MCC, 646 BTC_ACT_WL_2G_SCC, 647 BTC_ACT_WL_2G_AP, 648 BTC_ACT_WL_2G_GO, 649 BTC_ACT_WL_2G_GC, 650 BTC_ACT_WL_2G_NAN, 651 BTC_ACT_LAST, 652 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE, 653 BTC_ACT_EXT_BIT = BIT(14), 654 BTC_POLICY_EXT_BIT = BIT(15), 655 }; 656 657 #define BTC_FREERUN_ANTISO_MIN 30 658 #define BTC_TDMA_BTHID_MAX 2 659 #define BTC_BLINK_NOCONNECT 0 660 #define BTC_B1_MAX 250 /* unit ms */ 661 662 static void _run_coex(struct rtw89_dev *rtwdev, 663 enum btc_reason_and_action reason); 664 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state); 665 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update); 666 667 static void _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, 668 void *param, u16 len) 669 { 670 struct rtw89_btc *btc = &rtwdev->btc; 671 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 672 struct rtw89_btc_cx *cx = &btc->cx; 673 struct rtw89_btc_wl_info *wl = &cx->wl; 674 int ret; 675 676 if (!wl->status.map.init_ok) { 677 rtw89_debug(rtwdev, RTW89_DBG_BTC, 678 "[BTC], %s(): return by btc not init!!\n", __func__); 679 pfwinfo->cnt_h2c_fail++; 680 return; 681 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF && 682 wl->status.map.rf_off == BTC_LPS_RF_OFF) || 683 (wl->status.map.lps_pre == BTC_LPS_RF_OFF && 684 wl->status.map.lps == BTC_LPS_RF_OFF)) { 685 rtw89_debug(rtwdev, RTW89_DBG_BTC, 686 "[BTC], %s(): return by wl off!!\n", __func__); 687 pfwinfo->cnt_h2c_fail++; 688 return; 689 } 690 691 pfwinfo->cnt_h2c++; 692 693 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len, 694 false, true); 695 if (ret != 0) 696 pfwinfo->cnt_h2c_fail++; 697 } 698 699 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) 700 { 701 struct rtw89_btc *btc = &rtwdev->btc; 702 struct rtw89_btc_cx *cx = &btc->cx; 703 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 704 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 705 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 706 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 707 u8 i; 708 709 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 710 711 if (type & BTC_RESET_CX) 712 memset(cx, 0, sizeof(*cx)); 713 else if (type & BTC_RESET_BTINFO) /* only for BT enable */ 714 memset(bt, 0, sizeof(*bt)); 715 716 if (type & BTC_RESET_CTRL) { 717 memset(&btc->ctrl, 0, sizeof(btc->ctrl)); 718 btc->ctrl.trace_step = FCXDEF_STEP; 719 } 720 721 /* Init Coex variables that are not zero */ 722 if (type & BTC_RESET_DM) { 723 memset(&btc->dm, 0, sizeof(btc->dm)); 724 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state)); 725 726 for (i = 0; i < RTW89_PORT_NUM; i++) 727 memset(wl_linfo[i].rssi_state, 0, 728 sizeof(wl_linfo[i].rssi_state)); 729 730 /* set the slot_now table to original */ 731 btc->dm.tdma_now = t_def[CXTD_OFF]; 732 btc->dm.tdma = t_def[CXTD_OFF]; 733 memcpy(&btc->dm.slot_now, s_def, sizeof(btc->dm.slot_now)); 734 memcpy(&btc->dm.slot, s_def, sizeof(btc->dm.slot)); 735 736 btc->policy_len = 0; 737 btc->bt_req_len = 0; 738 739 btc->dm.coex_info_map = BTC_COEX_INFO_ALL; 740 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF; 741 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF; 742 } 743 744 if (type & BTC_RESET_MDINFO) 745 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo)); 746 } 747 748 #define BTC_RPT_HDR_SIZE 3 749 #define BTC_CHK_WLSLOT_DRIFT_MAX 15 750 #define BTC_CHK_BTSLOT_DRIFT_MAX 15 751 #define BTC_CHK_HANG_MAX 3 752 753 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt) 754 { 755 struct rtw89_btc *btc = &rtwdev->btc; 756 struct rtw89_btc_cx *cx = &btc->cx; 757 struct rtw89_btc_dm *dm = &btc->dm; 758 struct rtw89_btc_bt_info *bt = &cx->bt; 759 760 rtw89_debug(rtwdev, RTW89_DBG_BTC, 761 "[BTC], %s(): type:%d cnt:%d\n", 762 __func__, type, cnt); 763 764 switch (type) { 765 case BTC_DCNT_RPT_HANG: 766 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map) 767 dm->cnt_dm[BTC_DCNT_RPT_HANG]++; 768 else 769 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0; 770 771 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX) 772 dm->error.map.wl_fw_hang = true; 773 else 774 dm->error.map.wl_fw_hang = false; 775 776 dm->cnt_dm[BTC_DCNT_RPT] = cnt; 777 break; 778 case BTC_DCNT_CYCLE_HANG: 779 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt && 780 (dm->tdma_now.type != CXTDMA_OFF || 781 dm->tdma_now.ext_ctrl == CXECTL_EXT)) 782 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++; 783 else 784 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0; 785 786 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX) 787 dm->error.map.cycle_hang = true; 788 else 789 dm->error.map.cycle_hang = false; 790 791 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt; 792 break; 793 case BTC_DCNT_W1_HANG: 794 if (dm->cnt_dm[BTC_DCNT_W1] == cnt && 795 dm->tdma_now.type != CXTDMA_OFF) 796 dm->cnt_dm[BTC_DCNT_W1_HANG]++; 797 else 798 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0; 799 800 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX) 801 dm->error.map.w1_hang = true; 802 else 803 dm->error.map.w1_hang = false; 804 805 dm->cnt_dm[BTC_DCNT_W1] = cnt; 806 break; 807 case BTC_DCNT_B1_HANG: 808 if (dm->cnt_dm[BTC_DCNT_B1] == cnt && 809 dm->tdma_now.type != CXTDMA_OFF) 810 dm->cnt_dm[BTC_DCNT_B1_HANG]++; 811 else 812 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0; 813 814 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX) 815 dm->error.map.b1_hang = true; 816 else 817 dm->error.map.b1_hang = false; 818 819 dm->cnt_dm[BTC_DCNT_B1] = cnt; 820 break; 821 case BTC_DCNT_E2G_HANG: 822 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt && 823 dm->tdma_now.ext_ctrl == CXECTL_EXT) 824 dm->cnt_dm[BTC_DCNT_E2G_HANG]++; 825 else 826 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0; 827 828 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX) 829 dm->error.map.wl_e2g_hang = true; 830 else 831 dm->error.map.wl_e2g_hang = false; 832 833 dm->cnt_dm[BTC_DCNT_E2G] = cnt; 834 break; 835 case BTC_DCNT_TDMA_NONSYNC: 836 if (cnt != 0) /* if tdma not sync between drv/fw */ 837 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++; 838 else 839 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0; 840 841 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX) 842 dm->error.map.tdma_no_sync = true; 843 else 844 dm->error.map.tdma_no_sync = false; 845 break; 846 case BTC_DCNT_SLOT_NONSYNC: 847 if (cnt != 0) /* if slot not sync between drv/fw */ 848 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++; 849 else 850 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0; 851 852 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX) 853 dm->error.map.slot_no_sync = true; 854 else 855 dm->error.map.slot_no_sync = false; 856 break; 857 case BTC_DCNT_BTCNT_HANG: 858 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] + 859 cx->cnt_bt[BTC_BCNT_HIPRI_TX] + 860 cx->cnt_bt[BTC_BCNT_LOPRI_RX] + 861 cx->cnt_bt[BTC_BCNT_LOPRI_TX]; 862 863 if (cnt == 0) 864 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++; 865 else 866 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 867 868 if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX && 869 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] && 870 !bt->enable.now)) 871 _update_bt_scbd(rtwdev, false); 872 break; 873 case BTC_DCNT_WL_SLOT_DRIFT: 874 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX) 875 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++; 876 else 877 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0; 878 879 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 880 dm->error.map.wl_slot_drift = true; 881 else 882 dm->error.map.wl_slot_drift = false; 883 break; 884 case BTC_DCNT_BT_SLOT_DRIFT: 885 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX) 886 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++; 887 else 888 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0; 889 890 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 891 dm->error.map.bt_slot_drift = true; 892 else 893 dm->error.map.bt_slot_drift = false; 894 895 break; 896 } 897 } 898 899 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) 900 { 901 struct rtw89_btc *btc = &rtwdev->btc; 902 const struct rtw89_btc_ver *ver = btc->ver; 903 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 904 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 905 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc; 906 struct rtw89_btc_fbtc_btver *pver = NULL; 907 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1; 908 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2; 909 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL; 910 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL; 911 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL; 912 bool scan_update = true; 913 int i; 914 915 pver = (struct rtw89_btc_fbtc_btver *)pfinfo; 916 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo; 917 918 rtw89_debug(rtwdev, RTW89_DBG_BTC, 919 "[BTC], %s(): rpt_type:%d\n", 920 __func__, rpt_type); 921 922 switch (rpt_type) { 923 case BTC_RPT_TYPE_BT_VER: 924 bt->ver_info.fw = le32_to_cpu(pver->fw_ver); 925 bt->ver_info.fw_coex = le32_get_bits(pver->coex_ver, GENMASK(7, 0)); 926 bt->feature = le32_to_cpu(pver->feature); 927 break; 928 case BTC_RPT_TYPE_BT_SCAN: 929 if (ver->fcxbtscan == 1) { 930 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo; 931 for (i = 0; i < BTC_SCAN_MAX1; i++) { 932 bt->scan_info_v1[i] = pscan_v1->scan[i]; 933 if (bt->scan_info_v1[i].win == 0 && 934 bt->scan_info_v1[i].intvl == 0) 935 scan_update = false; 936 } 937 } else if (ver->fcxbtscan == 2) { 938 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo; 939 for (i = 0; i < CXSCAN_MAX; i++) { 940 bt->scan_info_v2[i] = pscan_v2->para[i]; 941 if ((pscan_v2->type & BIT(i)) && 942 pscan_v2->para[i].win == 0 && 943 pscan_v2->para[i].intvl == 0) 944 scan_update = false; 945 } 946 } 947 if (scan_update) 948 bt->scan_info_update = 1; 949 break; 950 case BTC_RPT_TYPE_BT_AFH: 951 if (ver->fcxbtafh == 2) { 952 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo; 953 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) { 954 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4); 955 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4); 956 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2); 957 } 958 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) { 959 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4); 960 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1); 961 } 962 } else if (ver->fcxbtafh == 1) { 963 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo; 964 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4); 965 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4); 966 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2); 967 } 968 break; 969 case BTC_RPT_TYPE_BT_DEVICE: 970 a2dp->device_name = le32_to_cpu(pdev->dev_name); 971 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id); 972 a2dp->flush_time = le32_to_cpu(pdev->flush_time); 973 break; 974 default: 975 break; 976 } 977 } 978 979 #define BTC_LEAK_AP_TH 10 980 #define BTC_CYSTA_CHK_PERIOD 100 981 982 struct rtw89_btc_prpt { 983 u8 type; 984 __le16 len; 985 u8 content[]; 986 } __packed; 987 988 static u32 _chk_btc_report(struct rtw89_dev *rtwdev, 989 struct rtw89_btc_btf_fwinfo *pfwinfo, 990 u8 *prptbuf, u32 index) 991 { 992 struct rtw89_btc *btc = &rtwdev->btc; 993 const struct rtw89_btc_ver *ver = btc->ver; 994 struct rtw89_btc_dm *dm = &btc->dm; 995 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 996 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 997 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 998 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL; 999 union rtw89_btc_fbtc_cysta_info *pcysta = NULL; 1000 struct rtw89_btc_prpt *btc_prpt = NULL; 1001 void *rpt_content = NULL, *pfinfo = NULL; 1002 u8 rpt_type = 0; 1003 u16 wl_slot_set = 0, wl_slot_real = 0; 1004 u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t = 0; 1005 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr; 1006 u8 i; 1007 1008 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1009 "[BTC], %s(): index:%d\n", 1010 __func__, index); 1011 1012 if (!prptbuf) { 1013 pfwinfo->err[BTFRE_INVALID_INPUT]++; 1014 return 0; 1015 } 1016 1017 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index]; 1018 rpt_type = btc_prpt->type; 1019 rpt_len = le16_to_cpu(btc_prpt->len); 1020 rpt_content = btc_prpt->content; 1021 1022 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1023 "[BTC], %s(): rpt_type:%d\n", 1024 __func__, rpt_type); 1025 1026 switch (rpt_type) { 1027 case BTC_RPT_TYPE_CTRL: 1028 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 1029 prpt = &pfwinfo->rpt_ctrl.finfo; 1030 if (ver->fcxbtcrpt == 1) { 1031 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1; 1032 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1); 1033 } else if (ver->fcxbtcrpt == 4) { 1034 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4; 1035 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4); 1036 } else if (ver->fcxbtcrpt == 5) { 1037 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5; 1038 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5); 1039 } else if (ver->fcxbtcrpt == 105) { 1040 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105; 1041 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105); 1042 pcinfo->req_fver = 5; 1043 break; 1044 } else { 1045 goto err; 1046 } 1047 pcinfo->req_fver = ver->fcxbtcrpt; 1048 break; 1049 case BTC_RPT_TYPE_TDMA: 1050 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 1051 if (ver->fcxtdma == 1) { 1052 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 1053 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); 1054 } else if (ver->fcxtdma == 3) { 1055 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; 1056 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); 1057 } else { 1058 goto err; 1059 } 1060 pcinfo->req_fver = ver->fcxtdma; 1061 break; 1062 case BTC_RPT_TYPE_SLOT: 1063 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 1064 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo; 1065 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo); 1066 pcinfo->req_fver = ver->fcxslots; 1067 break; 1068 case BTC_RPT_TYPE_CYSTA: 1069 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 1070 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 1071 if (ver->fcxcysta == 2) { 1072 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 1073 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 1074 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2); 1075 } else if (ver->fcxcysta == 3) { 1076 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 1077 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 1078 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3); 1079 } else if (ver->fcxcysta == 4) { 1080 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 1081 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 1082 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4); 1083 } else if (ver->fcxcysta == 5) { 1084 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 1085 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 1086 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5); 1087 } else { 1088 goto err; 1089 } 1090 pcinfo->req_fver = ver->fcxcysta; 1091 break; 1092 case BTC_RPT_TYPE_STEP: 1093 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 1094 if (ver->fcxstep == 2) { 1095 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2; 1096 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) * 1097 trace_step + 1098 offsetof(struct rtw89_btc_fbtc_steps_v2, step); 1099 } else if (ver->fcxstep == 3) { 1100 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3; 1101 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) * 1102 trace_step + 1103 offsetof(struct rtw89_btc_fbtc_steps_v3, step); 1104 } else { 1105 goto err; 1106 } 1107 pcinfo->req_fver = ver->fcxstep; 1108 break; 1109 case BTC_RPT_TYPE_NULLSTA: 1110 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 1111 if (ver->fcxnullsta == 1) { 1112 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1; 1113 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1); 1114 } else if (ver->fcxnullsta == 2) { 1115 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2; 1116 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2); 1117 } else { 1118 goto err; 1119 } 1120 pcinfo->req_fver = ver->fcxnullsta; 1121 break; 1122 case BTC_RPT_TYPE_MREG: 1123 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 1124 if (ver->fcxmreg == 1) { 1125 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 1126 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1); 1127 } else if (ver->fcxmreg == 2) { 1128 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 1129 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2); 1130 } else { 1131 goto err; 1132 } 1133 pcinfo->req_fver = ver->fcxmreg; 1134 break; 1135 case BTC_RPT_TYPE_GPIO_DBG: 1136 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 1137 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 1138 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo); 1139 pcinfo->req_fver = ver->fcxgpiodbg; 1140 break; 1141 case BTC_RPT_TYPE_BT_VER: 1142 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo; 1143 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo; 1144 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo); 1145 pcinfo->req_fver = ver->fcxbtver; 1146 break; 1147 case BTC_RPT_TYPE_BT_SCAN: 1148 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo; 1149 if (ver->fcxbtscan == 1) { 1150 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1; 1151 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1); 1152 } else if (ver->fcxbtscan == 2) { 1153 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2; 1154 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2); 1155 } 1156 pcinfo->req_fver = ver->fcxbtscan; 1157 break; 1158 case BTC_RPT_TYPE_BT_AFH: 1159 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo; 1160 if (ver->fcxbtafh == 1) { 1161 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1; 1162 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1); 1163 } else if (ver->fcxbtafh == 2) { 1164 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2; 1165 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2); 1166 } else { 1167 goto err; 1168 } 1169 pcinfo->req_fver = ver->fcxbtafh; 1170 break; 1171 case BTC_RPT_TYPE_BT_DEVICE: 1172 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo; 1173 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo; 1174 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo); 1175 pcinfo->req_fver = ver->fcxbtdevinfo; 1176 break; 1177 default: 1178 pfwinfo->err[BTFRE_UNDEF_TYPE]++; 1179 return 0; 1180 } 1181 1182 pcinfo->rx_len = rpt_len; 1183 pcinfo->rx_cnt++; 1184 1185 if (rpt_len != pcinfo->req_len) { 1186 if (rpt_type < BTC_RPT_TYPE_MAX) 1187 pfwinfo->len_mismch |= (0x1 << rpt_type); 1188 else 1189 pfwinfo->len_mismch |= BIT(31); 1190 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1191 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n", 1192 __func__, rpt_type, rpt_len, pcinfo->req_len); 1193 1194 pcinfo->valid = 0; 1195 return 0; 1196 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) { 1197 pfwinfo->err[BTFRE_EXCEPTION]++; 1198 pcinfo->valid = 0; 1199 return 0; 1200 } 1201 1202 memcpy(pfinfo, rpt_content, pcinfo->req_len); 1203 pcinfo->valid = 1; 1204 1205 switch (rpt_type) { 1206 case BTC_RPT_TYPE_CTRL: 1207 if (ver->fcxbtcrpt == 1) { 1208 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1; 1209 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable; 1210 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver; 1211 wl->ver_info.fw = prpt->v1.wl_fw_ver; 1212 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload; 1213 1214 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1215 pfwinfo->event[BTF_EVNT_RPT]); 1216 1217 /* To avoid I/O if WL LPS or power-off */ 1218 if (wl->status.map.lps != BTC_LPS_RF_OFF && 1219 !wl->status.map.rf_off) { 1220 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev); 1221 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1222 1223 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1224 rtw89_mac_get_plt_cnt(rtwdev, 1225 RTW89_MAC_0); 1226 } 1227 } else if (ver->fcxbtcrpt == 4) { 1228 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4; 1229 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en); 1230 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver); 1231 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver); 1232 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload); 1233 1234 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++) 1235 memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i], 1236 sizeof(dm->gnt.band[i])); 1237 1238 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1239 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]); 1240 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1241 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]); 1242 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1243 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]); 1244 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1245 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]); 1246 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1247 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]); 1248 1249 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1250 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1251 pfwinfo->event[BTF_EVNT_RPT]); 1252 1253 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 1254 bt->rfk_info.map.timeout = 1; 1255 else 1256 bt->rfk_info.map.timeout = 0; 1257 1258 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1259 } else if (ver->fcxbtcrpt == 5) { 1260 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5; 1261 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en); 1262 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver); 1263 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver); 1264 dm->wl_fw_cx_offload = 0; 1265 1266 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++) 1267 memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0], 1268 sizeof(dm->gnt.band[i])); 1269 1270 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1271 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]); 1272 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1273 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]); 1274 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1275 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]); 1276 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1277 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]); 1278 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1279 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]); 1280 1281 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1282 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1283 pfwinfo->event[BTF_EVNT_RPT]); 1284 1285 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1286 } else if (ver->fcxbtcrpt == 105) { 1287 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105; 1288 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en); 1289 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver); 1290 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver); 1291 dm->wl_fw_cx_offload = 0; 1292 1293 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++) 1294 memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0], 1295 sizeof(dm->gnt.band[i])); 1296 1297 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1298 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]); 1299 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1300 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]); 1301 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1302 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]); 1303 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1304 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]); 1305 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1306 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1307 1308 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1309 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1310 pfwinfo->event[BTF_EVNT_RPT]); 1311 1312 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1313 } else { 1314 goto err; 1315 } 1316 break; 1317 case BTC_RPT_TYPE_TDMA: 1318 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1319 "[BTC], %s(): check %d %zu\n", __func__, 1320 BTC_DCNT_TDMA_NONSYNC, 1321 sizeof(dm->tdma_now)); 1322 if (ver->fcxtdma == 1) 1323 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 1324 memcmp(&dm->tdma_now, 1325 &pfwinfo->rpt_fbtc_tdma.finfo.v1, 1326 sizeof(dm->tdma_now))); 1327 else if (ver->fcxtdma == 3) 1328 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 1329 memcmp(&dm->tdma_now, 1330 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma, 1331 sizeof(dm->tdma_now))); 1332 else 1333 goto err; 1334 break; 1335 case BTC_RPT_TYPE_SLOT: 1336 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1337 "[BTC], %s(): check %d %zu\n", 1338 __func__, BTC_DCNT_SLOT_NONSYNC, 1339 sizeof(dm->slot_now)); 1340 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 1341 memcmp(dm->slot_now, 1342 pfwinfo->rpt_fbtc_slots.finfo.slot, 1343 sizeof(dm->slot_now))); 1344 break; 1345 case BTC_RPT_TYPE_CYSTA: 1346 if (ver->fcxcysta == 2) { 1347 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD) 1348 break; 1349 /* Check Leak-AP */ 1350 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 && 1351 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) { 1352 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) < 1353 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt)) 1354 dm->leak_ap = 1; 1355 } 1356 1357 /* Check diff time between WL slot and W1/E2G slot */ 1358 if (dm->tdma_now.type == CXTDMA_OFF && 1359 dm->tdma_now.ext_ctrl == CXECTL_EXT) 1360 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur); 1361 else 1362 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1363 1364 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) { 1365 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set; 1366 _chk_btc_err(rtwdev, 1367 BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1368 } 1369 1370 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1371 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1])); 1372 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1373 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1])); 1374 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1375 le16_to_cpu(pcysta->v2.cycles)); 1376 } else if (ver->fcxcysta == 3) { 1377 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD) 1378 break; 1379 1380 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]); 1381 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr); 1382 1383 /* Check Leak-AP */ 1384 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1385 dm->tdma_now.rxflctrl) { 1386 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1387 dm->leak_ap = 1; 1388 } 1389 1390 /* Check diff time between real WL slot and W1 slot */ 1391 if (dm->tdma_now.type == CXTDMA_OFF) { 1392 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1393 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]); 1394 if (wl_slot_real > wl_slot_set) { 1395 diff_t = wl_slot_real - wl_slot_set; 1396 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1397 } 1398 } 1399 1400 /* Check diff time between real BT slot and EBT/E5G slot */ 1401 if (dm->tdma_now.type == CXTDMA_OFF && 1402 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1403 btc->bt_req_len != 0) { 1404 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]); 1405 if (btc->bt_req_len > bt_slot_real) { 1406 diff_t = btc->bt_req_len - bt_slot_real; 1407 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 1408 } 1409 } 1410 1411 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1412 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1])); 1413 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 1414 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1])); 1415 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1416 le16_to_cpu(pcysta->v3.cycles)); 1417 } else if (ver->fcxcysta == 4) { 1418 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD) 1419 break; 1420 1421 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]); 1422 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr); 1423 1424 /* Check Leak-AP */ 1425 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1426 dm->tdma_now.rxflctrl) { 1427 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1428 dm->leak_ap = 1; 1429 } 1430 1431 /* Check diff time between real WL slot and W1 slot */ 1432 if (dm->tdma_now.type == CXTDMA_OFF) { 1433 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1434 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]); 1435 if (wl_slot_real > wl_slot_set) { 1436 diff_t = wl_slot_real - wl_slot_set; 1437 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1438 } 1439 } 1440 1441 /* Check diff time between real BT slot and EBT/E5G slot */ 1442 if (dm->tdma_now.type == CXTDMA_OFF && 1443 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1444 btc->bt_req_len != 0) { 1445 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]); 1446 1447 if (btc->bt_req_len > bt_slot_real) { 1448 diff_t = btc->bt_req_len - bt_slot_real; 1449 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 1450 } 1451 } 1452 1453 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1454 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1])); 1455 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 1456 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1])); 1457 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1458 le16_to_cpu(pcysta->v4.cycles)); 1459 } else if (ver->fcxcysta == 5) { 1460 if (dm->fddt_train == BTC_FDDT_ENABLE) 1461 break; 1462 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]); 1463 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr); 1464 1465 /* Check Leak-AP */ 1466 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1467 dm->tdma_now.rxflctrl) { 1468 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 1469 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1470 dm->leak_ap = 1; 1471 } 1472 1473 /* Check diff time between real WL slot and W1 slot */ 1474 if (dm->tdma_now.type == CXTDMA_OFF) { 1475 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur); 1476 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]); 1477 1478 if (wl_slot_real > wl_slot_set) 1479 diff_t = wl_slot_real - wl_slot_set; 1480 else 1481 diff_t = wl_slot_set - wl_slot_real; 1482 } 1483 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1484 1485 /* Check diff time between real BT slot and EBT/E5G slot */ 1486 bt_slot_set = btc->bt_req_len; 1487 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]); 1488 diff_t = 0; 1489 if (dm->tdma_now.type == CXTDMA_OFF && 1490 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1491 bt_slot_set != 0) { 1492 if (bt_slot_set > bt_slot_real) 1493 diff_t = bt_slot_set - bt_slot_real; 1494 else 1495 diff_t = bt_slot_real - bt_slot_set; 1496 } 1497 1498 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 1499 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 1500 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G])); 1501 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1502 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1])); 1503 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 1504 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1])); 1505 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1506 le16_to_cpu(pcysta->v5.cycles)); 1507 } else { 1508 goto err; 1509 } 1510 break; 1511 case BTC_RPT_TYPE_BT_VER: 1512 case BTC_RPT_TYPE_BT_SCAN: 1513 case BTC_RPT_TYPE_BT_AFH: 1514 case BTC_RPT_TYPE_BT_DEVICE: 1515 _update_bt_report(rtwdev, rpt_type, pfinfo); 1516 break; 1517 } 1518 return (rpt_len + BTC_RPT_HDR_SIZE); 1519 1520 err: 1521 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1522 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type); 1523 return 0; 1524 } 1525 1526 static void _parse_btc_report(struct rtw89_dev *rtwdev, 1527 struct rtw89_btc_btf_fwinfo *pfwinfo, 1528 u8 *pbuf, u32 buf_len) 1529 { 1530 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 1531 struct rtw89_btc_prpt *btc_prpt = NULL; 1532 u32 index = 0, rpt_len = 0; 1533 1534 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1535 "[BTC], %s(): buf_len:%d\n", 1536 __func__, buf_len); 1537 1538 while (pbuf) { 1539 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index]; 1540 if (index + 2 >= ver->info_buf) 1541 break; 1542 /* At least 3 bytes: type(1) & len(2) */ 1543 rpt_len = le16_to_cpu(btc_prpt->len); 1544 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len) 1545 break; 1546 1547 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index); 1548 if (!rpt_len) 1549 break; 1550 index += rpt_len; 1551 } 1552 } 1553 1554 #define BTC_TLV_HDR_LEN 2 1555 1556 static void _append_tdma(struct rtw89_dev *rtwdev) 1557 { 1558 struct rtw89_btc *btc = &rtwdev->btc; 1559 const struct rtw89_btc_ver *ver = btc->ver; 1560 struct rtw89_btc_dm *dm = &btc->dm; 1561 struct rtw89_btc_btf_tlv *tlv; 1562 struct rtw89_btc_fbtc_tdma *v; 1563 struct rtw89_btc_fbtc_tdma_v3 *v3; 1564 u16 len = btc->policy_len; 1565 1566 if (!btc->update_policy_force && 1567 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) { 1568 rtw89_debug(rtwdev, 1569 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n", 1570 __func__); 1571 return; 1572 } 1573 1574 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 1575 tlv->type = CXPOLICY_TDMA; 1576 if (ver->fcxtdma == 1) { 1577 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0]; 1578 tlv->len = sizeof(*v); 1579 *v = dm->tdma; 1580 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 1581 } else { 1582 tlv->len = sizeof(*v3); 1583 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0]; 1584 v3->fver = ver->fcxtdma; 1585 v3->tdma = dm->tdma; 1586 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3); 1587 } 1588 1589 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1590 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n", 1591 __func__, dm->tdma.type, dm->tdma.rxflctrl, 1592 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n, 1593 dm->tdma.ext_ctrl); 1594 } 1595 1596 static void _append_slot(struct rtw89_dev *rtwdev) 1597 { 1598 struct rtw89_btc *btc = &rtwdev->btc; 1599 struct rtw89_btc_dm *dm = &btc->dm; 1600 struct rtw89_btc_btf_tlv *tlv = NULL; 1601 struct btc_fbtc_1slot *v = NULL; 1602 u16 len = 0; 1603 u8 i, cnt = 0; 1604 1605 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1606 "[BTC], %s(): A:btc->policy_len = %d\n", 1607 __func__, btc->policy_len); 1608 1609 for (i = 0; i < CXST_MAX; i++) { 1610 if (!btc->update_policy_force && 1611 !memcmp(&dm->slot[i], &dm->slot_now[i], 1612 sizeof(dm->slot[i]))) 1613 continue; 1614 1615 len = btc->policy_len; 1616 1617 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 1618 v = (struct btc_fbtc_1slot *)&tlv->val[0]; 1619 tlv->type = CXPOLICY_SLOT; 1620 tlv->len = sizeof(*v); 1621 1622 v->fver = FCXONESLOT_VER; 1623 v->sid = i; 1624 v->slot = dm->slot[i]; 1625 1626 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1627 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n", 1628 __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl, 1629 dm->slot[i].cxtype); 1630 cnt++; 1631 1632 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 1633 } 1634 1635 if (cnt > 0) 1636 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1637 "[BTC], %s(): slot update (cnt=%d)!!\n", 1638 __func__, cnt); 1639 } 1640 1641 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) 1642 { 1643 struct rtw89_btc *btc = &rtwdev->btc; 1644 const struct rtw89_btc_ver *ver = btc->ver; 1645 u32 bit_map = 0; 1646 1647 switch (rpt_map) { 1648 case RPT_EN_TDMA: 1649 bit_map = BIT(0); 1650 break; 1651 case RPT_EN_CYCLE: 1652 bit_map = BIT(1); 1653 break; 1654 case RPT_EN_MREG: 1655 bit_map = BIT(2); 1656 break; 1657 case RPT_EN_BT_VER_INFO: 1658 bit_map = BIT(3); 1659 break; 1660 case RPT_EN_BT_SCAN_INFO: 1661 bit_map = BIT(4); 1662 break; 1663 case RPT_EN_BT_DEVICE_INFO: 1664 switch (ver->frptmap) { 1665 case 0: 1666 case 1: 1667 case 2: 1668 bit_map = BIT(6); 1669 break; 1670 case 3: 1671 bit_map = BIT(5); 1672 break; 1673 default: 1674 break; 1675 } 1676 break; 1677 case RPT_EN_BT_AFH_MAP: 1678 switch (ver->frptmap) { 1679 case 0: 1680 case 1: 1681 case 2: 1682 bit_map = BIT(5); 1683 break; 1684 case 3: 1685 bit_map = BIT(6); 1686 break; 1687 default: 1688 break; 1689 } 1690 break; 1691 case RPT_EN_BT_AFH_MAP_LE: 1692 switch (ver->frptmap) { 1693 case 2: 1694 bit_map = BIT(8); 1695 break; 1696 case 3: 1697 bit_map = BIT(7); 1698 break; 1699 default: 1700 break; 1701 } 1702 break; 1703 case RPT_EN_FW_STEP_INFO: 1704 switch (ver->frptmap) { 1705 case 1: 1706 case 2: 1707 bit_map = BIT(7); 1708 break; 1709 case 3: 1710 bit_map = BIT(8); 1711 break; 1712 default: 1713 break; 1714 } 1715 break; 1716 case RPT_EN_TEST: 1717 bit_map = BIT(31); 1718 break; 1719 case RPT_EN_WL_ALL: 1720 switch (ver->frptmap) { 1721 case 0: 1722 case 1: 1723 case 2: 1724 bit_map = GENMASK(2, 0); 1725 break; 1726 case 3: 1727 bit_map = GENMASK(2, 0) | BIT(8); 1728 break; 1729 default: 1730 break; 1731 } 1732 break; 1733 case RPT_EN_BT_ALL: 1734 switch (ver->frptmap) { 1735 case 0: 1736 case 1: 1737 bit_map = GENMASK(6, 3); 1738 break; 1739 case 2: 1740 bit_map = GENMASK(6, 3) | BIT(8); 1741 break; 1742 case 3: 1743 bit_map = GENMASK(7, 3); 1744 break; 1745 default: 1746 break; 1747 } 1748 break; 1749 case RPT_EN_ALL: 1750 switch (ver->frptmap) { 1751 case 0: 1752 bit_map = GENMASK(6, 0); 1753 break; 1754 case 1: 1755 bit_map = GENMASK(7, 0); 1756 break; 1757 case 2: 1758 case 3: 1759 bit_map = GENMASK(8, 0); 1760 break; 1761 default: 1762 break; 1763 } 1764 break; 1765 case RPT_EN_MONITER: 1766 switch (ver->frptmap) { 1767 case 0: 1768 case 1: 1769 bit_map = GENMASK(6, 2); 1770 break; 1771 case 2: 1772 bit_map = GENMASK(6, 2) | BIT(8); 1773 break; 1774 case 3: 1775 bit_map = GENMASK(8, 2); 1776 break; 1777 default: 1778 break; 1779 } 1780 break; 1781 } 1782 1783 return bit_map; 1784 } 1785 1786 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev, 1787 u32 rpt_map, bool rpt_state) 1788 { 1789 struct rtw89_btc *btc = &rtwdev->btc; 1790 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map; 1791 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo; 1792 struct rtw89_btc_btf_set_report r = {0}; 1793 u32 val, bit_map; 1794 1795 if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0) 1796 return; 1797 1798 bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map); 1799 1800 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1801 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n", 1802 __func__, rpt_map, rpt_state); 1803 1804 if (rpt_state) 1805 val = fwinfo->rpt_en_map | bit_map; 1806 else 1807 val = fwinfo->rpt_en_map & ~bit_map; 1808 1809 if (val == fwinfo->rpt_en_map) 1810 return; 1811 1812 fwinfo->rpt_en_map = val; 1813 1814 r.fver = BTF_SET_REPORT_VER; 1815 r.enable = cpu_to_le32(val); 1816 r.para = cpu_to_le32(rpt_state); 1817 1818 _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r, sizeof(r)); 1819 } 1820 1821 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num, 1822 struct rtw89_btc_fbtc_slot *s) 1823 { 1824 struct rtw89_btc_btf_set_slot_table *tbl; 1825 u16 n; 1826 1827 n = struct_size(tbl, tbls, num); 1828 tbl = kmalloc(n, GFP_KERNEL); 1829 if (!tbl) 1830 return; 1831 1832 tbl->fver = BTF_SET_SLOT_TABLE_VER; 1833 tbl->tbl_num = num; 1834 memcpy(tbl->tbls, s, flex_array_size(tbl, tbls, num)); 1835 1836 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n); 1837 1838 kfree(tbl); 1839 } 1840 1841 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) 1842 { 1843 const struct rtw89_chip_info *chip = rtwdev->chip; 1844 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 1845 struct rtw89_btc_btf_set_mon_reg *monreg = NULL; 1846 u8 n, ulen, cxmreg_max; 1847 u16 sz = 0; 1848 1849 n = chip->mon_reg_num; 1850 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1851 "[BTC], %s(): mon_reg_num=%d\n", __func__, n); 1852 1853 if (ver->fcxmreg == 1) 1854 cxmreg_max = CXMREG_MAX; 1855 else if (ver->fcxmreg == 2) 1856 cxmreg_max = CXMREG_MAX_V2; 1857 else 1858 return; 1859 1860 if (n > cxmreg_max) { 1861 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1862 "[BTC], %s(): mon reg count %d > %d\n", 1863 __func__, n, cxmreg_max); 1864 return; 1865 } 1866 1867 ulen = sizeof(monreg->regs[0]); 1868 sz = struct_size(monreg, regs, n); 1869 monreg = kmalloc(sz, GFP_KERNEL); 1870 if (!monreg) 1871 return; 1872 1873 monreg->fver = ver->fcxmreg; 1874 monreg->reg_num = n; 1875 memcpy(monreg->regs, chip->mon_reg, flex_array_size(monreg, regs, n)); 1876 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1877 "[BTC], %s(): sz=%d ulen=%d n=%d\n", 1878 __func__, sz, ulen, n); 1879 1880 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, (u8 *)monreg, sz); 1881 kfree(monreg); 1882 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1); 1883 } 1884 1885 static void _update_dm_step(struct rtw89_dev *rtwdev, 1886 enum btc_reason_and_action reason_or_action) 1887 { 1888 struct rtw89_btc *btc = &rtwdev->btc; 1889 struct rtw89_btc_dm *dm = &btc->dm; 1890 1891 /* use ring-structure to store dm step */ 1892 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action; 1893 dm->dm_step.step_pos++; 1894 1895 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) { 1896 dm->dm_step.step_pos = 0; 1897 dm->dm_step.step_ov = true; 1898 } 1899 } 1900 1901 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 1902 enum btc_reason_and_action action) 1903 { 1904 struct rtw89_btc *btc = &rtwdev->btc; 1905 struct rtw89_btc_dm *dm = &btc->dm; 1906 1907 dm->run_action = action; 1908 1909 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT); 1910 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT); 1911 1912 btc->policy_len = 0; 1913 btc->policy_type = policy_type; 1914 1915 _append_tdma(rtwdev); 1916 _append_slot(rtwdev); 1917 1918 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN) 1919 return; 1920 1921 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1922 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n", 1923 __func__, action, policy_type, btc->policy_len); 1924 1925 if (dm->tdma.rxflctrl == CXFLC_NULLP || 1926 dm->tdma.rxflctrl == CXFLC_QOSNULL) 1927 btc->lps = 1; 1928 else 1929 btc->lps = 0; 1930 1931 if (btc->lps == 1) 1932 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps); 1933 1934 _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY, 1935 btc->policy, btc->policy_len); 1936 1937 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now)); 1938 memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now)); 1939 1940 if (btc->update_policy_force) 1941 btc->update_policy_force = false; 1942 1943 if (btc->lps == 0) 1944 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps); 1945 } 1946 1947 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type) 1948 { 1949 struct rtw89_btc *btc = &rtwdev->btc; 1950 const struct rtw89_btc_ver *ver = btc->ver; 1951 struct rtw89_btc_dm *dm = &btc->dm; 1952 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1953 struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para; 1954 1955 switch (type) { 1956 case CXDRVINFO_INIT: 1957 rtw89_fw_h2c_cxdrv_init(rtwdev); 1958 break; 1959 case CXDRVINFO_ROLE: 1960 if (ver->fwlrole == 0) 1961 rtw89_fw_h2c_cxdrv_role(rtwdev); 1962 else if (ver->fwlrole == 1) 1963 rtw89_fw_h2c_cxdrv_role_v1(rtwdev); 1964 else if (ver->fwlrole == 2) 1965 rtw89_fw_h2c_cxdrv_role_v2(rtwdev); 1966 break; 1967 case CXDRVINFO_CTRL: 1968 rtw89_fw_h2c_cxdrv_ctrl(rtwdev); 1969 break; 1970 case CXDRVINFO_TRX: 1971 dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power, 1972 RTW89_BTC_WL_DEF_TX_PWR); 1973 dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain, 1974 RTW89_BTC_WL_DEF_TX_PWR); 1975 dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power, 1976 RTW89_BTC_WL_DEF_TX_PWR); 1977 dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain, 1978 RTW89_BTC_WL_DEF_TX_PWR); 1979 dm->trx_info.cn = wl->cn_report; 1980 dm->trx_info.nhm = wl->nhm.pwr; 1981 rtw89_fw_h2c_cxdrv_trx(rtwdev); 1982 break; 1983 case CXDRVINFO_RFK: 1984 rtw89_fw_h2c_cxdrv_rfk(rtwdev); 1985 break; 1986 default: 1987 break; 1988 } 1989 } 1990 1991 static 1992 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len) 1993 { 1994 struct rtw89_btc *btc = &rtwdev->btc; 1995 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 1996 1997 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1998 "[BTC], %s(): evt_id:%d len:%d\n", 1999 __func__, evt_id, len); 2000 2001 if (!len || !data) 2002 return; 2003 2004 switch (evt_id) { 2005 case BTF_EVNT_RPT: 2006 _parse_btc_report(rtwdev, pfwinfo, data, len); 2007 break; 2008 default: 2009 break; 2010 } 2011 } 2012 2013 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state) 2014 { 2015 struct rtw89_btc *btc = &rtwdev->btc; 2016 struct rtw89_btc_dm *dm = &btc->dm; 2017 struct rtw89_mac_ax_gnt *g = dm->gnt.band; 2018 u8 i; 2019 2020 if (phy_map > BTC_PHY_ALL) 2021 return; 2022 2023 for (i = 0; i < RTW89_PHY_MAX; i++) { 2024 if (!(phy_map & BIT(i))) 2025 continue; 2026 2027 switch (wl_state) { 2028 case BTC_GNT_HW: 2029 g[i].gnt_wl_sw_en = 0; 2030 g[i].gnt_wl = 0; 2031 break; 2032 case BTC_GNT_SW_LO: 2033 g[i].gnt_wl_sw_en = 1; 2034 g[i].gnt_wl = 0; 2035 break; 2036 case BTC_GNT_SW_HI: 2037 g[i].gnt_wl_sw_en = 1; 2038 g[i].gnt_wl = 1; 2039 break; 2040 } 2041 2042 switch (bt_state) { 2043 case BTC_GNT_HW: 2044 g[i].gnt_bt_sw_en = 0; 2045 g[i].gnt_bt = 0; 2046 break; 2047 case BTC_GNT_SW_LO: 2048 g[i].gnt_bt_sw_en = 1; 2049 g[i].gnt_bt = 0; 2050 break; 2051 case BTC_GNT_SW_HI: 2052 g[i].gnt_bt_sw_en = 1; 2053 g[i].gnt_bt = 1; 2054 break; 2055 } 2056 } 2057 2058 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt); 2059 } 2060 2061 #define BTC_TDMA_WLROLE_MAX 2 2062 2063 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable) 2064 { 2065 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2066 "[BTC], %s(): set bt %s wlan_act\n", __func__, 2067 enable ? "ignore" : "do not ignore"); 2068 2069 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1); 2070 } 2071 2072 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0) 2073 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0) 2074 #define WL_TX_POWER_WITH_BT GENMASK(31, 16) 2075 #define WL_TX_POWER_INT_PART GENMASK(8, 2) 2076 #define WL_TX_POWER_FRA_PART GENMASK(1, 0) 2077 #define B_BTC_WL_TX_POWER_SIGN BIT(7) 2078 #define B_TSSI_WL_TX_POWER_SIGN BIT(8) 2079 2080 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level) 2081 { 2082 const struct rtw89_chip_info *chip = rtwdev->chip; 2083 struct rtw89_btc *btc = &rtwdev->btc; 2084 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2085 u32 pwr_val; 2086 2087 if (wl->rf_para.tx_pwr_freerun == level) 2088 return; 2089 2090 wl->rf_para.tx_pwr_freerun = level; 2091 btc->dm.rf_trx_para.wl_tx_power = level; 2092 2093 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2094 "[BTC], %s(): level = %d\n", 2095 __func__, level); 2096 2097 if (level == RTW89_BTC_WL_DEF_TX_PWR) { 2098 pwr_val = WL_TX_POWER_NO_BTC_CTRL; 2099 } else { /* only apply "force tx power" */ 2100 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level); 2101 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR) 2102 pwr_val = RTW89_BTC_WL_DEF_TX_PWR; 2103 2104 if (level & B_BTC_WL_TX_POWER_SIGN) 2105 pwr_val |= B_TSSI_WL_TX_POWER_SIGN; 2106 pwr_val |= WL_TX_POWER_WITH_BT; 2107 } 2108 2109 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val); 2110 } 2111 2112 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) 2113 { 2114 const struct rtw89_chip_info *chip = rtwdev->chip; 2115 struct rtw89_btc *btc = &rtwdev->btc; 2116 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2117 2118 if (wl->rf_para.rx_gain_freerun == level) 2119 return; 2120 2121 wl->rf_para.rx_gain_freerun = level; 2122 btc->dm.rf_trx_para.wl_rx_gain = level; 2123 2124 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2125 "[BTC], %s(): level = %d\n", 2126 __func__, level); 2127 2128 chip->ops->btc_set_wl_rx_gain(rtwdev, level); 2129 } 2130 2131 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level) 2132 { 2133 struct rtw89_btc *btc = &rtwdev->btc; 2134 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2135 u8 buf; 2136 2137 if (bt->rf_para.tx_pwr_freerun == level) 2138 return; 2139 2140 bt->rf_para.tx_pwr_freerun = level; 2141 btc->dm.rf_trx_para.bt_tx_power = level; 2142 2143 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2144 "[BTC], %s(): level = %d\n", 2145 __func__, level); 2146 2147 buf = (s8)(-level); 2148 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1); 2149 } 2150 2151 #define BTC_BT_RX_NORMAL_LVL 7 2152 2153 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level) 2154 { 2155 struct rtw89_btc *btc = &rtwdev->btc; 2156 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2157 2158 if (bt->rf_para.rx_gain_freerun == level || 2159 level > BTC_BT_RX_NORMAL_LVL) 2160 return; 2161 2162 bt->rf_para.rx_gain_freerun = level; 2163 btc->dm.rf_trx_para.bt_rx_gain = level; 2164 2165 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2166 "[BTC], %s(): level = %d\n", 2167 __func__, level); 2168 2169 if (level == BTC_BT_RX_NORMAL_LVL) 2170 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false); 2171 else 2172 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true); 2173 2174 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, 1); 2175 } 2176 2177 static void _set_rf_trx_para(struct rtw89_dev *rtwdev) 2178 { 2179 const struct rtw89_chip_info *chip = rtwdev->chip; 2180 struct rtw89_btc *btc = &rtwdev->btc; 2181 struct rtw89_btc_dm *dm = &btc->dm; 2182 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2183 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2184 struct rtw89_btc_bt_link_info *b = &bt->link_info; 2185 struct rtw89_btc_rf_trx_para para; 2186 u32 wl_stb_chg = 0; 2187 u8 level_id = 0; 2188 2189 if (!dm->freerun) { 2190 /* fix LNA2 = level-5 for BT ACI issue at BTG */ 2191 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) || 2192 dm->bt_only == 1) 2193 dm->trx_para_level = 1; 2194 else 2195 dm->trx_para_level = 0; 2196 } 2197 2198 level_id = (u8)dm->trx_para_level; 2199 2200 if (level_id >= chip->rf_para_dlink_num || 2201 level_id >= chip->rf_para_ulink_num) { 2202 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2203 "[BTC], %s(): invalid level_id: %d\n", 2204 __func__, level_id); 2205 return; 2206 } 2207 2208 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 2209 para = chip->rf_para_ulink[level_id]; 2210 else 2211 para = chip->rf_para_dlink[level_id]; 2212 2213 if (para.wl_tx_power != RTW89_BTC_WL_DEF_TX_PWR) 2214 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2215 "[BTC], %s(): wl_tx_power=%d\n", 2216 __func__, para.wl_tx_power); 2217 _set_wl_tx_power(rtwdev, para.wl_tx_power); 2218 _set_wl_rx_gain(rtwdev, para.wl_rx_gain); 2219 _set_bt_tx_power(rtwdev, para.bt_tx_power); 2220 _set_bt_rx_gain(rtwdev, para.bt_rx_gain); 2221 2222 if (bt->enable.now == 0 || wl->status.map.rf_off == 1 || 2223 wl->status.map.lps == BTC_LPS_RF_OFF) 2224 wl_stb_chg = 0; 2225 else 2226 wl_stb_chg = 1; 2227 2228 if (wl_stb_chg != dm->wl_stb_chg) { 2229 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2230 "[BTC], %s(): wl_stb_chg=%d\n", 2231 __func__, wl_stb_chg); 2232 dm->wl_stb_chg = wl_stb_chg; 2233 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 2234 } 2235 } 2236 2237 static void _update_btc_state_map(struct rtw89_dev *rtwdev) 2238 { 2239 struct rtw89_btc *btc = &rtwdev->btc; 2240 struct rtw89_btc_cx *cx = &btc->cx; 2241 struct rtw89_btc_wl_info *wl = &cx->wl; 2242 struct rtw89_btc_bt_info *bt = &cx->bt; 2243 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 2244 2245 if (wl->status.map.connecting || wl->status.map._4way || 2246 wl->status.map.roaming) { 2247 cx->state_map = BTC_WLINKING; 2248 } else if (wl->status.map.scan) { /* wl scan */ 2249 if (bt_linfo->status.map.inq_pag) 2250 cx->state_map = BTC_WSCAN_BSCAN; 2251 else 2252 cx->state_map = BTC_WSCAN_BNOSCAN; 2253 } else if (wl->status.map.busy) { /* only busy */ 2254 if (bt_linfo->status.map.inq_pag) 2255 cx->state_map = BTC_WBUSY_BSCAN; 2256 else 2257 cx->state_map = BTC_WBUSY_BNOSCAN; 2258 } else { /* wl idle */ 2259 cx->state_map = BTC_WIDLE; 2260 } 2261 } 2262 2263 static void _set_bt_afh_info(struct rtw89_dev *rtwdev) 2264 { 2265 const struct rtw89_chip_info *chip = rtwdev->chip; 2266 struct rtw89_btc *btc = &rtwdev->btc; 2267 const struct rtw89_btc_ver *ver = btc->ver; 2268 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2269 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2270 struct rtw89_btc_bt_link_info *b = &bt->link_info; 2271 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 2272 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 2273 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 2274 struct rtw89_btc_wl_active_role *r; 2275 struct rtw89_btc_wl_active_role_v1 *r1; 2276 struct rtw89_btc_wl_active_role_v2 *r2; 2277 u8 en = 0, i, ch = 0, bw = 0; 2278 u8 mode, connect_cnt; 2279 2280 if (btc->ctrl.manual || wl->status.map.scan) 2281 return; 2282 2283 if (ver->fwlrole == 0) { 2284 mode = wl_rinfo->link_mode; 2285 connect_cnt = wl_rinfo->connect_cnt; 2286 } else if (ver->fwlrole == 1) { 2287 mode = wl_rinfo_v1->link_mode; 2288 connect_cnt = wl_rinfo_v1->connect_cnt; 2289 } else if (ver->fwlrole == 2) { 2290 mode = wl_rinfo_v2->link_mode; 2291 connect_cnt = wl_rinfo_v2->connect_cnt; 2292 } else { 2293 return; 2294 } 2295 2296 if (wl->status.map.rf_off || bt->whql_test || 2297 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G || 2298 connect_cnt > BTC_TDMA_WLROLE_MAX) { 2299 en = false; 2300 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) { 2301 en = true; 2302 /* get p2p channel */ 2303 for (i = 0; i < RTW89_PORT_NUM; i++) { 2304 r = &wl_rinfo->active_role[i]; 2305 r1 = &wl_rinfo_v1->active_role_v1[i]; 2306 r2 = &wl_rinfo_v2->active_role_v2[i]; 2307 2308 if (ver->fwlrole == 0 && 2309 (r->role == RTW89_WIFI_ROLE_P2P_GO || 2310 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 2311 ch = r->ch; 2312 bw = r->bw; 2313 break; 2314 } else if (ver->fwlrole == 1 && 2315 (r1->role == RTW89_WIFI_ROLE_P2P_GO || 2316 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 2317 ch = r1->ch; 2318 bw = r1->bw; 2319 break; 2320 } else if (ver->fwlrole == 2 && 2321 (r2->role == RTW89_WIFI_ROLE_P2P_GO || 2322 r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 2323 ch = r2->ch; 2324 bw = r2->bw; 2325 break; 2326 } 2327 } 2328 } else { 2329 en = true; 2330 /* get 2g channel */ 2331 for (i = 0; i < RTW89_PORT_NUM; i++) { 2332 r = &wl_rinfo->active_role[i]; 2333 r1 = &wl_rinfo_v1->active_role_v1[i]; 2334 r2 = &wl_rinfo_v2->active_role_v2[i]; 2335 2336 if (ver->fwlrole == 0 && 2337 r->connected && r->band == RTW89_BAND_2G) { 2338 ch = r->ch; 2339 bw = r->bw; 2340 break; 2341 } else if (ver->fwlrole == 1 && 2342 r1->connected && r1->band == RTW89_BAND_2G) { 2343 ch = r1->ch; 2344 bw = r1->bw; 2345 break; 2346 } else if (ver->fwlrole == 2 && 2347 r2->connected && r2->band == RTW89_BAND_2G) { 2348 ch = r2->ch; 2349 bw = r2->bw; 2350 break; 2351 } 2352 } 2353 } 2354 2355 switch (bw) { 2356 case RTW89_CHANNEL_WIDTH_20: 2357 bw = 20 + chip->afh_guard_ch * 2; 2358 break; 2359 case RTW89_CHANNEL_WIDTH_40: 2360 bw = 40 + chip->afh_guard_ch * 2; 2361 break; 2362 case RTW89_CHANNEL_WIDTH_5: 2363 bw = 5 + chip->afh_guard_ch * 2; 2364 break; 2365 case RTW89_CHANNEL_WIDTH_10: 2366 bw = 10 + chip->afh_guard_ch * 2; 2367 break; 2368 default: 2369 bw = 0; 2370 en = false; /* turn off AFH info if BW > 40 */ 2371 break; 2372 } 2373 2374 if (wl->afh_info.en == en && 2375 wl->afh_info.ch == ch && 2376 wl->afh_info.bw == bw && 2377 b->profile_cnt.last == b->profile_cnt.now) { 2378 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2379 "[BTC], %s(): return because no change!\n", 2380 __func__); 2381 return; 2382 } 2383 2384 wl->afh_info.en = en; 2385 wl->afh_info.ch = ch; 2386 wl->afh_info.bw = bw; 2387 2388 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3); 2389 2390 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2391 "[BTC], %s(): en=%d, ch=%d, bw=%d\n", 2392 __func__, en, ch, bw); 2393 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; 2394 } 2395 2396 static bool _check_freerun(struct rtw89_dev *rtwdev) 2397 { 2398 struct rtw89_btc *btc = &rtwdev->btc; 2399 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2400 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2401 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 2402 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 2403 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 2404 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc; 2405 2406 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 2407 btc->dm.trx_para_level = 0; 2408 return false; 2409 } 2410 2411 /* The below is dedicated antenna case */ 2412 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX || 2413 wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) { 2414 btc->dm.trx_para_level = 5; 2415 return true; 2416 } 2417 2418 if (bt_linfo->profile_cnt.now == 0) { 2419 btc->dm.trx_para_level = 5; 2420 return true; 2421 } 2422 2423 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) { 2424 btc->dm.trx_para_level = 5; 2425 return true; 2426 } 2427 2428 /* TODO get isolation by BT psd */ 2429 if (btc->mdinfo.ant.isolation >= BTC_FREERUN_ANTISO_MIN) { 2430 btc->dm.trx_para_level = 5; 2431 return true; 2432 } 2433 2434 if (!wl->status.map.busy) {/* wl idle -> freerun */ 2435 btc->dm.trx_para_level = 5; 2436 return true; 2437 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */ 2438 btc->dm.trx_para_level = 0; 2439 return false; 2440 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 2441 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) { 2442 btc->dm.trx_para_level = 6; 2443 return true; 2444 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) { 2445 btc->dm.trx_para_level = 7; 2446 return true; 2447 } 2448 btc->dm.trx_para_level = 0; 2449 return false; 2450 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) { 2451 if (bt_linfo->rssi > 28) { 2452 btc->dm.trx_para_level = 6; 2453 return true; 2454 } 2455 } 2456 2457 btc->dm.trx_para_level = 0; 2458 return false; 2459 } 2460 2461 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; }) 2462 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; }) 2463 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; }) 2464 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; }) 2465 2466 #define _slot_set(btc, sid, dura, tbl, type) \ 2467 do { \ 2468 typeof(sid) _sid = (sid); \ 2469 typeof(btc) _btc = (btc); \ 2470 _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\ 2471 _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \ 2472 _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \ 2473 } while (0) 2474 2475 #define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura) 2476 #define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl) 2477 #define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type) 2478 2479 struct btc_btinfo_lb2 { 2480 u8 connect: 1; 2481 u8 sco_busy: 1; 2482 u8 inq_pag: 1; 2483 u8 acl_busy: 1; 2484 u8 hfp: 1; 2485 u8 hid: 1; 2486 u8 a2dp: 1; 2487 u8 pan: 1; 2488 }; 2489 2490 struct btc_btinfo_lb3 { 2491 u8 retry: 4; 2492 u8 cqddr: 1; 2493 u8 inq: 1; 2494 u8 mesh_busy: 1; 2495 u8 pag: 1; 2496 }; 2497 2498 struct btc_btinfo_hb0 { 2499 s8 rssi; 2500 }; 2501 2502 struct btc_btinfo_hb1 { 2503 u8 ble_connect: 1; 2504 u8 reinit: 1; 2505 u8 relink: 1; 2506 u8 igno_wl: 1; 2507 u8 voice: 1; 2508 u8 ble_scan: 1; 2509 u8 role_sw: 1; 2510 u8 multi_link: 1; 2511 }; 2512 2513 struct btc_btinfo_hb2 { 2514 u8 pan_active: 1; 2515 u8 afh_update: 1; 2516 u8 a2dp_active: 1; 2517 u8 slave: 1; 2518 u8 hid_slot: 2; 2519 u8 hid_cnt: 2; 2520 }; 2521 2522 struct btc_btinfo_hb3 { 2523 u8 a2dp_bitpool: 6; 2524 u8 tx_3m: 1; 2525 u8 a2dp_sink: 1; 2526 }; 2527 2528 union btc_btinfo { 2529 u8 val; 2530 struct btc_btinfo_lb2 lb2; 2531 struct btc_btinfo_lb3 lb3; 2532 struct btc_btinfo_hb0 hb0; 2533 struct btc_btinfo_hb1 hb1; 2534 struct btc_btinfo_hb2 hb2; 2535 struct btc_btinfo_hb3 hb3; 2536 }; 2537 2538 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 2539 enum btc_reason_and_action action) 2540 { 2541 const struct rtw89_chip_info *chip = rtwdev->chip; 2542 2543 chip->ops->btc_set_policy(rtwdev, policy_type); 2544 _fw_set_policy(rtwdev, policy_type, action); 2545 } 2546 2547 #define BTC_B1_MAX 250 /* unit ms */ 2548 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type) 2549 { 2550 struct rtw89_btc *btc = &rtwdev->btc; 2551 struct rtw89_btc_dm *dm = &btc->dm; 2552 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 2553 struct rtw89_btc_fbtc_slot *s = dm->slot; 2554 u8 type; 2555 u32 tbl_w1, tbl_b1, tbl_b4; 2556 2557 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 2558 if (btc->cx.wl.status.map._4way) 2559 tbl_w1 = cxtbl[1]; 2560 else 2561 tbl_w1 = cxtbl[8]; 2562 tbl_b1 = cxtbl[3]; 2563 tbl_b4 = cxtbl[3]; 2564 } else { 2565 tbl_w1 = cxtbl[16]; 2566 tbl_b1 = cxtbl[17]; 2567 tbl_b4 = cxtbl[17]; 2568 } 2569 2570 type = (u8)((policy_type & BTC_CXP_MASK) >> 8); 2571 btc->bt_req_en = false; 2572 2573 switch (type) { 2574 case BTC_CXP_USERDEF0: 2575 *t = t_def[CXTD_OFF]; 2576 s[CXST_OFF] = s_def[CXST_OFF]; 2577 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2578 btc->update_policy_force = true; 2579 break; 2580 case BTC_CXP_OFF: /* TDMA off */ 2581 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2582 *t = t_def[CXTD_OFF]; 2583 s[CXST_OFF] = s_def[CXST_OFF]; 2584 2585 switch (policy_type) { 2586 case BTC_CXP_OFF_BT: 2587 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2588 break; 2589 case BTC_CXP_OFF_WL: 2590 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 2591 break; 2592 case BTC_CXP_OFF_EQ0: 2593 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 2594 break; 2595 case BTC_CXP_OFF_EQ1: 2596 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 2597 break; 2598 case BTC_CXP_OFF_EQ2: 2599 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 2600 break; 2601 case BTC_CXP_OFF_EQ3: 2602 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 2603 break; 2604 case BTC_CXP_OFF_BWB0: 2605 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 2606 break; 2607 case BTC_CXP_OFF_BWB1: 2608 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2609 break; 2610 case BTC_CXP_OFF_BWB3: 2611 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 2612 break; 2613 } 2614 break; 2615 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 2616 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2617 *t = t_def[CXTD_OFF_B2]; 2618 s[CXST_OFF] = s_def[CXST_OFF]; 2619 switch (policy_type) { 2620 case BTC_CXP_OFFB_BWB0: 2621 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2622 break; 2623 } 2624 break; 2625 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 2626 btc->bt_req_en = true; 2627 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2628 *t = t_def[CXTD_OFF_EXT]; 2629 switch (policy_type) { 2630 case BTC_CXP_OFFE_DEF: 2631 s[CXST_E2G] = s_def[CXST_E2G]; 2632 s[CXST_E5G] = s_def[CXST_E5G]; 2633 s[CXST_EBT] = s_def[CXST_EBT]; 2634 s[CXST_ENULL] = s_def[CXST_ENULL]; 2635 break; 2636 case BTC_CXP_OFFE_DEF2: 2637 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 2638 s[CXST_E5G] = s_def[CXST_E5G]; 2639 s[CXST_EBT] = s_def[CXST_EBT]; 2640 s[CXST_ENULL] = s_def[CXST_ENULL]; 2641 break; 2642 } 2643 break; 2644 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 2645 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2646 *t = t_def[CXTD_FIX]; 2647 switch (policy_type) { 2648 case BTC_CXP_FIX_TD3030: 2649 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2650 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2651 break; 2652 case BTC_CXP_FIX_TD5050: 2653 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2654 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2655 break; 2656 case BTC_CXP_FIX_TD2030: 2657 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2658 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2659 break; 2660 case BTC_CXP_FIX_TD4010: 2661 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 2662 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2663 break; 2664 case BTC_CXP_FIX_TD4020: 2665 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX); 2666 _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX); 2667 break; 2668 case BTC_CXP_FIX_TD7010: 2669 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 2670 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2671 break; 2672 case BTC_CXP_FIX_TD2060: 2673 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2674 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2675 break; 2676 case BTC_CXP_FIX_TD3060: 2677 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2678 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2679 break; 2680 case BTC_CXP_FIX_TD2080: 2681 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2682 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2683 break; 2684 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 2685 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2686 tbl_w1, SLOT_ISO); 2687 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2688 tbl_b1, SLOT_MIX); 2689 break; 2690 } 2691 break; 2692 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 2693 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2694 *t = t_def[CXTD_PFIX]; 2695 if (btc->cx.wl.role_info.role_map.role.ap) 2696 _tdma_set_flctrl(btc, CXFLC_QOSNULL); 2697 2698 switch (policy_type) { 2699 case BTC_CXP_PFIX_TD3030: 2700 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2701 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2702 break; 2703 case BTC_CXP_PFIX_TD5050: 2704 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2705 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2706 break; 2707 case BTC_CXP_PFIX_TD2030: 2708 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2709 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2710 break; 2711 case BTC_CXP_PFIX_TD2060: 2712 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2713 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2714 break; 2715 case BTC_CXP_PFIX_TD3070: 2716 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2717 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2718 break; 2719 case BTC_CXP_PFIX_TD2080: 2720 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2721 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2722 break; 2723 } 2724 break; 2725 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 2726 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2727 *t = t_def[CXTD_AUTO]; 2728 switch (policy_type) { 2729 case BTC_CXP_AUTO_TD50B1: 2730 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2731 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2732 break; 2733 case BTC_CXP_AUTO_TD60B1: 2734 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2735 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2736 break; 2737 case BTC_CXP_AUTO_TD20B1: 2738 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2739 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2740 break; 2741 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 2742 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2743 tbl_w1, SLOT_ISO); 2744 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2745 tbl_b1, SLOT_MIX); 2746 break; 2747 } 2748 break; 2749 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 2750 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2751 *t = t_def[CXTD_PAUTO]; 2752 switch (policy_type) { 2753 case BTC_CXP_PAUTO_TD50B1: 2754 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2755 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2756 break; 2757 case BTC_CXP_PAUTO_TD60B1: 2758 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2759 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2760 break; 2761 case BTC_CXP_PAUTO_TD20B1: 2762 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2763 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2764 break; 2765 case BTC_CXP_PAUTO_TDW1B1: 2766 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2767 tbl_w1, SLOT_ISO); 2768 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2769 tbl_b1, SLOT_MIX); 2770 break; 2771 } 2772 break; 2773 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 2774 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2775 *t = t_def[CXTD_AUTO2]; 2776 switch (policy_type) { 2777 case BTC_CXP_AUTO2_TD3050: 2778 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2779 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2780 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2781 break; 2782 case BTC_CXP_AUTO2_TD3070: 2783 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2784 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 2785 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2786 break; 2787 case BTC_CXP_AUTO2_TD5050: 2788 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2789 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2790 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2791 break; 2792 case BTC_CXP_AUTO2_TD6060: 2793 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2794 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 2795 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2796 break; 2797 case BTC_CXP_AUTO2_TD2080: 2798 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2799 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 2800 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2801 break; 2802 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 2803 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2804 tbl_w1, SLOT_ISO); 2805 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 2806 tbl_b4, SLOT_MIX); 2807 break; 2808 } 2809 break; 2810 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 2811 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2812 *t = t_def[CXTD_PAUTO2]; 2813 switch (policy_type) { 2814 case BTC_CXP_PAUTO2_TD3050: 2815 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2816 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2817 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2818 break; 2819 case BTC_CXP_PAUTO2_TD3070: 2820 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2821 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 2822 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2823 break; 2824 case BTC_CXP_PAUTO2_TD5050: 2825 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2826 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2827 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2828 break; 2829 case BTC_CXP_PAUTO2_TD6060: 2830 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2831 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 2832 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2833 break; 2834 case BTC_CXP_PAUTO2_TD2080: 2835 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2836 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 2837 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2838 break; 2839 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 2840 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2841 tbl_w1, SLOT_ISO); 2842 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 2843 tbl_b4, SLOT_MIX); 2844 break; 2845 } 2846 break; 2847 } 2848 } 2849 EXPORT_SYMBOL(rtw89_btc_set_policy); 2850 2851 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) 2852 { 2853 struct rtw89_btc *btc = &rtwdev->btc; 2854 struct rtw89_btc_dm *dm = &btc->dm; 2855 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 2856 struct rtw89_btc_fbtc_slot *s = dm->slot; 2857 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1; 2858 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc; 2859 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc; 2860 u8 type, null_role; 2861 u32 tbl_w1, tbl_b1, tbl_b4; 2862 2863 type = FIELD_GET(BTC_CXP_MASK, policy_type); 2864 2865 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 2866 if (btc->cx.wl.status.map._4way) 2867 tbl_w1 = cxtbl[1]; 2868 else if (hid->exist && hid->type == BTC_HID_218) 2869 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */ 2870 else 2871 tbl_w1 = cxtbl[8]; 2872 2873 if (dm->leak_ap && 2874 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) { 2875 tbl_b1 = cxtbl[3]; 2876 tbl_b4 = cxtbl[3]; 2877 } else if (hid->exist && hid->type == BTC_HID_218) { 2878 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */ 2879 tbl_b4 = cxtbl[4]; 2880 } else { 2881 tbl_b1 = cxtbl[2]; 2882 tbl_b4 = cxtbl[2]; 2883 } 2884 } else { 2885 tbl_w1 = cxtbl[16]; 2886 tbl_b1 = cxtbl[17]; 2887 tbl_b4 = cxtbl[17]; 2888 } 2889 2890 btc->bt_req_en = false; 2891 2892 switch (type) { 2893 case BTC_CXP_USERDEF0: 2894 btc->update_policy_force = true; 2895 *t = t_def[CXTD_OFF]; 2896 s[CXST_OFF] = s_def[CXST_OFF]; 2897 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2898 break; 2899 case BTC_CXP_OFF: /* TDMA off */ 2900 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2901 *t = t_def[CXTD_OFF]; 2902 s[CXST_OFF] = s_def[CXST_OFF]; 2903 2904 switch (policy_type) { 2905 case BTC_CXP_OFF_BT: 2906 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2907 break; 2908 case BTC_CXP_OFF_WL: 2909 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 2910 break; 2911 case BTC_CXP_OFF_EQ0: 2912 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 2913 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 2914 break; 2915 case BTC_CXP_OFF_EQ1: 2916 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 2917 break; 2918 case BTC_CXP_OFF_EQ2: 2919 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 2920 break; 2921 case BTC_CXP_OFF_EQ3: 2922 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); 2923 break; 2924 case BTC_CXP_OFF_BWB0: 2925 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 2926 break; 2927 case BTC_CXP_OFF_BWB1: 2928 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2929 break; 2930 case BTC_CXP_OFF_BWB2: 2931 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 2932 break; 2933 case BTC_CXP_OFF_BWB3: 2934 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 2935 break; 2936 default: 2937 break; 2938 } 2939 break; 2940 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 2941 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2942 *t = t_def[CXTD_OFF_B2]; 2943 s[CXST_OFF] = s_def[CXST_OFF]; 2944 2945 switch (policy_type) { 2946 case BTC_CXP_OFFB_BWB0: 2947 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2948 break; 2949 default: 2950 break; 2951 } 2952 break; 2953 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 2954 btc->bt_req_en = true; 2955 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2956 *t = t_def[CXTD_OFF_EXT]; 2957 2958 /* To avoid wl-s0 tx break by hid/hfp tx */ 2959 if (hid->exist || hfp->exist) 2960 tbl_w1 = cxtbl[16]; 2961 2962 switch (policy_type) { 2963 case BTC_CXP_OFFE_DEF: 2964 s[CXST_E2G] = s_def[CXST_E2G]; 2965 s[CXST_E5G] = s_def[CXST_E5G]; 2966 s[CXST_EBT] = s_def[CXST_EBT]; 2967 s[CXST_ENULL] = s_def[CXST_ENULL]; 2968 break; 2969 case BTC_CXP_OFFE_DEF2: 2970 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 2971 s[CXST_E5G] = s_def[CXST_E5G]; 2972 s[CXST_EBT] = s_def[CXST_EBT]; 2973 s[CXST_ENULL] = s_def[CXST_ENULL]; 2974 break; 2975 default: 2976 break; 2977 } 2978 s[CXST_OFF] = s_def[CXST_OFF]; 2979 break; 2980 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 2981 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2982 *t = t_def[CXTD_FIX]; 2983 2984 switch (policy_type) { 2985 case BTC_CXP_FIX_TD3030: 2986 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2987 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2988 break; 2989 case BTC_CXP_FIX_TD5050: 2990 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2991 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2992 break; 2993 case BTC_CXP_FIX_TD2030: 2994 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2995 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2996 break; 2997 case BTC_CXP_FIX_TD4010: 2998 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 2999 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3000 break; 3001 case BTC_CXP_FIX_TD4010ISO: 3002 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 3003 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3004 break; 3005 case BTC_CXP_FIX_TD4020: 3006 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX); 3007 _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX); 3008 break; 3009 case BTC_CXP_FIX_TD7010: 3010 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 3011 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3012 break; 3013 case BTC_CXP_FIX_TD2060: 3014 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3015 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3016 break; 3017 case BTC_CXP_FIX_TD3060: 3018 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3019 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3020 break; 3021 case BTC_CXP_FIX_TD2080: 3022 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3023 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 3024 break; 3025 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 3026 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3027 tbl_w1, SLOT_ISO); 3028 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3029 tbl_b1, SLOT_MIX); 3030 break; 3031 default: 3032 break; 3033 } 3034 break; 3035 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 3036 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3037 *t = t_def[CXTD_PFIX]; 3038 3039 switch (policy_type) { 3040 case BTC_CXP_PFIX_TD3030: 3041 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3042 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3043 break; 3044 case BTC_CXP_PFIX_TD5050: 3045 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3046 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 3047 break; 3048 case BTC_CXP_PFIX_TD2030: 3049 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3050 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3051 break; 3052 case BTC_CXP_PFIX_TD2060: 3053 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3054 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3055 break; 3056 case BTC_CXP_PFIX_TD3070: 3057 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3058 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3059 break; 3060 case BTC_CXP_PFIX_TD2080: 3061 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3062 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 3063 break; 3064 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */ 3065 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3066 tbl_w1, SLOT_ISO); 3067 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3068 tbl_b1, SLOT_MIX); 3069 break; 3070 default: 3071 break; 3072 } 3073 break; 3074 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 3075 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3076 *t = t_def[CXTD_AUTO]; 3077 3078 switch (policy_type) { 3079 case BTC_CXP_AUTO_TD50B1: 3080 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3081 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3082 break; 3083 case BTC_CXP_AUTO_TD60B1: 3084 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3085 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3086 break; 3087 case BTC_CXP_AUTO_TD20B1: 3088 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3089 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3090 break; 3091 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 3092 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3093 tbl_w1, SLOT_ISO); 3094 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3095 tbl_b1, SLOT_MIX); 3096 break; 3097 default: 3098 break; 3099 } 3100 break; 3101 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 3102 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3103 *t = t_def[CXTD_PAUTO]; 3104 3105 switch (policy_type) { 3106 case BTC_CXP_PAUTO_TD50B1: 3107 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3108 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3109 break; 3110 case BTC_CXP_PAUTO_TD60B1: 3111 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3112 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3113 break; 3114 case BTC_CXP_PAUTO_TD20B1: 3115 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3116 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3117 break; 3118 case BTC_CXP_PAUTO_TDW1B1: 3119 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3120 tbl_w1, SLOT_ISO); 3121 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3122 tbl_b1, SLOT_MIX); 3123 break; 3124 default: 3125 break; 3126 } 3127 break; 3128 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 3129 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3130 *t = t_def[CXTD_AUTO2]; 3131 3132 switch (policy_type) { 3133 case BTC_CXP_AUTO2_TD3050: 3134 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3135 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3136 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3137 break; 3138 case BTC_CXP_AUTO2_TD3070: 3139 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3140 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3141 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3142 break; 3143 case BTC_CXP_AUTO2_TD5050: 3144 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3145 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3146 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3147 break; 3148 case BTC_CXP_AUTO2_TD6060: 3149 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3150 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3151 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3152 break; 3153 case BTC_CXP_AUTO2_TD2080: 3154 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3155 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3156 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3157 break; 3158 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 3159 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3160 tbl_w1, SLOT_ISO); 3161 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3162 tbl_b1, SLOT_MIX); 3163 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3164 tbl_b4, SLOT_MIX); 3165 break; 3166 default: 3167 break; 3168 } 3169 break; 3170 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 3171 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3172 *t = t_def[CXTD_PAUTO2]; 3173 3174 switch (policy_type) { 3175 case BTC_CXP_PAUTO2_TD3050: 3176 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3177 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3178 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3179 break; 3180 case BTC_CXP_PAUTO2_TD3070: 3181 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3182 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3183 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3184 break; 3185 case BTC_CXP_PAUTO2_TD5050: 3186 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3187 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3188 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3189 break; 3190 case BTC_CXP_PAUTO2_TD6060: 3191 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3192 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3193 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3194 break; 3195 case BTC_CXP_PAUTO2_TD2080: 3196 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3197 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3198 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3199 break; 3200 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 3201 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3202 tbl_w1, SLOT_ISO); 3203 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3204 tbl_b1, SLOT_MIX); 3205 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3206 tbl_b4, SLOT_MIX); 3207 break; 3208 default: 3209 break; 3210 } 3211 break; 3212 } 3213 3214 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) { 3215 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) | 3216 FIELD_PREP(0xf0, dm->wl_scc.null_role2); 3217 _tdma_set_flctrl_role(btc, null_role); 3218 } 3219 3220 /* enter leak_slot after each null-1 */ 3221 if (dm->leak_ap && dm->tdma.leak_n > 1) 3222 _tdma_set_lek(btc, 1); 3223 3224 if (dm->tdma_instant_excute) { 3225 btc->dm.tdma.option_ctrl |= BIT(0); 3226 btc->update_policy_force = true; 3227 } 3228 } 3229 EXPORT_SYMBOL(rtw89_btc_set_policy_v1); 3230 3231 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map, 3232 u8 tx_val, u8 rx_val) 3233 { 3234 struct rtw89_mac_ax_plt plt; 3235 3236 plt.band = RTW89_MAC_0; 3237 plt.tx = tx_val; 3238 plt.rx = rx_val; 3239 3240 if (phy_map & BTC_PHY_0) 3241 rtw89_mac_cfg_plt(rtwdev, &plt); 3242 3243 if (!rtwdev->dbcc_en) 3244 return; 3245 3246 plt.band = RTW89_MAC_1; 3247 if (phy_map & BTC_PHY_1) 3248 rtw89_mac_cfg_plt(rtwdev, &plt); 3249 } 3250 3251 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec, 3252 u8 phy_map, u8 type) 3253 { 3254 struct rtw89_btc *btc = &rtwdev->btc; 3255 struct rtw89_btc_dm *dm = &btc->dm; 3256 struct rtw89_btc_cx *cx = &btc->cx; 3257 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3258 struct rtw89_btc_bt_info *bt = &cx->bt; 3259 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 3260 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0; 3261 u32 ant_path_type; 3262 3263 ant_path_type = ((phy_map << 8) + type); 3264 3265 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF || 3266 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE || 3267 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX) 3268 force_exec = FC_EXEC; 3269 3270 if (!force_exec && ant_path_type == dm->set_ant_path) { 3271 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3272 "[BTC], %s(): return by no change!!\n", 3273 __func__); 3274 return; 3275 } else if (bt->rfk_info.map.run) { 3276 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3277 "[BTC], %s(): return by bt rfk!!\n", __func__); 3278 return; 3279 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 3280 wl->rfk_info.state != BTC_WRFK_STOP) { 3281 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3282 "[BTC], %s(): return by wl rfk!!\n", __func__); 3283 return; 3284 } 3285 3286 dm->set_ant_path = ant_path_type; 3287 3288 rtw89_debug(rtwdev, 3289 RTW89_DBG_BTC, 3290 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 3291 __func__, phy_map, dm->set_ant_path & 0xff); 3292 3293 switch (type) { 3294 case BTC_ANT_WPOWERON: 3295 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 3296 break; 3297 case BTC_ANT_WINIT: 3298 if (bt->enable.now) 3299 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 3300 else 3301 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 3302 3303 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3304 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT); 3305 break; 3306 case BTC_ANT_WONLY: 3307 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 3308 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3309 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3310 break; 3311 case BTC_ANT_WOFF: 3312 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 3313 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3314 break; 3315 case BTC_ANT_W2G: 3316 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3317 if (rtwdev->dbcc_en) { 3318 for (i = 0; i < RTW89_PHY_MAX; i++) { 3319 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G); 3320 3321 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 3322 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 3323 /* BT should control by GNT_BT if WL_2G at S0 */ 3324 if (i == 1 && 3325 wl_dinfo->real_band[0] == RTW89_BAND_2G && 3326 wl_dinfo->real_band[1] == RTW89_BAND_5G) 3327 gnt_bt_ctrl = BTC_GNT_HW; 3328 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl); 3329 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE; 3330 _set_bt_plut(rtwdev, BIT(i), 3331 plt_ctrl, plt_ctrl); 3332 } 3333 } else { 3334 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 3335 _set_bt_plut(rtwdev, BTC_PHY_ALL, 3336 BTC_PLT_BT, BTC_PLT_BT); 3337 } 3338 break; 3339 case BTC_ANT_W5G: 3340 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3341 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW); 3342 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3343 break; 3344 case BTC_ANT_W25G: 3345 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3346 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 3347 _set_bt_plut(rtwdev, BTC_PHY_ALL, 3348 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 3349 break; 3350 case BTC_ANT_FREERUN: 3351 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3352 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI); 3353 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 3354 break; 3355 case BTC_ANT_WRFK: 3356 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 3357 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 3358 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 3359 break; 3360 case BTC_ANT_BRFK: 3361 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 3362 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 3363 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 3364 break; 3365 default: 3366 break; 3367 } 3368 } 3369 3370 static void _action_wl_only(struct rtw89_dev *rtwdev) 3371 { 3372 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 3373 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY); 3374 } 3375 3376 static void _action_wl_init(struct rtw89_dev *rtwdev) 3377 { 3378 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3379 3380 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT); 3381 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT); 3382 } 3383 3384 static void _action_wl_off(struct rtw89_dev *rtwdev) 3385 { 3386 struct rtw89_btc *btc = &rtwdev->btc; 3387 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3388 3389 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3390 3391 if (wl->status.map.rf_off || btc->dm.bt_only) 3392 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF); 3393 3394 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 3395 } 3396 3397 static void _action_freerun(struct rtw89_dev *rtwdev) 3398 { 3399 struct rtw89_btc *btc = &rtwdev->btc; 3400 3401 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3402 3403 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN); 3404 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN); 3405 3406 btc->dm.freerun = true; 3407 } 3408 3409 static void _action_bt_whql(struct rtw89_dev *rtwdev) 3410 { 3411 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3412 3413 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3414 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL); 3415 } 3416 3417 static void _action_bt_off(struct rtw89_dev *rtwdev) 3418 { 3419 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3420 3421 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 3422 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF); 3423 } 3424 3425 static void _action_bt_idle(struct rtw89_dev *rtwdev) 3426 { 3427 struct rtw89_btc *btc = &rtwdev->btc; 3428 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info; 3429 3430 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3431 3432 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3433 switch (btc->cx.state_map) { 3434 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/ 3435 if (b->profile_cnt.now > 0) 3436 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, 3437 BTC_ACT_BT_IDLE); 3438 else 3439 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, 3440 BTC_ACT_BT_IDLE); 3441 break; 3442 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */ 3443 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, 3444 BTC_ACT_BT_IDLE); 3445 break; 3446 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */ 3447 if (b->profile_cnt.now > 0) 3448 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, 3449 BTC_ACT_BT_IDLE); 3450 else 3451 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, 3452 BTC_ACT_BT_IDLE); 3453 break; 3454 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */ 3455 _set_policy(rtwdev, BTC_CXP_FIX_TD5050, 3456 BTC_ACT_BT_IDLE); 3457 break; 3458 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */ 3459 _set_policy(rtwdev, BTC_CXP_FIX_TD7010, 3460 BTC_ACT_BT_IDLE); 3461 break; 3462 case BTC_WIDLE: /* wl-idle + bt-idle */ 3463 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE); 3464 break; 3465 } 3466 } else { /* dedicated-antenna */ 3467 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE); 3468 } 3469 } 3470 3471 static void _action_bt_hfp(struct rtw89_dev *rtwdev) 3472 { 3473 struct rtw89_btc *btc = &rtwdev->btc; 3474 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3475 3476 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3477 3478 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 3479 if (btc->cx.wl.status.map._4way) { 3480 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP); 3481 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3482 btc->cx.bt.scan_rx_low_pri = true; 3483 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP); 3484 } else { 3485 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 3486 } 3487 } else { 3488 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP); 3489 } 3490 } 3491 3492 static void _action_bt_hid(struct rtw89_dev *rtwdev) 3493 { 3494 const struct rtw89_chip_info *chip = rtwdev->chip; 3495 struct rtw89_btc *btc = &rtwdev->btc; 3496 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3497 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3498 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc; 3499 u16 policy_type = BTC_CXP_OFF_BT; 3500 3501 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3502 3503 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3504 if (wl->status.map._4way) { 3505 policy_type = BTC_CXP_OFF_WL; 3506 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3507 btc->cx.bt.scan_rx_low_pri = true; 3508 if (hid->type & BTC_HID_BLE) 3509 policy_type = BTC_CXP_OFF_BWB0; 3510 else 3511 policy_type = BTC_CXP_OFF_BWB2; 3512 } else if (hid->type == BTC_HID_218) { 3513 bt->scan_rx_low_pri = true; 3514 policy_type = BTC_CXP_OFF_BWB2; 3515 } else if (chip->para_ver == 0x1) { 3516 policy_type = BTC_CXP_OFF_BWB3; 3517 } else { 3518 policy_type = BTC_CXP_OFF_BWB1; 3519 } 3520 } else { /* dedicated-antenna */ 3521 policy_type = BTC_CXP_OFF_EQ3; 3522 } 3523 3524 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID); 3525 } 3526 3527 static void _action_bt_a2dp(struct rtw89_dev *rtwdev) 3528 { 3529 struct rtw89_btc *btc = &rtwdev->btc; 3530 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 3531 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3532 struct rtw89_btc_dm *dm = &btc->dm; 3533 3534 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3535 3536 switch (btc->cx.state_map) { 3537 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 3538 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3539 dm->slot_dur[CXST_W1] = 40; 3540 dm->slot_dur[CXST_B1] = 200; 3541 _set_policy(rtwdev, 3542 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 3543 } else { 3544 _set_policy(rtwdev, 3545 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP); 3546 } 3547 break; 3548 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 3549 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 3550 break; 3551 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 3552 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 3553 break; 3554 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 3555 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 3556 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3557 dm->slot_dur[CXST_W1] = 40; 3558 dm->slot_dur[CXST_B1] = 200; 3559 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, 3560 BTC_ACT_BT_A2DP); 3561 } else { 3562 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, 3563 BTC_ACT_BT_A2DP); 3564 } 3565 break; 3566 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 3567 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 3568 break; 3569 } 3570 } 3571 3572 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 3573 { 3574 struct rtw89_btc *btc = &rtwdev->btc; 3575 3576 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3577 3578 switch (btc->cx.state_map) { 3579 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 3580 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 3581 break; 3582 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 3583 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 3584 break; 3585 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 3586 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 3587 break; 3588 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 3589 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 3590 break; 3591 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 3592 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 3593 break; 3594 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 3595 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 3596 break; 3597 } 3598 } 3599 3600 static void _action_bt_pan(struct rtw89_dev *rtwdev) 3601 { 3602 struct rtw89_btc *btc = &rtwdev->btc; 3603 3604 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3605 3606 switch (btc->cx.state_map) { 3607 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 3608 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 3609 break; 3610 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 3611 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 3612 break; 3613 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 3614 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 3615 break; 3616 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 3617 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 3618 break; 3619 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 3620 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, BTC_ACT_BT_PAN); 3621 break; 3622 case BTC_WIDLE: /* wl-idle + bt-pan */ 3623 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 3624 break; 3625 } 3626 } 3627 3628 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 3629 { 3630 struct rtw89_btc *btc = &rtwdev->btc; 3631 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 3632 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3633 struct rtw89_btc_dm *dm = &btc->dm; 3634 3635 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3636 3637 switch (btc->cx.state_map) { 3638 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 3639 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 3640 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3641 dm->slot_dur[CXST_W1] = 40; 3642 dm->slot_dur[CXST_B1] = 200; 3643 _set_policy(rtwdev, 3644 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 3645 } else { 3646 _set_policy(rtwdev, 3647 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID); 3648 } 3649 break; 3650 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 3651 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 3652 break; 3653 3654 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 3655 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 3656 break; 3657 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 3658 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 3659 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3660 dm->slot_dur[CXST_W1] = 40; 3661 dm->slot_dur[CXST_B1] = 200; 3662 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, 3663 BTC_ACT_BT_A2DP_HID); 3664 } else { 3665 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, 3666 BTC_ACT_BT_A2DP_HID); 3667 } 3668 break; 3669 } 3670 } 3671 3672 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 3673 { 3674 struct rtw89_btc *btc = &rtwdev->btc; 3675 3676 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3677 3678 switch (btc->cx.state_map) { 3679 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 3680 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3681 break; 3682 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 3683 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3684 break; 3685 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 3686 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 3687 break; 3688 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 3689 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3690 break; 3691 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 3692 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 3693 break; 3694 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 3695 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 3696 break; 3697 } 3698 } 3699 3700 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 3701 { 3702 struct rtw89_btc *btc = &rtwdev->btc; 3703 3704 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3705 3706 switch (btc->cx.state_map) { 3707 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 3708 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 3709 break; 3710 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 3711 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 3712 break; 3713 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 3714 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 3715 break; 3716 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 3717 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 3718 break; 3719 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 3720 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 3721 break; 3722 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 3723 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 3724 break; 3725 } 3726 } 3727 3728 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 3729 { 3730 struct rtw89_btc *btc = &rtwdev->btc; 3731 3732 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3733 3734 switch (btc->cx.state_map) { 3735 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 3736 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 3737 BTC_ACT_BT_A2DP_PAN_HID); 3738 break; 3739 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 3740 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 3741 BTC_ACT_BT_A2DP_PAN_HID); 3742 break; 3743 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 3744 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 3745 BTC_ACT_BT_A2DP_PAN_HID); 3746 break; 3747 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 3748 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 3749 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 3750 BTC_ACT_BT_A2DP_PAN_HID); 3751 break; 3752 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 3753 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 3754 BTC_ACT_BT_A2DP_PAN_HID); 3755 break; 3756 } 3757 } 3758 3759 static void _action_wl_5g(struct rtw89_dev *rtwdev) 3760 { 3761 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 3762 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 3763 } 3764 3765 static void _action_wl_other(struct rtw89_dev *rtwdev) 3766 { 3767 struct rtw89_btc *btc = &rtwdev->btc; 3768 3769 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3770 3771 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) 3772 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 3773 else 3774 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 3775 } 3776 3777 static void _action_wl_nc(struct rtw89_dev *rtwdev) 3778 { 3779 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3780 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 3781 } 3782 3783 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 3784 { 3785 struct rtw89_btc *btc = &rtwdev->btc; 3786 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 3787 3788 if (rfk.state != BTC_WRFK_START) 3789 return; 3790 3791 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 3792 __func__, rfk.band); 3793 3794 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 3795 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 3796 } 3797 3798 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 3799 { 3800 struct rtw89_btc *btc = &rtwdev->btc; 3801 const struct rtw89_btc_ver *ver = btc->ver; 3802 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3803 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3804 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3805 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 3806 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 3807 bool is_btg; 3808 u8 mode; 3809 3810 if (btc->ctrl.manual) 3811 return; 3812 3813 if (ver->fwlrole == 0) 3814 mode = wl_rinfo->link_mode; 3815 else if (ver->fwlrole == 1) 3816 mode = wl_rinfo_v1->link_mode; 3817 else if (ver->fwlrole == 2) 3818 mode = wl_rinfo_v2->link_mode; 3819 else 3820 return; 3821 3822 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */ 3823 if (mode == BTC_WLINK_5G) /* always 0 if 5G */ 3824 is_btg = false; 3825 else if (mode == BTC_WLINK_25G_DBCC && 3826 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 3827 is_btg = false; 3828 else 3829 is_btg = true; 3830 3831 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT && 3832 is_btg == btc->dm.wl_btg_rx) 3833 return; 3834 3835 btc->dm.wl_btg_rx = is_btg; 3836 3837 if (mode == BTC_WLINK_25G_MCC) 3838 return; 3839 3840 rtw89_ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0); 3841 } 3842 3843 struct rtw89_txtime_data { 3844 struct rtw89_dev *rtwdev; 3845 int type; 3846 u32 tx_time; 3847 u8 tx_retry; 3848 u16 enable; 3849 bool reenable; 3850 }; 3851 3852 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 3853 { 3854 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 3855 struct rtw89_txtime_data *iter_data = 3856 (struct rtw89_txtime_data *)data; 3857 struct rtw89_dev *rtwdev = iter_data->rtwdev; 3858 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 3859 struct rtw89_btc *btc = &rtwdev->btc; 3860 struct rtw89_btc_cx *cx = &btc->cx; 3861 struct rtw89_btc_wl_info *wl = &cx->wl; 3862 struct rtw89_btc_wl_link_info *plink = NULL; 3863 u8 port = rtwvif->port; 3864 u32 tx_time = iter_data->tx_time; 3865 u8 tx_retry = iter_data->tx_retry; 3866 u16 enable = iter_data->enable; 3867 bool reenable = iter_data->reenable; 3868 3869 plink = &wl->link_info[port]; 3870 3871 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3872 "[BTC], %s(): port = %d\n", __func__, port); 3873 3874 if (!plink->connected) { 3875 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3876 "[BTC], %s(): connected = %d\n", 3877 __func__, plink->connected); 3878 return; 3879 } 3880 3881 /* backup the original tx time before tx-limit on */ 3882 if (reenable) { 3883 rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); 3884 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); 3885 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3886 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 3887 __func__, plink->tx_time, plink->tx_retry); 3888 } 3889 3890 /* restore the original tx time if no tx-limit */ 3891 if (!enable) { 3892 rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); 3893 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, 3894 plink->tx_retry); 3895 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3896 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 3897 __func__, plink->tx_time, plink->tx_retry); 3898 3899 } else { 3900 rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); 3901 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); 3902 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3903 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 3904 __func__, tx_time, tx_retry); 3905 } 3906 } 3907 3908 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 3909 { 3910 struct rtw89_btc *btc = &rtwdev->btc; 3911 const struct rtw89_btc_ver *ver = btc->ver; 3912 struct rtw89_btc_cx *cx = &btc->cx; 3913 struct rtw89_btc_dm *dm = &btc->dm; 3914 struct rtw89_btc_wl_info *wl = &cx->wl; 3915 struct rtw89_btc_bt_info *bt = &cx->bt; 3916 struct rtw89_btc_bt_link_info *b = &bt->link_info; 3917 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 3918 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 3919 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3920 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3921 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 3922 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 3923 u8 mode; 3924 u8 tx_retry; 3925 u32 tx_time; 3926 u16 enable; 3927 bool reenable = false; 3928 3929 if (btc->ctrl.manual) 3930 return; 3931 3932 if (ver->fwlrole == 0) 3933 mode = wl_rinfo->link_mode; 3934 else if (ver->fwlrole == 1) 3935 mode = wl_rinfo_v1->link_mode; 3936 else if (ver->fwlrole == 2) 3937 mode = wl_rinfo_v2->link_mode; 3938 else 3939 return; 3940 3941 if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 || 3942 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) { 3943 enable = 0; 3944 tx_time = BTC_MAX_TX_TIME_DEF; 3945 tx_retry = BTC_MAX_TX_RETRY_DEF; 3946 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 3947 enable = 1; 3948 tx_time = BTC_MAX_TX_TIME_L2; 3949 tx_retry = BTC_MAX_TX_RETRY_L1; 3950 } else if (hfp->exist || hid->exist) { 3951 enable = 1; 3952 tx_time = BTC_MAX_TX_TIME_L3; 3953 tx_retry = BTC_MAX_TX_RETRY_L1; 3954 } else { 3955 enable = 0; 3956 tx_time = BTC_MAX_TX_TIME_DEF; 3957 tx_retry = BTC_MAX_TX_RETRY_DEF; 3958 } 3959 3960 if (dm->wl_tx_limit.enable == enable && 3961 dm->wl_tx_limit.tx_time == tx_time && 3962 dm->wl_tx_limit.tx_retry == tx_retry) 3963 return; 3964 3965 if (!dm->wl_tx_limit.enable && enable) 3966 reenable = true; 3967 3968 dm->wl_tx_limit.enable = enable; 3969 dm->wl_tx_limit.tx_time = tx_time; 3970 dm->wl_tx_limit.tx_retry = tx_retry; 3971 3972 data.enable = enable; 3973 data.tx_time = tx_time; 3974 data.tx_retry = tx_retry; 3975 data.reenable = reenable; 3976 3977 ieee80211_iterate_stations_atomic(rtwdev->hw, 3978 rtw89_tx_time_iter, 3979 &data); 3980 } 3981 3982 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 3983 { 3984 struct rtw89_btc *btc = &rtwdev->btc; 3985 const struct rtw89_btc_ver *ver = btc->ver; 3986 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3987 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3988 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3989 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 3990 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3991 bool bt_hi_lna_rx = false; 3992 u8 mode; 3993 3994 if (ver->fwlrole == 0) 3995 mode = wl_rinfo->link_mode; 3996 else if (ver->fwlrole == 1) 3997 mode = wl_rinfo_v1->link_mode; 3998 else if (ver->fwlrole == 2) 3999 mode = wl_rinfo_v2->link_mode; 4000 else 4001 return; 4002 4003 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 4004 bt_hi_lna_rx = true; 4005 4006 if (bt_hi_lna_rx == bt->hi_lna_rx) 4007 return; 4008 4009 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 4010 } 4011 4012 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 4013 { 4014 struct rtw89_btc *btc = &rtwdev->btc; 4015 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4016 4017 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri)); 4018 } 4019 4020 /* TODO add these functions */ 4021 static void _action_common(struct rtw89_dev *rtwdev) 4022 { 4023 struct rtw89_btc *btc = &rtwdev->btc; 4024 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4025 4026 _set_btg_ctrl(rtwdev); 4027 _set_wl_tx_limit(rtwdev); 4028 _set_bt_afh_info(rtwdev); 4029 _set_bt_rx_agc(rtwdev); 4030 _set_rf_trx_para(rtwdev); 4031 _set_bt_rx_scan_pri(rtwdev); 4032 4033 if (wl->scbd_change) { 4034 rtw89_mac_cfg_sb(rtwdev, wl->scbd); 4035 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n", 4036 wl->scbd); 4037 wl->scbd_change = false; 4038 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++; 4039 } 4040 btc->dm.tdma_instant_excute = 0; 4041 } 4042 4043 static void _action_by_bt(struct rtw89_dev *rtwdev) 4044 { 4045 struct rtw89_btc *btc = &rtwdev->btc; 4046 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4047 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 4048 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 4049 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 4050 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 4051 u8 profile_map = 0; 4052 4053 if (bt_linfo->hfp_desc.exist) 4054 profile_map |= BTC_BT_HFP; 4055 4056 if (bt_linfo->hid_desc.exist) 4057 profile_map |= BTC_BT_HID; 4058 4059 if (bt_linfo->a2dp_desc.exist) 4060 profile_map |= BTC_BT_A2DP; 4061 4062 if (bt_linfo->pan_desc.exist) 4063 profile_map |= BTC_BT_PAN; 4064 4065 switch (profile_map) { 4066 case BTC_BT_NOPROFILE: 4067 if (_check_freerun(rtwdev)) 4068 _action_freerun(rtwdev); 4069 else if (pan.active) 4070 _action_bt_pan(rtwdev); 4071 else 4072 _action_bt_idle(rtwdev); 4073 break; 4074 case BTC_BT_HFP: 4075 if (_check_freerun(rtwdev)) 4076 _action_freerun(rtwdev); 4077 else 4078 _action_bt_hfp(rtwdev); 4079 break; 4080 case BTC_BT_HFP | BTC_BT_HID: 4081 case BTC_BT_HID: 4082 if (_check_freerun(rtwdev)) 4083 _action_freerun(rtwdev); 4084 else 4085 _action_bt_hid(rtwdev); 4086 break; 4087 case BTC_BT_A2DP: 4088 if (_check_freerun(rtwdev)) 4089 _action_freerun(rtwdev); 4090 else if (a2dp.sink) 4091 _action_bt_a2dpsink(rtwdev); 4092 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 4093 _action_bt_a2dp_pan(rtwdev); 4094 else 4095 _action_bt_a2dp(rtwdev); 4096 break; 4097 case BTC_BT_PAN: 4098 _action_bt_pan(rtwdev); 4099 break; 4100 case BTC_BT_A2DP | BTC_BT_HFP: 4101 case BTC_BT_A2DP | BTC_BT_HID: 4102 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 4103 if (_check_freerun(rtwdev)) 4104 _action_freerun(rtwdev); 4105 else 4106 _action_bt_a2dp_hid(rtwdev); 4107 break; 4108 case BTC_BT_A2DP | BTC_BT_PAN: 4109 _action_bt_a2dp_pan(rtwdev); 4110 break; 4111 case BTC_BT_PAN | BTC_BT_HFP: 4112 case BTC_BT_PAN | BTC_BT_HID: 4113 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 4114 _action_bt_pan_hid(rtwdev); 4115 break; 4116 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 4117 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 4118 default: 4119 _action_bt_a2dp_pan_hid(rtwdev); 4120 break; 4121 } 4122 } 4123 4124 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 4125 { 4126 _action_by_bt(rtwdev); 4127 } 4128 4129 static void _action_wl_scan(struct rtw89_dev *rtwdev) 4130 { 4131 struct rtw89_btc *btc = &rtwdev->btc; 4132 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4133 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4134 4135 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { 4136 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 4137 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) 4138 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 4139 BTC_RSN_NTFY_SCAN_START); 4140 else 4141 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, 4142 BTC_RSN_NTFY_SCAN_START); 4143 4144 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 4145 } else if (rtwdev->dbcc_en) { 4146 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 4147 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 4148 _action_wl_5g(rtwdev); 4149 else 4150 _action_by_bt(rtwdev); 4151 } else { 4152 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 4153 _action_wl_5g(rtwdev); 4154 else 4155 _action_by_bt(rtwdev); 4156 } 4157 } 4158 4159 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 4160 { 4161 struct rtw89_btc *btc = &rtwdev->btc; 4162 4163 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 4164 4165 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 4166 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4167 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 4168 BTC_ACT_WL_25G_MCC); 4169 else 4170 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 4171 BTC_ACT_WL_25G_MCC); 4172 } else { /* dedicated-antenna */ 4173 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC); 4174 } 4175 } 4176 4177 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 4178 { struct rtw89_btc *btc = &rtwdev->btc; 4179 4180 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4181 4182 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 4183 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4184 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 4185 BTC_ACT_WL_2G_MCC); 4186 else 4187 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 4188 BTC_ACT_WL_2G_MCC); 4189 } else { /* dedicated-antenna */ 4190 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 4191 } 4192 } 4193 4194 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 4195 { 4196 struct rtw89_btc *btc = &rtwdev->btc; 4197 4198 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4199 4200 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 4201 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4202 _set_policy(rtwdev, 4203 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC); 4204 else 4205 _set_policy(rtwdev, 4206 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC); 4207 } else { /* dedicated-antenna */ 4208 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC); 4209 } 4210 } 4211 4212 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev) 4213 { 4214 struct rtw89_btc *btc = &rtwdev->btc; 4215 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4216 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4217 struct rtw89_btc_dm *dm = &btc->dm; 4218 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 4219 u16 policy_type = BTC_CXP_OFF_BT; 4220 u32 dur; 4221 4222 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) { 4223 policy_type = BTC_CXP_OFF_EQ0; 4224 } else { 4225 /* shared-antenna */ 4226 switch (wl_rinfo->mrole_type) { 4227 case BTC_WLMROLE_STA_GC: 4228 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4229 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 4230 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4231 _action_by_bt(rtwdev); 4232 return; 4233 case BTC_WLMROLE_STA_STA: 4234 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4235 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 4236 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4237 _action_by_bt(rtwdev); 4238 return; 4239 case BTC_WLMROLE_STA_GC_NOA: 4240 case BTC_WLMROLE_STA_GO: 4241 case BTC_WLMROLE_STA_GO_NOA: 4242 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4243 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 4244 dur = wl_rinfo->mrole_noa_duration; 4245 4246 if (wl->status.map._4way) { 4247 dm->wl_scc.ebt_null = 0; 4248 policy_type = BTC_CXP_OFFE_WL; 4249 } else if (bt->link_info.status.map.connect == 0) { 4250 dm->wl_scc.ebt_null = 0; 4251 policy_type = BTC_CXP_OFFE_2GISOB; 4252 } else if (bt->link_info.a2dp_desc.exist && 4253 dur < btc->bt_req_len) { 4254 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4255 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 4256 } else if (bt->link_info.a2dp_desc.exist || 4257 bt->link_info.pan_desc.exist) { 4258 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4259 policy_type = BTC_CXP_OFFE_2GBWISOB; 4260 } else { 4261 dm->wl_scc.ebt_null = 0; 4262 policy_type = BTC_CXP_OFFE_2GBWISOB; 4263 } 4264 break; 4265 default: 4266 break; 4267 } 4268 } 4269 4270 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4271 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 4272 } 4273 4274 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev) 4275 { 4276 struct rtw89_btc *btc = &rtwdev->btc; 4277 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4278 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4279 struct rtw89_btc_dm *dm = &btc->dm; 4280 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 4281 u16 policy_type = BTC_CXP_OFF_BT; 4282 u32 dur; 4283 4284 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) { 4285 policy_type = BTC_CXP_OFF_EQ0; 4286 } else { 4287 /* shared-antenna */ 4288 switch (wl_rinfo->mrole_type) { 4289 case BTC_WLMROLE_STA_GC: 4290 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4291 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 4292 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4293 _action_by_bt(rtwdev); 4294 return; 4295 case BTC_WLMROLE_STA_STA: 4296 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4297 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 4298 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 4299 _action_by_bt(rtwdev); 4300 return; 4301 case BTC_WLMROLE_STA_GC_NOA: 4302 case BTC_WLMROLE_STA_GO: 4303 case BTC_WLMROLE_STA_GO_NOA: 4304 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 4305 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 4306 dur = wl_rinfo->mrole_noa_duration; 4307 4308 if (wl->status.map._4way) { 4309 dm->wl_scc.ebt_null = 0; 4310 policy_type = BTC_CXP_OFFE_WL; 4311 } else if (bt->link_info.status.map.connect == 0) { 4312 dm->wl_scc.ebt_null = 0; 4313 policy_type = BTC_CXP_OFFE_2GISOB; 4314 } else if (bt->link_info.a2dp_desc.exist && 4315 dur < btc->bt_req_len) { 4316 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4317 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 4318 } else if (bt->link_info.a2dp_desc.exist || 4319 bt->link_info.pan_desc.exist) { 4320 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 4321 policy_type = BTC_CXP_OFFE_2GBWISOB; 4322 } else { 4323 dm->wl_scc.ebt_null = 0; 4324 policy_type = BTC_CXP_OFFE_2GBWISOB; 4325 } 4326 break; 4327 default: 4328 break; 4329 } 4330 } 4331 4332 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4333 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 4334 } 4335 4336 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 4337 { 4338 struct rtw89_btc *btc = &rtwdev->btc; 4339 4340 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4341 4342 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 4343 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4344 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 4345 BTC_ACT_WL_2G_AP); 4346 else 4347 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 4348 } else {/* dedicated-antenna */ 4349 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 4350 } 4351 } 4352 4353 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 4354 { 4355 struct rtw89_btc *btc = &rtwdev->btc; 4356 4357 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4358 4359 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 4360 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4361 _set_policy(rtwdev, 4362 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 4363 else 4364 _set_policy(rtwdev, 4365 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 4366 } else { /* dedicated-antenna */ 4367 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 4368 } 4369 } 4370 4371 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 4372 { 4373 struct rtw89_btc *btc = &rtwdev->btc; 4374 4375 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4376 4377 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 4378 _action_by_bt(rtwdev); 4379 } else {/* dedicated-antenna */ 4380 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 4381 } 4382 } 4383 4384 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 4385 { 4386 struct rtw89_btc *btc = &rtwdev->btc; 4387 4388 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4389 4390 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 4391 if (btc->cx.bt.link_info.profile_cnt.now == 0) 4392 _set_policy(rtwdev, 4393 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 4394 else 4395 _set_policy(rtwdev, 4396 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 4397 } else { /* dedicated-antenna */ 4398 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 4399 } 4400 } 4401 4402 static u32 _read_scbd(struct rtw89_dev *rtwdev) 4403 { 4404 const struct rtw89_chip_info *chip = rtwdev->chip; 4405 struct rtw89_btc *btc = &rtwdev->btc; 4406 u32 scbd_val = 0; 4407 4408 if (!chip->scbd) 4409 return 0; 4410 4411 scbd_val = rtw89_mac_get_sb(rtwdev); 4412 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n", 4413 scbd_val); 4414 4415 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++; 4416 return scbd_val; 4417 } 4418 4419 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state) 4420 { 4421 const struct rtw89_chip_info *chip = rtwdev->chip; 4422 struct rtw89_btc *btc = &rtwdev->btc; 4423 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4424 u32 scbd_val = 0; 4425 u8 force_exec = false; 4426 4427 if (!chip->scbd) 4428 return; 4429 4430 scbd_val = state ? wl->scbd | val : wl->scbd & ~val; 4431 4432 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON) 4433 force_exec = true; 4434 4435 if (scbd_val != wl->scbd || force_exec) { 4436 wl->scbd = scbd_val; 4437 wl->scbd_change = true; 4438 } 4439 } 4440 4441 static u8 4442 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 4443 { 4444 const struct rtw89_chip_info *chip = rtwdev->chip; 4445 u8 next_state, tol = chip->rssi_tol; 4446 4447 if (pre_state == BTC_RSSI_ST_LOW || 4448 pre_state == BTC_RSSI_ST_STAY_LOW) { 4449 if (rssi >= (thresh + tol)) 4450 next_state = BTC_RSSI_ST_HIGH; 4451 else 4452 next_state = BTC_RSSI_ST_STAY_LOW; 4453 } else { 4454 if (rssi < thresh) 4455 next_state = BTC_RSSI_ST_LOW; 4456 else 4457 next_state = BTC_RSSI_ST_STAY_HIGH; 4458 } 4459 4460 return next_state; 4461 } 4462 4463 static 4464 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 4465 { 4466 struct rtw89_btc *btc = &rtwdev->btc; 4467 4468 btc->cx.wl.dbcc_info.real_band[phy_idx] = 4469 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 4470 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 4471 btc->cx.wl.dbcc_info.op_band[phy_idx]; 4472 } 4473 4474 static void _update_wl_info(struct rtw89_dev *rtwdev) 4475 { 4476 struct rtw89_btc *btc = &rtwdev->btc; 4477 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4478 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4479 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4480 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4481 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4482 u8 cnt_2g = 0, cnt_5g = 0, phy; 4483 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0}; 4484 bool b2g = false, b5g = false, client_joined = false; 4485 4486 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4487 4488 for (i = 0; i < RTW89_PORT_NUM; i++) { 4489 /* check if role active? */ 4490 if (!wl_linfo[i].active) 4491 continue; 4492 4493 cnt_active++; 4494 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role; 4495 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid; 4496 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy; 4497 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band; 4498 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4499 wl_rinfo->active_role[cnt_active - 1].connected = 0; 4500 4501 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4502 4503 phy = wl_linfo[i].phy; 4504 4505 /* check dbcc role */ 4506 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4507 wl_dinfo->role[phy] = wl_linfo[i].role; 4508 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4509 _update_dbcc_band(rtwdev, phy); 4510 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4511 } 4512 4513 if (wl_linfo[i].connected == MLME_NO_LINK) { 4514 continue; 4515 } else if (wl_linfo[i].connected == MLME_LINKING) { 4516 cnt_connecting++; 4517 } else { 4518 cnt_connect++; 4519 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4520 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4521 wl_linfo[i].client_cnt > 1) 4522 client_joined = true; 4523 } 4524 4525 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4526 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch; 4527 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw; 4528 wl_rinfo->active_role[cnt_active - 1].connected = 1; 4529 4530 /* only care 2 roles + BT coex */ 4531 if (wl_linfo[i].band != RTW89_BAND_2G) { 4532 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4533 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4534 cnt_5g++; 4535 b5g = true; 4536 } else { 4537 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4538 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4539 cnt_2g++; 4540 b2g = true; 4541 } 4542 } 4543 4544 wl_rinfo->connect_cnt = cnt_connect; 4545 4546 /* Be careful to change the following sequence!! */ 4547 if (cnt_connect == 0) { 4548 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4549 wl_rinfo->role_map.role.none = 1; 4550 } else if (!b2g && b5g) { 4551 wl_rinfo->link_mode = BTC_WLINK_5G; 4552 } else if (wl_rinfo->role_map.role.nan) { 4553 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4554 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4555 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4556 } else if (b2g && b5g && cnt_connect == 2) { 4557 if (rtwdev->dbcc_en) { 4558 switch (wl_dinfo->role[RTW89_PHY_0]) { 4559 case RTW89_WIFI_ROLE_STATION: 4560 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4561 break; 4562 case RTW89_WIFI_ROLE_P2P_GO: 4563 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4564 break; 4565 case RTW89_WIFI_ROLE_P2P_CLIENT: 4566 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4567 break; 4568 case RTW89_WIFI_ROLE_AP: 4569 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4570 break; 4571 default: 4572 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4573 break; 4574 } 4575 } else { 4576 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4577 } 4578 } else if (!b5g && cnt_connect == 2) { 4579 if (wl_rinfo->role_map.role.station && 4580 (wl_rinfo->role_map.role.p2p_go || 4581 wl_rinfo->role_map.role.p2p_gc || 4582 wl_rinfo->role_map.role.ap)) { 4583 if (wl_2g_ch[0] == wl_2g_ch[1]) 4584 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4585 else 4586 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4587 } else { 4588 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4589 } 4590 } else if (!b5g && cnt_connect == 1) { 4591 if (wl_rinfo->role_map.role.station) 4592 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4593 else if (wl_rinfo->role_map.role.ap) 4594 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4595 else if (wl_rinfo->role_map.role.p2p_go) 4596 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4597 else if (wl_rinfo->role_map.role.p2p_gc) 4598 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4599 else 4600 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4601 } 4602 4603 /* if no client_joined, don't care P2P-GO/AP role */ 4604 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4605 if (!client_joined) { 4606 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4607 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4608 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4609 wl_rinfo->connect_cnt = 1; 4610 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4611 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4612 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4613 wl_rinfo->connect_cnt = 0; 4614 } 4615 } 4616 } 4617 4618 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4619 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4620 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4621 4622 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4623 } 4624 4625 static void _update_wl_info_v1(struct rtw89_dev *rtwdev) 4626 { 4627 struct rtw89_btc *btc = &rtwdev->btc; 4628 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4629 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4630 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 4631 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4632 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4633 u8 cnt_2g = 0, cnt_5g = 0, phy; 4634 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 4635 bool b2g = false, b5g = false, client_joined = false; 4636 u8 i; 4637 4638 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4639 4640 for (i = 0; i < RTW89_PORT_NUM; i++) { 4641 if (!wl_linfo[i].active) 4642 continue; 4643 4644 cnt_active++; 4645 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role; 4646 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid; 4647 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy; 4648 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band; 4649 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4650 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0; 4651 4652 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4653 4654 phy = wl_linfo[i].phy; 4655 4656 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4657 wl_dinfo->role[phy] = wl_linfo[i].role; 4658 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4659 _update_dbcc_band(rtwdev, phy); 4660 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4661 } 4662 4663 if (wl_linfo[i].connected == MLME_NO_LINK) { 4664 continue; 4665 } else if (wl_linfo[i].connected == MLME_LINKING) { 4666 cnt_connecting++; 4667 } else { 4668 cnt_connect++; 4669 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4670 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4671 wl_linfo[i].client_cnt > 1) 4672 client_joined = true; 4673 } 4674 4675 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4676 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch; 4677 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw; 4678 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1; 4679 4680 /* only care 2 roles + BT coex */ 4681 if (wl_linfo[i].band != RTW89_BAND_2G) { 4682 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4683 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4684 cnt_5g++; 4685 b5g = true; 4686 } else { 4687 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4688 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4689 cnt_2g++; 4690 b2g = true; 4691 } 4692 } 4693 4694 wl_rinfo->connect_cnt = cnt_connect; 4695 4696 /* Be careful to change the following sequence!! */ 4697 if (cnt_connect == 0) { 4698 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4699 wl_rinfo->role_map.role.none = 1; 4700 } else if (!b2g && b5g) { 4701 wl_rinfo->link_mode = BTC_WLINK_5G; 4702 } else if (wl_rinfo->role_map.role.nan) { 4703 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4704 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4705 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4706 } else if (b2g && b5g && cnt_connect == 2) { 4707 if (rtwdev->dbcc_en) { 4708 switch (wl_dinfo->role[RTW89_PHY_0]) { 4709 case RTW89_WIFI_ROLE_STATION: 4710 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4711 break; 4712 case RTW89_WIFI_ROLE_P2P_GO: 4713 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4714 break; 4715 case RTW89_WIFI_ROLE_P2P_CLIENT: 4716 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4717 break; 4718 case RTW89_WIFI_ROLE_AP: 4719 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4720 break; 4721 default: 4722 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4723 break; 4724 } 4725 } else { 4726 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4727 } 4728 } else if (!b5g && cnt_connect == 2) { 4729 if (wl_rinfo->role_map.role.station && 4730 (wl_rinfo->role_map.role.p2p_go || 4731 wl_rinfo->role_map.role.p2p_gc || 4732 wl_rinfo->role_map.role.ap)) { 4733 if (wl_2g_ch[0] == wl_2g_ch[1]) 4734 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4735 else 4736 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4737 } else { 4738 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4739 } 4740 } else if (!b5g && cnt_connect == 1) { 4741 if (wl_rinfo->role_map.role.station) 4742 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4743 else if (wl_rinfo->role_map.role.ap) 4744 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4745 else if (wl_rinfo->role_map.role.p2p_go) 4746 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4747 else if (wl_rinfo->role_map.role.p2p_gc) 4748 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4749 else 4750 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4751 } 4752 4753 /* if no client_joined, don't care P2P-GO/AP role */ 4754 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4755 if (!client_joined) { 4756 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4757 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4758 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4759 wl_rinfo->connect_cnt = 1; 4760 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4761 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4762 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4763 wl_rinfo->connect_cnt = 0; 4764 } 4765 } 4766 } 4767 4768 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4769 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4770 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4771 4772 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4773 } 4774 4775 static void _update_wl_info_v2(struct rtw89_dev *rtwdev) 4776 { 4777 struct rtw89_btc *btc = &rtwdev->btc; 4778 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4779 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4780 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 4781 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4782 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4783 u8 cnt_2g = 0, cnt_5g = 0, phy; 4784 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 4785 bool b2g = false, b5g = false, client_joined = false; 4786 u8 i; 4787 4788 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4789 4790 for (i = 0; i < RTW89_PORT_NUM; i++) { 4791 if (!wl_linfo[i].active) 4792 continue; 4793 4794 cnt_active++; 4795 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role; 4796 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid; 4797 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy; 4798 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band; 4799 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4800 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0; 4801 4802 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4803 4804 phy = wl_linfo[i].phy; 4805 4806 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4807 wl_dinfo->role[phy] = wl_linfo[i].role; 4808 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4809 _update_dbcc_band(rtwdev, phy); 4810 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4811 } 4812 4813 if (wl_linfo[i].connected == MLME_NO_LINK) { 4814 continue; 4815 } else if (wl_linfo[i].connected == MLME_LINKING) { 4816 cnt_connecting++; 4817 } else { 4818 cnt_connect++; 4819 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4820 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4821 wl_linfo[i].client_cnt > 1) 4822 client_joined = true; 4823 } 4824 4825 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4826 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch; 4827 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw; 4828 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1; 4829 4830 /* only care 2 roles + BT coex */ 4831 if (wl_linfo[i].band != RTW89_BAND_2G) { 4832 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4833 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4834 cnt_5g++; 4835 b5g = true; 4836 } else { 4837 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4838 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4839 cnt_2g++; 4840 b2g = true; 4841 } 4842 } 4843 4844 wl_rinfo->connect_cnt = cnt_connect; 4845 4846 /* Be careful to change the following sequence!! */ 4847 if (cnt_connect == 0) { 4848 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4849 wl_rinfo->role_map.role.none = 1; 4850 } else if (!b2g && b5g) { 4851 wl_rinfo->link_mode = BTC_WLINK_5G; 4852 } else if (wl_rinfo->role_map.role.nan) { 4853 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4854 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4855 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4856 } else if (b2g && b5g && cnt_connect == 2) { 4857 if (rtwdev->dbcc_en) { 4858 switch (wl_dinfo->role[RTW89_PHY_0]) { 4859 case RTW89_WIFI_ROLE_STATION: 4860 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4861 break; 4862 case RTW89_WIFI_ROLE_P2P_GO: 4863 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4864 break; 4865 case RTW89_WIFI_ROLE_P2P_CLIENT: 4866 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4867 break; 4868 case RTW89_WIFI_ROLE_AP: 4869 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4870 break; 4871 default: 4872 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4873 break; 4874 } 4875 } else { 4876 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4877 } 4878 } else if (!b5g && cnt_connect == 2) { 4879 if (wl_rinfo->role_map.role.station && 4880 (wl_rinfo->role_map.role.p2p_go || 4881 wl_rinfo->role_map.role.p2p_gc || 4882 wl_rinfo->role_map.role.ap)) { 4883 if (wl_2g_ch[0] == wl_2g_ch[1]) 4884 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4885 else 4886 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4887 } else { 4888 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4889 } 4890 } else if (!b5g && cnt_connect == 1) { 4891 if (wl_rinfo->role_map.role.station) 4892 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4893 else if (wl_rinfo->role_map.role.ap) 4894 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4895 else if (wl_rinfo->role_map.role.p2p_go) 4896 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4897 else if (wl_rinfo->role_map.role.p2p_gc) 4898 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4899 else 4900 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4901 } 4902 4903 /* if no client_joined, don't care P2P-GO/AP role */ 4904 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4905 if (!client_joined) { 4906 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4907 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4908 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4909 wl_rinfo->connect_cnt = 1; 4910 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4911 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4912 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4913 wl_rinfo->connect_cnt = 0; 4914 } 4915 } 4916 } 4917 4918 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4919 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4920 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4921 4922 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4923 } 4924 4925 #define BTC_CHK_HANG_MAX 3 4926 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 4927 4928 void rtw89_coex_act1_work(struct work_struct *work) 4929 { 4930 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4931 coex_act1_work.work); 4932 struct rtw89_btc *btc = &rtwdev->btc; 4933 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4934 struct rtw89_btc_cx *cx = &btc->cx; 4935 struct rtw89_btc_wl_info *wl = &cx->wl; 4936 4937 mutex_lock(&rtwdev->mutex); 4938 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4939 dm->cnt_notify[BTC_NCNT_TIMER]++; 4940 if (wl->status.map._4way) 4941 wl->status.map._4way = false; 4942 if (wl->status.map.connecting) 4943 wl->status.map.connecting = false; 4944 4945 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 4946 mutex_unlock(&rtwdev->mutex); 4947 } 4948 4949 void rtw89_coex_bt_devinfo_work(struct work_struct *work) 4950 { 4951 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4952 coex_bt_devinfo_work.work); 4953 struct rtw89_btc *btc = &rtwdev->btc; 4954 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4955 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 4956 4957 mutex_lock(&rtwdev->mutex); 4958 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4959 dm->cnt_notify[BTC_NCNT_TIMER]++; 4960 a2dp->play_latency = 0; 4961 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 4962 mutex_unlock(&rtwdev->mutex); 4963 } 4964 4965 void rtw89_coex_rfk_chk_work(struct work_struct *work) 4966 { 4967 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4968 coex_rfk_chk_work.work); 4969 struct rtw89_btc *btc = &rtwdev->btc; 4970 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4971 struct rtw89_btc_cx *cx = &btc->cx; 4972 struct rtw89_btc_wl_info *wl = &cx->wl; 4973 4974 mutex_lock(&rtwdev->mutex); 4975 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4976 dm->cnt_notify[BTC_NCNT_TIMER]++; 4977 if (wl->rfk_info.state != BTC_WRFK_STOP) { 4978 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4979 "[BTC], %s(): RFK timeout\n", __func__); 4980 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++; 4981 dm->error.map.wl_rfk_timeout = true; 4982 wl->rfk_info.state = BTC_WRFK_STOP; 4983 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 4984 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 4985 } 4986 mutex_unlock(&rtwdev->mutex); 4987 } 4988 4989 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) 4990 { 4991 const struct rtw89_chip_info *chip = rtwdev->chip; 4992 struct rtw89_btc *btc = &rtwdev->btc; 4993 struct rtw89_btc_cx *cx = &btc->cx; 4994 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4995 u32 val; 4996 bool status_change = false; 4997 4998 if (!chip->scbd) 4999 return; 5000 5001 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 5002 5003 val = _read_scbd(rtwdev); 5004 if (val == BTC_SCB_INV_VALUE) { 5005 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5006 "[BTC], %s(): return by invalid scbd value\n", 5007 __func__); 5008 return; 5009 } 5010 5011 if (!(val & BTC_BSCB_ON) || 5012 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX) 5013 bt->enable.now = 0; 5014 else 5015 bt->enable.now = 1; 5016 5017 if (bt->enable.now != bt->enable.last) 5018 status_change = true; 5019 5020 /* reset bt info if bt re-enable */ 5021 if (bt->enable.now && !bt->enable.last) { 5022 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 5023 cx->cnt_bt[BTC_BCNT_REENABLE]++; 5024 bt->enable.now = 1; 5025 } 5026 5027 bt->enable.last = bt->enable.now; 5028 bt->scbd = val; 5029 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 5030 5031 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 5032 status_change = true; 5033 5034 bt->whql_test = !!(val & BTC_BSCB_WHQL); 5035 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE; 5036 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT); 5037 5038 /* if rfk run 1->0 */ 5039 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN)) 5040 status_change = true; 5041 5042 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN); 5043 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); 5044 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 5045 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); 5046 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 5047 5048 if (!only_update && status_change) 5049 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 5050 } 5051 5052 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) 5053 { 5054 struct rtw89_btc *btc = &rtwdev->btc; 5055 struct rtw89_btc_cx *cx = &btc->cx; 5056 struct rtw89_btc_bt_info *bt = &cx->bt; 5057 5058 _update_bt_scbd(rtwdev, true); 5059 5060 cx->cnt_wl[BTC_WCNT_RFK_REQ]++; 5061 5062 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) && 5063 !bt->rfk_info.map.timeout) { 5064 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++; 5065 } else { 5066 cx->cnt_wl[BTC_WCNT_RFK_GO]++; 5067 return true; 5068 } 5069 return false; 5070 } 5071 5072 static 5073 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 5074 { 5075 struct rtw89_btc *btc = &rtwdev->btc; 5076 const struct rtw89_btc_ver *ver = btc->ver; 5077 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5078 struct rtw89_btc_cx *cx = &btc->cx; 5079 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5080 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5081 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5082 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5083 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5084 u8 mode; 5085 5086 lockdep_assert_held(&rtwdev->mutex); 5087 5088 dm->run_reason = reason; 5089 _update_dm_step(rtwdev, reason); 5090 _update_btc_state_map(rtwdev); 5091 5092 if (ver->fwlrole == 0) 5093 mode = wl_rinfo->link_mode; 5094 else if (ver->fwlrole == 1) 5095 mode = wl_rinfo_v1->link_mode; 5096 else if (ver->fwlrole == 2) 5097 mode = wl_rinfo_v2->link_mode; 5098 else 5099 return; 5100 5101 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 5102 __func__, reason, mode); 5103 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 5104 __func__, dm->wl_only, dm->bt_only); 5105 5106 /* Be careful to change the following function sequence!! */ 5107 if (btc->ctrl.manual) { 5108 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5109 "[BTC], %s(): return for Manual CTRL!!\n", 5110 __func__); 5111 return; 5112 } 5113 5114 if (btc->ctrl.igno_bt && 5115 (reason == BTC_RSN_UPDATE_BT_INFO || 5116 reason == BTC_RSN_UPDATE_BT_SCBD)) { 5117 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5118 "[BTC], %s(): return for Stop Coex DM!!\n", 5119 __func__); 5120 return; 5121 } 5122 5123 if (!wl->status.map.init_ok) { 5124 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5125 "[BTC], %s(): return for WL init fail!!\n", 5126 __func__); 5127 return; 5128 } 5129 5130 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 5131 wl->status.map.lps_pre == wl->status.map.lps && 5132 (reason == BTC_RSN_NTFY_POWEROFF || 5133 reason == BTC_RSN_NTFY_RADIO_STATE)) { 5134 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5135 "[BTC], %s(): return for WL rf off state no change!!\n", 5136 __func__); 5137 return; 5138 } 5139 5140 dm->cnt_dm[BTC_DCNT_RUN]++; 5141 dm->fddt_train = BTC_FDDT_DISABLE; 5142 5143 if (btc->ctrl.always_freerun) { 5144 _action_freerun(rtwdev); 5145 btc->ctrl.igno_bt = true; 5146 goto exit; 5147 } 5148 5149 if (dm->wl_only) { 5150 _action_wl_only(rtwdev); 5151 btc->ctrl.igno_bt = true; 5152 goto exit; 5153 } 5154 5155 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) { 5156 _action_wl_off(rtwdev); 5157 btc->ctrl.igno_bt = true; 5158 goto exit; 5159 } 5160 5161 btc->ctrl.igno_bt = false; 5162 dm->freerun = false; 5163 bt->scan_rx_low_pri = false; 5164 5165 if (reason == BTC_RSN_NTFY_INIT) { 5166 _action_wl_init(rtwdev); 5167 goto exit; 5168 } 5169 5170 if (!cx->bt.enable.now && !cx->other.type) { 5171 _action_bt_off(rtwdev); 5172 goto exit; 5173 } 5174 5175 if (cx->bt.whql_test) { 5176 _action_bt_whql(rtwdev); 5177 goto exit; 5178 } 5179 5180 if (wl->rfk_info.state != BTC_WRFK_STOP) { 5181 _action_wl_rfk(rtwdev); 5182 goto exit; 5183 } 5184 5185 if (cx->state_map == BTC_WLINKING) { 5186 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || 5187 mode == BTC_WLINK_5G) { 5188 _action_wl_scan(rtwdev); 5189 goto exit; 5190 } 5191 } 5192 5193 if (wl->status.map.scan) { 5194 _action_wl_scan(rtwdev); 5195 goto exit; 5196 } 5197 5198 switch (mode) { 5199 case BTC_WLINK_NOLINK: 5200 _action_wl_nc(rtwdev); 5201 break; 5202 case BTC_WLINK_2G_STA: 5203 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 5204 bt->scan_rx_low_pri = true; 5205 _action_wl_2g_sta(rtwdev); 5206 break; 5207 case BTC_WLINK_2G_AP: 5208 bt->scan_rx_low_pri = true; 5209 _action_wl_2g_ap(rtwdev); 5210 break; 5211 case BTC_WLINK_2G_GO: 5212 bt->scan_rx_low_pri = true; 5213 _action_wl_2g_go(rtwdev); 5214 break; 5215 case BTC_WLINK_2G_GC: 5216 bt->scan_rx_low_pri = true; 5217 _action_wl_2g_gc(rtwdev); 5218 break; 5219 case BTC_WLINK_2G_SCC: 5220 bt->scan_rx_low_pri = true; 5221 if (ver->fwlrole == 0) 5222 _action_wl_2g_scc(rtwdev); 5223 else if (ver->fwlrole == 1) 5224 _action_wl_2g_scc_v1(rtwdev); 5225 else if (ver->fwlrole == 2) 5226 _action_wl_2g_scc_v2(rtwdev); 5227 break; 5228 case BTC_WLINK_2G_MCC: 5229 bt->scan_rx_low_pri = true; 5230 _action_wl_2g_mcc(rtwdev); 5231 break; 5232 case BTC_WLINK_25G_MCC: 5233 bt->scan_rx_low_pri = true; 5234 _action_wl_25g_mcc(rtwdev); 5235 break; 5236 case BTC_WLINK_5G: 5237 _action_wl_5g(rtwdev); 5238 break; 5239 case BTC_WLINK_2G_NAN: 5240 _action_wl_2g_nan(rtwdev); 5241 break; 5242 default: 5243 _action_wl_other(rtwdev); 5244 break; 5245 } 5246 5247 exit: 5248 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 5249 _action_common(rtwdev); 5250 } 5251 5252 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 5253 { 5254 struct rtw89_btc *btc = &rtwdev->btc; 5255 5256 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5257 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 5258 } 5259 5260 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 5261 { 5262 struct rtw89_btc *btc = &rtwdev->btc; 5263 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5264 5265 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 5266 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 5267 5268 btc->cx.wl.status.map.rf_off = 1; 5269 btc->cx.wl.status.map.busy = 0; 5270 wl->status.map.lps = BTC_LPS_OFF; 5271 5272 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 5273 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 5274 5275 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 5276 5277 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 5278 } 5279 5280 static void _set_init_info(struct rtw89_dev *rtwdev) 5281 { 5282 const struct rtw89_chip_info *chip = rtwdev->chip; 5283 struct rtw89_btc *btc = &rtwdev->btc; 5284 struct rtw89_btc_dm *dm = &btc->dm; 5285 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5286 5287 dm->init_info.wl_only = (u8)dm->wl_only; 5288 dm->init_info.bt_only = (u8)dm->bt_only; 5289 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok; 5290 dm->init_info.dbcc_en = rtwdev->dbcc_en; 5291 dm->init_info.cx_other = btc->cx.other.type; 5292 dm->init_info.wl_guard_ch = chip->afh_guard_ch; 5293 dm->init_info.module = btc->mdinfo; 5294 } 5295 5296 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 5297 { 5298 struct rtw89_btc *btc = &rtwdev->btc; 5299 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 5300 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5301 const struct rtw89_chip_info *chip = rtwdev->chip; 5302 5303 _reset_btc_var(rtwdev, BTC_RESET_ALL); 5304 btc->dm.run_reason = BTC_RSN_NONE; 5305 btc->dm.run_action = BTC_ACT_NONE; 5306 btc->ctrl.igno_bt = true; 5307 5308 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5309 "[BTC], %s(): mode=%d\n", __func__, mode); 5310 5311 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 5312 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 5313 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 5314 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 5315 5316 chip->ops->btc_set_rfe(rtwdev); 5317 chip->ops->btc_init_cfg(rtwdev); 5318 5319 if (!wl->status.map.init_ok) { 5320 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5321 "[BTC], %s(): return for WL init fail!!\n", 5322 __func__); 5323 dm->error.map.init = true; 5324 return; 5325 } 5326 5327 _write_scbd(rtwdev, 5328 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 5329 _update_bt_scbd(rtwdev, true); 5330 if (rtw89_mac_get_ctrl_path(rtwdev)) { 5331 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5332 "[BTC], %s(): PTA owner warning!!\n", 5333 __func__); 5334 dm->error.map.pta_owner = true; 5335 } 5336 5337 _set_init_info(rtwdev); 5338 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR); 5339 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot); 5340 btc_fw_set_monreg(rtwdev); 5341 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 5342 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 5343 5344 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 5345 } 5346 5347 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 5348 { 5349 struct rtw89_btc *btc = &rtwdev->btc; 5350 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5351 5352 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5353 "[BTC], %s(): phy_idx=%d, band=%d\n", 5354 __func__, phy_idx, band); 5355 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 5356 wl->status.map.scan = true; 5357 wl->scan_info.band[phy_idx] = band; 5358 wl->scan_info.phy_map |= BIT(phy_idx); 5359 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 5360 5361 if (rtwdev->dbcc_en) { 5362 wl->dbcc_info.scan_band[phy_idx] = band; 5363 _update_dbcc_band(rtwdev, phy_idx); 5364 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5365 } 5366 5367 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 5368 } 5369 5370 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 5371 { 5372 struct rtw89_btc *btc = &rtwdev->btc; 5373 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5374 5375 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5376 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 5377 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 5378 5379 wl->status.map.scan = false; 5380 wl->scan_info.phy_map &= ~BIT(phy_idx); 5381 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 5382 5383 if (rtwdev->dbcc_en) { 5384 _update_dbcc_band(rtwdev, phy_idx); 5385 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5386 } 5387 5388 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 5389 } 5390 5391 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 5392 { 5393 struct rtw89_btc *btc = &rtwdev->btc; 5394 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5395 5396 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5397 "[BTC], %s(): phy_idx=%d, band=%d\n", 5398 __func__, phy_idx, band); 5399 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 5400 5401 wl->scan_info.band[phy_idx] = band; 5402 wl->scan_info.phy_map |= BIT(phy_idx); 5403 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 5404 5405 if (rtwdev->dbcc_en) { 5406 wl->dbcc_info.scan_band[phy_idx] = band; 5407 _update_dbcc_band(rtwdev, phy_idx); 5408 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 5409 } 5410 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 5411 } 5412 5413 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 5414 enum btc_pkt_type pkt_type) 5415 { 5416 struct rtw89_btc *btc = &rtwdev->btc; 5417 struct rtw89_btc_cx *cx = &btc->cx; 5418 struct rtw89_btc_wl_info *wl = &cx->wl; 5419 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info; 5420 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 5421 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 5422 u32 cnt; 5423 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 5424 bool delay_work = false; 5425 5426 switch (pkt_type) { 5427 case PACKET_DHCP: 5428 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP]; 5429 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5430 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 5431 wl->status.map.connecting = true; 5432 delay_work = true; 5433 break; 5434 case PACKET_EAPOL: 5435 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 5436 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5437 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 5438 wl->status.map._4way = true; 5439 delay_work = true; 5440 if (hfp->exist || hid->exist) 5441 delay /= 2; 5442 break; 5443 case PACKET_EAPOL_END: 5444 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 5445 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5446 "[BTC], %s(): EAPOL_End cnt=%d\n", 5447 __func__, cnt); 5448 wl->status.map._4way = false; 5449 cancel_delayed_work(&rtwdev->coex_act1_work); 5450 break; 5451 case PACKET_ARP: 5452 cnt = ++cx->cnt_wl[BTC_WCNT_ARP]; 5453 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5454 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 5455 return; 5456 case PACKET_ICMP: 5457 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5458 "[BTC], %s(): ICMP pkt\n", __func__); 5459 return; 5460 default: 5461 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5462 "[BTC], %s(): unknown packet type %d\n", 5463 __func__, pkt_type); 5464 return; 5465 } 5466 5467 if (delay_work) { 5468 cancel_delayed_work(&rtwdev->coex_act1_work); 5469 ieee80211_queue_delayed_work(rtwdev->hw, 5470 &rtwdev->coex_act1_work, delay); 5471 } 5472 5473 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 5474 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 5475 } 5476 5477 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work) 5478 { 5479 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5480 btc.eapol_notify_work); 5481 5482 mutex_lock(&rtwdev->mutex); 5483 rtw89_leave_ps_mode(rtwdev); 5484 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 5485 mutex_unlock(&rtwdev->mutex); 5486 } 5487 5488 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work) 5489 { 5490 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5491 btc.arp_notify_work); 5492 5493 mutex_lock(&rtwdev->mutex); 5494 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 5495 mutex_unlock(&rtwdev->mutex); 5496 } 5497 5498 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work) 5499 { 5500 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5501 btc.dhcp_notify_work); 5502 5503 mutex_lock(&rtwdev->mutex); 5504 rtw89_leave_ps_mode(rtwdev); 5505 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 5506 mutex_unlock(&rtwdev->mutex); 5507 } 5508 5509 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work) 5510 { 5511 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 5512 btc.icmp_notify_work); 5513 5514 mutex_lock(&rtwdev->mutex); 5515 rtw89_leave_ps_mode(rtwdev); 5516 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 5517 mutex_unlock(&rtwdev->mutex); 5518 } 5519 5520 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4) 5521 5522 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 5523 { 5524 const struct rtw89_chip_info *chip = rtwdev->chip; 5525 struct rtw89_btc *btc = &rtwdev->btc; 5526 struct rtw89_btc_cx *cx = &btc->cx; 5527 struct rtw89_btc_bt_info *bt = &cx->bt; 5528 struct rtw89_btc_bt_link_info *b = &bt->link_info; 5529 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 5530 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 5531 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 5532 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 5533 union btc_btinfo btinfo; 5534 5535 if (buf[BTC_BTINFO_L1] != 6) 5536 return; 5537 5538 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) { 5539 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5540 "[BTC], %s(): return by bt-info duplicate!!\n", 5541 __func__); 5542 cx->cnt_bt[BTC_BCNT_INFOSAME]++; 5543 return; 5544 } 5545 5546 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX); 5547 5548 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5549 "[BTC], %s(): bt_info[2]=0x%02x\n", 5550 __func__, bt->raw_info[2]); 5551 5552 /* reset to mo-connect before update */ 5553 b->status.val = BTC_BLINK_NOCONNECT; 5554 b->profile_cnt.last = b->profile_cnt.now; 5555 b->relink.last = b->relink.now; 5556 a2dp->exist_last = a2dp->exist; 5557 b->multi_link.last = b->multi_link.now; 5558 bt->inq_pag.last = bt->inq_pag.now; 5559 b->profile_cnt.now = 0; 5560 hid->type = 0; 5561 5562 /* parse raw info low-Byte2 */ 5563 btinfo.val = bt->raw_info[BTC_BTINFO_L2]; 5564 b->status.map.connect = btinfo.lb2.connect; 5565 b->status.map.sco_busy = btinfo.lb2.sco_busy; 5566 b->status.map.acl_busy = btinfo.lb2.acl_busy; 5567 b->status.map.inq_pag = btinfo.lb2.inq_pag; 5568 bt->inq_pag.now = btinfo.lb2.inq_pag; 5569 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 5570 5571 hfp->exist = btinfo.lb2.hfp; 5572 b->profile_cnt.now += (u8)hfp->exist; 5573 hid->exist = btinfo.lb2.hid; 5574 b->profile_cnt.now += (u8)hid->exist; 5575 a2dp->exist = btinfo.lb2.a2dp; 5576 b->profile_cnt.now += (u8)a2dp->exist; 5577 pan->active = btinfo.lb2.pan; 5578 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 5579 5580 /* parse raw info low-Byte3 */ 5581 btinfo.val = bt->raw_info[BTC_BTINFO_L3]; 5582 if (btinfo.lb3.retry != 0) 5583 cx->cnt_bt[BTC_BCNT_RETRY]++; 5584 b->cqddr = btinfo.lb3.cqddr; 5585 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 5586 bt->inq = btinfo.lb3.inq; 5587 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 5588 bt->pag = btinfo.lb3.pag; 5589 5590 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 5591 /* parse raw info high-Byte0 */ 5592 btinfo.val = bt->raw_info[BTC_BTINFO_H0]; 5593 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 5594 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 5595 btc->dm.trx_info.bt_rssi = b->rssi; 5596 5597 /* parse raw info high-Byte1 */ 5598 btinfo.val = bt->raw_info[BTC_BTINFO_H1]; 5599 b->status.map.ble_connect = btinfo.hb1.ble_connect; 5600 if (btinfo.hb1.ble_connect) 5601 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); 5602 5603 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 5604 bt->reinit = btinfo.hb1.reinit; 5605 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 5606 b->relink.now = btinfo.hb1.relink; 5607 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 5608 bt->igno_wl = btinfo.hb1.igno_wl; 5609 5610 if (bt->igno_wl && !cx->wl.status.map.rf_off) 5611 _set_bt_ignore_wlan_act(rtwdev, false); 5612 5613 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); 5614 bt->ble_scan_en = btinfo.hb1.ble_scan; 5615 5616 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 5617 b->role_sw = btinfo.hb1.role_sw; 5618 5619 b->multi_link.now = btinfo.hb1.multi_link; 5620 5621 /* parse raw info high-Byte2 */ 5622 btinfo.val = bt->raw_info[BTC_BTINFO_H2]; 5623 pan->exist = btinfo.hb2.pan_active; 5624 b->profile_cnt.now += (u8)pan->exist; 5625 5626 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 5627 b->afh_update = btinfo.hb2.afh_update; 5628 a2dp->active = btinfo.hb2.a2dp_active; 5629 b->slave_role = btinfo.hb2.slave; 5630 hid->slot_info = btinfo.hb2.hid_slot; 5631 hid->pair_cnt = btinfo.hb2.hid_cnt; 5632 hid->type |= (hid->slot_info == BTC_HID_218 ? 5633 BTC_HID_218 : BTC_HID_418); 5634 /* parse raw info high-Byte3 */ 5635 btinfo.val = bt->raw_info[BTC_BTINFO_H3]; 5636 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 5637 5638 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 5639 cx->cnt_bt[BTC_BCNT_RATECHG]++; 5640 b->tx_3m = (u32)btinfo.hb3.tx_3m; 5641 5642 a2dp->sink = btinfo.hb3.a2dp_sink; 5643 5644 if (!a2dp->exist_last && a2dp->exist) { 5645 a2dp->vendor_id = 0; 5646 a2dp->flush_time = 0; 5647 a2dp->play_latency = 1; 5648 ieee80211_queue_delayed_work(rtwdev->hw, 5649 &rtwdev->coex_bt_devinfo_work, 5650 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 5651 } 5652 5653 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 5654 } 5655 5656 enum btc_wl_mode { 5657 BTC_WL_MODE_HT = 0, 5658 BTC_WL_MODE_VHT = 1, 5659 BTC_WL_MODE_HE = 2, 5660 BTC_WL_MODE_NUM, 5661 }; 5662 5663 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 5664 struct rtw89_sta *rtwsta, enum btc_role_state state) 5665 { 5666 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, 5667 rtwvif->sub_entity_idx); 5668 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 5669 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); 5670 struct rtw89_btc *btc = &rtwdev->btc; 5671 const struct rtw89_btc_ver *ver = btc->ver; 5672 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5673 struct rtw89_btc_wl_link_info r = {0}; 5674 struct rtw89_btc_wl_link_info *wlinfo = NULL; 5675 u8 mode = 0; 5676 5677 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 5678 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5679 "[BTC], role is STA=%d\n", 5680 vif->type == NL80211_IFTYPE_STATION); 5681 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); 5682 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 5683 chan->band_type, chan->channel, chan->band_width); 5684 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 5685 state == BTC_ROLE_MSTS_STA_CONN_END); 5686 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5687 "[BTC], bcn_period=%d dtim_period=%d\n", 5688 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); 5689 5690 if (rtwsta) { 5691 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 5692 rtwsta->mac_id); 5693 5694 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5695 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 5696 sta->deflink.he_cap.has_he, 5697 sta->deflink.vht_cap.vht_supported, 5698 sta->deflink.ht_cap.ht_supported); 5699 if (sta->deflink.he_cap.has_he) 5700 mode |= BIT(BTC_WL_MODE_HE); 5701 if (sta->deflink.vht_cap.vht_supported) 5702 mode |= BIT(BTC_WL_MODE_VHT); 5703 if (sta->deflink.ht_cap.ht_supported) 5704 mode |= BIT(BTC_WL_MODE_HT); 5705 5706 r.mode = mode; 5707 } 5708 5709 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) 5710 return; 5711 5712 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5713 "[BTC], wifi_role=%d\n", rtwvif->wifi_role); 5714 5715 r.role = rtwvif->wifi_role; 5716 r.phy = rtwvif->phy_idx; 5717 r.pid = rtwvif->port; 5718 r.active = true; 5719 r.connected = MLME_LINKED; 5720 r.bcn_period = vif->bss_conf.beacon_int; 5721 r.dtim_period = vif->bss_conf.dtim_period; 5722 r.band = chan->band_type; 5723 r.ch = chan->channel; 5724 r.bw = chan->band_width; 5725 ether_addr_copy(r.mac_addr, rtwvif->mac_addr); 5726 5727 if (rtwsta && vif->type == NL80211_IFTYPE_STATION) 5728 r.mac_id = rtwsta->mac_id; 5729 5730 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 5731 5732 wlinfo = &wl->link_info[r.pid]; 5733 5734 memcpy(wlinfo, &r, sizeof(*wlinfo)); 5735 if (ver->fwlrole == 0) 5736 _update_wl_info(rtwdev); 5737 else if (ver->fwlrole == 1) 5738 _update_wl_info_v1(rtwdev); 5739 else if (ver->fwlrole == 2) 5740 _update_wl_info_v2(rtwdev); 5741 5742 if (wlinfo->role == RTW89_WIFI_ROLE_STATION && 5743 wlinfo->connected == MLME_NO_LINK) 5744 btc->dm.leak_ap = 0; 5745 5746 if (state == BTC_ROLE_MSTS_STA_CONN_START) 5747 wl->status.map.connecting = 1; 5748 else 5749 wl->status.map.connecting = 0; 5750 5751 if (state == BTC_ROLE_MSTS_STA_DIS_CONN) 5752 wl->status.map._4way = false; 5753 5754 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 5755 } 5756 5757 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 5758 { 5759 const struct rtw89_chip_info *chip = rtwdev->chip; 5760 struct rtw89_btc *btc = &rtwdev->btc; 5761 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5762 u32 val; 5763 5764 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 5765 __func__, rf_state); 5766 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 5767 5768 switch (rf_state) { 5769 case BTC_RFCTRL_WL_OFF: 5770 wl->status.map.rf_off = 1; 5771 wl->status.map.lps = BTC_LPS_OFF; 5772 wl->status.map.busy = 0; 5773 break; 5774 case BTC_RFCTRL_FW_CTRL: 5775 wl->status.map.rf_off = 0; 5776 wl->status.map.lps = BTC_LPS_RF_OFF; 5777 wl->status.map.busy = 0; 5778 break; 5779 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */ 5780 wl->status.map.rf_off = 0; 5781 wl->status.map.lps = BTC_LPS_RF_ON; 5782 wl->status.map.busy = 0; 5783 break; 5784 case BTC_RFCTRL_WL_ON: 5785 default: 5786 wl->status.map.rf_off = 0; 5787 wl->status.map.lps = BTC_LPS_OFF; 5788 break; 5789 } 5790 5791 if (rf_state == BTC_RFCTRL_WL_ON) { 5792 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true); 5793 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 5794 _write_scbd(rtwdev, val, true); 5795 _update_bt_scbd(rtwdev, true); 5796 chip->ops->btc_init_cfg(rtwdev); 5797 } else { 5798 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false); 5799 if (rf_state == BTC_RFCTRL_WL_OFF) 5800 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 5801 else if (rf_state == BTC_RFCTRL_LPS_WL_ON && 5802 wl->status.map.lps_pre != BTC_LPS_OFF) 5803 _update_bt_scbd(rtwdev, true); 5804 } 5805 5806 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 5807 if (wl->status.map.lps_pre == BTC_LPS_OFF && 5808 wl->status.map.lps_pre != wl->status.map.lps) 5809 btc->dm.tdma_instant_excute = 1; 5810 else 5811 btc->dm.tdma_instant_excute = 0; 5812 5813 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 5814 btc->dm.tdma_instant_excute = 0; 5815 wl->status.map.rf_off_pre = wl->status.map.rf_off; 5816 wl->status.map.lps_pre = wl->status.map.lps; 5817 } 5818 5819 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 5820 enum btc_wl_rfk_type type, 5821 enum btc_wl_rfk_state state) 5822 { 5823 struct rtw89_btc *btc = &rtwdev->btc; 5824 struct rtw89_btc_cx *cx = &btc->cx; 5825 struct rtw89_btc_wl_info *wl = &cx->wl; 5826 bool result = BTC_WRFK_REJECT; 5827 5828 wl->rfk_info.type = type; 5829 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 5830 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 5831 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 5832 5833 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5834 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 5835 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 5836 type, state); 5837 5838 switch (state) { 5839 case BTC_WRFK_START: 5840 result = _chk_wl_rfk_request(rtwdev); 5841 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP; 5842 5843 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result); 5844 5845 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 5846 break; 5847 case BTC_WRFK_ONESHOT_START: 5848 case BTC_WRFK_ONESHOT_STOP: 5849 if (wl->rfk_info.state == BTC_WRFK_STOP) { 5850 result = BTC_WRFK_REJECT; 5851 } else { 5852 result = BTC_WRFK_ALLOW; 5853 wl->rfk_info.state = state; 5854 } 5855 break; 5856 case BTC_WRFK_STOP: 5857 result = BTC_WRFK_ALLOW; 5858 wl->rfk_info.state = BTC_WRFK_STOP; 5859 5860 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 5861 cancel_delayed_work(&rtwdev->coex_rfk_chk_work); 5862 break; 5863 default: 5864 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5865 "[BTC], %s() warning state=%d\n", __func__, state); 5866 break; 5867 } 5868 5869 if (result == BTC_WRFK_ALLOW) { 5870 if (wl->rfk_info.state == BTC_WRFK_START || 5871 wl->rfk_info.state == BTC_WRFK_STOP) 5872 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 5873 5874 if (wl->rfk_info.state == BTC_WRFK_START) 5875 ieee80211_queue_delayed_work(rtwdev->hw, 5876 &rtwdev->coex_rfk_chk_work, 5877 RTW89_COEX_RFK_CHK_WORK_PERIOD); 5878 } 5879 5880 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5881 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 5882 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 5883 5884 return result == BTC_WRFK_ALLOW; 5885 } 5886 5887 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 5888 enum btc_wl_rfk_type type, 5889 enum btc_wl_rfk_state state) 5890 { 5891 u8 band; 5892 bool allow; 5893 int ret; 5894 5895 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 5896 5897 rtw89_debug(rtwdev, RTW89_DBG_RFK, 5898 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 5899 band == RTW89_BAND_2G ? "2G" : 5900 band == RTW89_BAND_5G ? "5G" : "6G", 5901 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 5902 type, 5903 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 5904 state == BTC_WRFK_STOP ? "RFK_STOP" : 5905 state == BTC_WRFK_START ? "RFK_START" : 5906 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 5907 "ONE-SHOT_STOP"); 5908 5909 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 5910 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 5911 return; 5912 } 5913 5914 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 5915 rtwdev, phy_map, type, state); 5916 if (ret) { 5917 rtw89_warn(rtwdev, "RFK notify timeout\n"); 5918 rtwdev->is_bt_iqk_timeout = true; 5919 } 5920 } 5921 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 5922 5923 struct rtw89_btc_wl_sta_iter_data { 5924 struct rtw89_dev *rtwdev; 5925 u8 busy_all; 5926 u8 dir_all; 5927 u8 rssi_map_all; 5928 bool is_sta_change; 5929 bool is_traffic_change; 5930 }; 5931 5932 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 5933 { 5934 struct rtw89_btc_wl_sta_iter_data *iter_data = 5935 (struct rtw89_btc_wl_sta_iter_data *)data; 5936 struct rtw89_dev *rtwdev = iter_data->rtwdev; 5937 struct rtw89_btc *btc = &rtwdev->btc; 5938 struct rtw89_btc_dm *dm = &btc->dm; 5939 const struct rtw89_btc_ver *ver = btc->ver; 5940 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5941 struct rtw89_btc_wl_link_info *link_info = NULL; 5942 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 5943 struct rtw89_traffic_stats *link_info_t = NULL; 5944 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 5945 struct rtw89_traffic_stats *stats = &rtwvif->stats; 5946 const struct rtw89_chip_info *chip = rtwdev->chip; 5947 struct rtw89_btc_wl_role_info *r; 5948 struct rtw89_btc_wl_role_info_v1 *r1; 5949 u32 last_tx_rate, last_rx_rate; 5950 u16 last_tx_lvl, last_rx_lvl; 5951 u8 port = rtwvif->port; 5952 u8 rssi; 5953 u8 busy = 0; 5954 u8 dir = 0; 5955 u8 rssi_map = 0; 5956 u8 i = 0; 5957 bool is_sta_change = false, is_traffic_change = false; 5958 5959 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; 5960 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 5961 5962 link_info = &wl->link_info[port]; 5963 link_info->stat.traffic = rtwvif->stats; 5964 link_info_t = &link_info->stat.traffic; 5965 5966 if (link_info->connected == MLME_NO_LINK) { 5967 link_info->rx_rate_drop_cnt = 0; 5968 return; 5969 } 5970 5971 link_info->stat.rssi = rssi; 5972 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 5973 link_info->rssi_state[i] = 5974 _update_rssi_state(rtwdev, 5975 link_info->rssi_state[i], 5976 link_info->stat.rssi, 5977 chip->wl_rssi_thres[i]); 5978 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 5979 rssi_map |= BIT(i); 5980 5981 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED && 5982 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 5983 is_sta_change = true; 5984 } 5985 iter_data->rssi_map_all |= rssi_map; 5986 5987 last_tx_rate = link_info_t->tx_rate; 5988 last_rx_rate = link_info_t->rx_rate; 5989 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 5990 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 5991 5992 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 5993 stats->rx_tfc_lv != RTW89_TFC_IDLE) 5994 busy = 1; 5995 5996 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 5997 dir = RTW89_TFC_UL; 5998 else 5999 dir = RTW89_TFC_DL; 6000 6001 link_info = &wl->link_info[port]; 6002 if (link_info->busy != busy || link_info->dir != dir) { 6003 is_sta_change = true; 6004 link_info->busy = busy; 6005 link_info->dir = dir; 6006 } 6007 6008 iter_data->busy_all |= busy; 6009 iter_data->dir_all |= BIT(dir); 6010 6011 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 6012 last_rx_rate > RTW89_HW_RATE_CCK2 && 6013 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 6014 link_info->rx_rate_drop_cnt++; 6015 6016 if (last_tx_rate != rtwsta->ra_report.hw_rate || 6017 last_rx_rate != rtwsta->rx_hw_rate || 6018 last_tx_lvl != link_info_t->tx_tfc_lv || 6019 last_rx_lvl != link_info_t->rx_tfc_lv) 6020 is_traffic_change = true; 6021 6022 link_info_t->tx_rate = rtwsta->ra_report.hw_rate; 6023 link_info_t->rx_rate = rtwsta->rx_hw_rate; 6024 6025 if (link_info->role == RTW89_WIFI_ROLE_STATION || 6026 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { 6027 dm->trx_info.tx_rate = link_info_t->tx_rate; 6028 dm->trx_info.rx_rate = link_info_t->rx_rate; 6029 } 6030 6031 if (ver->fwlrole == 0) { 6032 r = &wl->role_info; 6033 r->active_role[port].tx_lvl = stats->tx_tfc_lv; 6034 r->active_role[port].rx_lvl = stats->rx_tfc_lv; 6035 r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate; 6036 r->active_role[port].rx_rate = rtwsta->rx_hw_rate; 6037 } else if (ver->fwlrole == 1) { 6038 r1 = &wl->role_info_v1; 6039 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; 6040 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; 6041 r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate; 6042 r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate; 6043 } else if (ver->fwlrole == 2) { 6044 dm->trx_info.tx_lvl = stats->tx_tfc_lv; 6045 dm->trx_info.rx_lvl = stats->rx_tfc_lv; 6046 dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate; 6047 dm->trx_info.rx_rate = rtwsta->rx_hw_rate; 6048 } 6049 6050 dm->trx_info.tx_tp = link_info_t->tx_throughput; 6051 dm->trx_info.rx_tp = link_info_t->rx_throughput; 6052 6053 if (is_sta_change) 6054 iter_data->is_sta_change = true; 6055 6056 if (is_traffic_change) 6057 iter_data->is_traffic_change = true; 6058 } 6059 6060 #define BTC_NHM_CHK_INTVL 20 6061 6062 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 6063 { 6064 struct rtw89_btc *btc = &rtwdev->btc; 6065 struct rtw89_btc_dm *dm = &btc->dm; 6066 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6067 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 6068 u8 i; 6069 6070 ieee80211_iterate_stations_atomic(rtwdev->hw, 6071 rtw89_btc_ntfy_wl_sta_iter, 6072 &data); 6073 6074 wl->rssi_level = 0; 6075 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 6076 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 6077 /* set RSSI level 4 ~ 0 if rssi bit map match */ 6078 if (data.rssi_map_all & BIT(i - 1)) { 6079 wl->rssi_level = i; 6080 break; 6081 } 6082 } 6083 6084 if (dm->trx_info.wl_rssi != wl->rssi_level) 6085 dm->trx_info.wl_rssi = wl->rssi_level; 6086 6087 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 6088 __func__, !!wl->status.map.busy); 6089 6090 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 6091 6092 if (data.is_traffic_change) 6093 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6094 if (data.is_sta_change) { 6095 wl->status.map.busy = data.busy_all; 6096 wl->status.map.traffic_dir = data.dir_all; 6097 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 6098 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 6099 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 6100 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 6101 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 6102 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 6103 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 6104 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 6105 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 6106 } 6107 } 6108 6109 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 6110 u32 len, u8 class, u8 func) 6111 { 6112 struct rtw89_btc *btc = &rtwdev->btc; 6113 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6114 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 6115 6116 len -= RTW89_C2H_HEADER_LEN; 6117 6118 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6119 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 6120 __func__, len, class, func); 6121 6122 if (class != BTFC_FW_EVENT) 6123 return; 6124 6125 switch (func) { 6126 case BTF_EVNT_RPT: 6127 case BTF_EVNT_BUF_OVERFLOW: 6128 pfwinfo->event[func]++; 6129 /* Don't need rtw89_leave_ps_mode() */ 6130 btc_fw_event(rtwdev, func, buf, len); 6131 break; 6132 case BTF_EVNT_BT_INFO: 6133 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6134 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 6135 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++; 6136 _update_bt_info(rtwdev, buf, len); 6137 break; 6138 case BTF_EVNT_BT_SCBD: 6139 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6140 "[BTC], handle C2H BT SCBD with data %8ph\n", buf); 6141 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++; 6142 _update_bt_scbd(rtwdev, false); 6143 break; 6144 case BTF_EVNT_BT_PSD: 6145 break; 6146 case BTF_EVNT_BT_REG: 6147 btc->dbg.rb_done = true; 6148 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 6149 6150 break; 6151 case BTF_EVNT_C2H_LOOPBACK: 6152 btc->dbg.rb_done = true; 6153 btc->dbg.rb_val = buf[0]; 6154 break; 6155 case BTF_EVNT_CX_RUNINFO: 6156 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 6157 break; 6158 } 6159 } 6160 6161 #define BTC_CX_FW_OFFLOAD 0 6162 6163 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6164 { 6165 const struct rtw89_chip_info *chip = rtwdev->chip; 6166 struct rtw89_hal *hal = &rtwdev->hal; 6167 struct rtw89_btc *btc = &rtwdev->btc; 6168 struct rtw89_btc_dm *dm = &btc->dm; 6169 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6170 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6171 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 6172 6173 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 6174 return; 6175 6176 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 6177 6178 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n", 6179 chip->chip_id); 6180 6181 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 6182 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 6183 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 6184 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 6185 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ", 6186 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch); 6187 6188 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 6189 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 6190 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 6191 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 6192 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)", 6193 ver_main, ver_sub, ver_hotfix, id_branch); 6194 6195 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 6196 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 6197 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 6198 seq_printf(m, "(%s, desired:%d.%d.%d), ", 6199 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 6200 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 6201 6202 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n", 6203 bt->ver_info.fw_coex, 6204 (bt->ver_info.fw_coex >= chip->btcx_desired ? 6205 "Match" : "Mismatch"), chip->btcx_desired); 6206 6207 if (bt->enable.now && bt->ver_info.fw == 0) 6208 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 6209 else 6210 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 6211 6212 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 6213 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 6214 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 6215 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 6216 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n", 6217 "[sub_module]", 6218 ver_main, ver_sub, ver_hotfix, id_branch, 6219 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 6220 6221 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 6222 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type, 6223 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num, 6224 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ? 6225 "1Ant_Pos:S1, " : "1Ant_Pos:S0, "))); 6226 6227 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 6228 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, 6229 hal->rx_nss); 6230 } 6231 6232 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6233 { 6234 struct rtw89_btc *btc = &rtwdev->btc; 6235 struct rtw89_btc_wl_link_info *plink = NULL; 6236 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6237 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6238 struct rtw89_traffic_stats *t; 6239 u8 i; 6240 6241 if (rtwdev->dbcc_en) { 6242 seq_printf(m, 6243 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ", 6244 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0], 6245 wl_dinfo->scan_band[RTW89_PHY_0], 6246 wl_dinfo->real_band[RTW89_PHY_0]); 6247 seq_printf(m, 6248 "PHY1_band(op:%d/scan:%d/real:%d)\n", 6249 wl_dinfo->op_band[RTW89_PHY_1], 6250 wl_dinfo->scan_band[RTW89_PHY_1], 6251 wl_dinfo->real_band[RTW89_PHY_1]); 6252 } 6253 6254 for (i = 0; i < RTW89_PORT_NUM; i++) { 6255 plink = &btc->cx.wl.link_info[i]; 6256 6257 if (!plink->active) 6258 continue; 6259 6260 seq_printf(m, 6261 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 6262 plink->pid, (u32)plink->role, plink->phy, 6263 (u32)plink->connected, plink->client_cnt - 1, 6264 (u32)plink->mode, plink->ch, (u32)plink->bw); 6265 6266 if (plink->connected == MLME_NO_LINK) 6267 continue; 6268 6269 seq_printf(m, 6270 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 6271 plink->mac_id, plink->tx_time, plink->tx_retry); 6272 6273 seq_printf(m, 6274 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 6275 plink->pid, 110 - plink->stat.rssi, 6276 plink->stat.rssi, plink->busy, 6277 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 6278 6279 t = &plink->stat.traffic; 6280 6281 seq_printf(m, 6282 "tx[rate:%d/busy_level:%d], ", 6283 (u32)t->tx_rate, t->tx_tfc_lv); 6284 6285 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n", 6286 (u32)t->rx_rate, 6287 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 6288 } 6289 } 6290 6291 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6292 { 6293 struct rtw89_btc *btc = &rtwdev->btc; 6294 const struct rtw89_btc_ver *ver = btc->ver; 6295 struct rtw89_btc_cx *cx = &btc->cx; 6296 struct rtw89_btc_wl_info *wl = &cx->wl; 6297 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6298 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 6299 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 6300 u8 mode; 6301 6302 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 6303 return; 6304 6305 seq_puts(m, "========== [WL Status] ==========\n"); 6306 6307 if (ver->fwlrole == 0) 6308 mode = wl_rinfo->link_mode; 6309 else if (ver->fwlrole == 1) 6310 mode = wl_rinfo_v1->link_mode; 6311 else if (ver->fwlrole == 2) 6312 mode = wl_rinfo_v2->link_mode; 6313 else 6314 return; 6315 6316 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode); 6317 6318 seq_printf(m, 6319 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 6320 wl->status.map.rf_off, wl->status.map.lps, 6321 wl->status.map.scan ? "Y" : "N", 6322 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 6323 6324 seq_printf(m, 6325 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n", 6326 wl->status.map.connecting ? "Y" : "N", 6327 wl->status.map.roaming ? "Y" : "N", 6328 wl->status.map._4way ? "Y" : "N", 6329 wl->status.map.init_ok ? "Y" : "N"); 6330 6331 _show_wl_role_info(rtwdev, m); 6332 } 6333 6334 enum btc_bt_a2dp_type { 6335 BTC_A2DP_LEGACY = 0, 6336 BTC_A2DP_TWS_SNIFF = 1, 6337 BTC_A2DP_TWS_RELAY = 2, 6338 }; 6339 6340 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6341 { 6342 struct rtw89_btc *btc = &rtwdev->btc; 6343 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 6344 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 6345 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 6346 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 6347 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 6348 6349 if (hfp.exist) { 6350 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 6351 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 6352 bt_linfo->sut_pwr_level[0], 6353 bt_linfo->golden_rx_shift[0]); 6354 } 6355 6356 if (hid.exist) { 6357 seq_printf(m, 6358 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 6359 "[HID]", 6360 hid.type & BTC_HID_218 ? "2/18," : "", 6361 hid.type & BTC_HID_418 ? "4/18," : "", 6362 hid.type & BTC_HID_BLE ? "BLE," : "", 6363 hid.type & BTC_HID_RCU ? "RCU," : "", 6364 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 6365 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 6366 bt_linfo->golden_rx_shift[1]); 6367 } 6368 6369 if (a2dp.exist) { 6370 seq_printf(m, 6371 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 6372 "[A2DP]", 6373 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 6374 a2dp.bitpool, a2dp.flush_time); 6375 6376 seq_printf(m, 6377 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 6378 a2dp.vendor_id, a2dp.device_name, 6379 bt_linfo->sut_pwr_level[2], 6380 bt_linfo->golden_rx_shift[2]); 6381 } 6382 6383 if (pan.exist) { 6384 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n", 6385 "[PAN]", 6386 bt_linfo->sut_pwr_level[3], 6387 bt_linfo->golden_rx_shift[3]); 6388 } 6389 } 6390 6391 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6392 { 6393 struct rtw89_btc *btc = &rtwdev->btc; 6394 const struct rtw89_btc_ver *ver = btc->ver; 6395 struct rtw89_btc_cx *cx = &btc->cx; 6396 struct rtw89_btc_bt_info *bt = &cx->bt; 6397 struct rtw89_btc_wl_info *wl = &cx->wl; 6398 struct rtw89_btc_module *module = &btc->mdinfo; 6399 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 6400 u8 *afh = bt_linfo->afh_map; 6401 u8 *afh_le = bt_linfo->afh_map_le; 6402 6403 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 6404 return; 6405 6406 seq_puts(m, "========== [BT Status] ==========\n"); 6407 6408 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ", 6409 "[status]", bt->enable.now ? "Y" : "N", 6410 bt->btg_type ? "Y" : "N", 6411 (bt->enable.now && (bt->btg_type != module->bt_pos) ? 6412 "(efuse-mismatch!!)" : ""), 6413 (bt_linfo->status.map.connect ? "Y" : "N")); 6414 6415 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 6416 bt->igno_wl ? "Y" : "N", 6417 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 6418 6419 seq_printf(m, " %-15s : profile:%s%s%s%s%s ", 6420 "[profile]", 6421 (bt_linfo->profile_cnt.now == 0) ? "None," : "", 6422 bt_linfo->hfp_desc.exist ? "HFP," : "", 6423 bt_linfo->hid_desc.exist ? "HID," : "", 6424 bt_linfo->a2dp_desc.exist ? 6425 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 6426 bt_linfo->pan_desc.exist ? "PAN," : ""); 6427 6428 seq_printf(m, 6429 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 6430 bt_linfo->multi_link.now ? "Y" : "N", 6431 bt_linfo->slave_role ? "Slave" : "Master", 6432 bt_linfo->status.map.ble_connect ? "Y" : "N", 6433 bt_linfo->cqddr ? "Y" : "N", 6434 bt_linfo->a2dp_desc.active ? "Y" : "N", 6435 bt_linfo->pan_desc.active ? "Y" : "N"); 6436 6437 seq_printf(m, 6438 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s", 6439 "[link]", bt_linfo->rssi - 100, 6440 bt_linfo->tx_3m ? 3 : 2, 6441 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 6442 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 6443 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 6444 6445 seq_printf(m, 6446 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 6447 bt_linfo->relink.now ? " ReLink!!" : "", 6448 afh[0], afh[1], afh[2], afh[3], afh[4], 6449 afh[5], afh[6], afh[7], afh[8], afh[9]); 6450 6451 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 6452 seq_printf(m, 6453 "LE[%02x%02x_%02x_%02x%02x]", 6454 afh_le[0], afh_le[1], afh_le[2], 6455 afh_le[3], afh_le[4]); 6456 6457 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n", 6458 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw); 6459 6460 seq_printf(m, 6461 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 6462 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY], 6463 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG], 6464 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]); 6465 6466 seq_printf(m, 6467 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 6468 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH], 6469 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ], 6470 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]); 6471 6472 _show_bt_profile_info(rtwdev, m); 6473 6474 seq_printf(m, 6475 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 6476 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 6477 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 6478 bt->raw_info[7], 6479 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 6480 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 6481 cx->cnt_bt[BTC_BCNT_INFOSAME]); 6482 6483 seq_printf(m, 6484 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)", 6485 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX], 6486 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX], 6487 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]); 6488 6489 if (!bt->scan_info_update) { 6490 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true); 6491 seq_puts(m, "\n"); 6492 } else { 6493 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false); 6494 if (ver->fcxbtscan == 1) { 6495 seq_printf(m, 6496 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)", 6497 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win), 6498 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl), 6499 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win), 6500 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl), 6501 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win), 6502 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl), 6503 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win), 6504 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl)); 6505 } else if (ver->fcxbtscan == 2) { 6506 seq_printf(m, 6507 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)", 6508 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win), 6509 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl), 6510 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win), 6511 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl), 6512 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win), 6513 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl)); 6514 } 6515 seq_puts(m, "\n"); 6516 } 6517 6518 if (bt->enable.now && bt->ver_info.fw == 0) 6519 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 6520 else 6521 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 6522 6523 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect) 6524 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true); 6525 else 6526 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false); 6527 6528 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 6529 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true); 6530 else 6531 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false); 6532 6533 if (bt_linfo->a2dp_desc.exist && 6534 (bt_linfo->a2dp_desc.flush_time == 0 || 6535 bt_linfo->a2dp_desc.vendor_id == 0 || 6536 bt_linfo->a2dp_desc.play_latency == 1)) 6537 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true); 6538 else 6539 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false); 6540 } 6541 6542 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 6543 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 6544 #define CASE_BTC_POLICY_STR(e) \ 6545 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 6546 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 6547 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e 6548 6549 static const char *steps_to_str(u16 step) 6550 { 6551 switch (step) { 6552 CASE_BTC_RSN_STR(NONE); 6553 CASE_BTC_RSN_STR(NTFY_INIT); 6554 CASE_BTC_RSN_STR(NTFY_SWBAND); 6555 CASE_BTC_RSN_STR(NTFY_WL_STA); 6556 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 6557 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 6558 CASE_BTC_RSN_STR(NTFY_WL_RFK); 6559 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 6560 CASE_BTC_RSN_STR(NTFY_SCAN_START); 6561 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 6562 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 6563 CASE_BTC_RSN_STR(NTFY_POWEROFF); 6564 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 6565 CASE_BTC_RSN_STR(CMD_SET_COEX); 6566 CASE_BTC_RSN_STR(ACT1_WORK); 6567 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 6568 CASE_BTC_RSN_STR(RFK_CHK_WORK); 6569 6570 CASE_BTC_ACT_STR(NONE); 6571 CASE_BTC_ACT_STR(WL_ONLY); 6572 CASE_BTC_ACT_STR(WL_5G); 6573 CASE_BTC_ACT_STR(WL_OTHER); 6574 CASE_BTC_ACT_STR(WL_IDLE); 6575 CASE_BTC_ACT_STR(WL_NC); 6576 CASE_BTC_ACT_STR(WL_RFK); 6577 CASE_BTC_ACT_STR(WL_INIT); 6578 CASE_BTC_ACT_STR(WL_OFF); 6579 CASE_BTC_ACT_STR(FREERUN); 6580 CASE_BTC_ACT_STR(BT_WHQL); 6581 CASE_BTC_ACT_STR(BT_RFK); 6582 CASE_BTC_ACT_STR(BT_OFF); 6583 CASE_BTC_ACT_STR(BT_IDLE); 6584 CASE_BTC_ACT_STR(BT_HFP); 6585 CASE_BTC_ACT_STR(BT_HID); 6586 CASE_BTC_ACT_STR(BT_A2DP); 6587 CASE_BTC_ACT_STR(BT_A2DPSINK); 6588 CASE_BTC_ACT_STR(BT_PAN); 6589 CASE_BTC_ACT_STR(BT_A2DP_HID); 6590 CASE_BTC_ACT_STR(BT_A2DP_PAN); 6591 CASE_BTC_ACT_STR(BT_PAN_HID); 6592 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 6593 CASE_BTC_ACT_STR(WL_25G_MCC); 6594 CASE_BTC_ACT_STR(WL_2G_MCC); 6595 CASE_BTC_ACT_STR(WL_2G_SCC); 6596 CASE_BTC_ACT_STR(WL_2G_AP); 6597 CASE_BTC_ACT_STR(WL_2G_GO); 6598 CASE_BTC_ACT_STR(WL_2G_GC); 6599 CASE_BTC_ACT_STR(WL_2G_NAN); 6600 6601 CASE_BTC_POLICY_STR(OFF_BT); 6602 CASE_BTC_POLICY_STR(OFF_WL); 6603 CASE_BTC_POLICY_STR(OFF_EQ0); 6604 CASE_BTC_POLICY_STR(OFF_EQ1); 6605 CASE_BTC_POLICY_STR(OFF_EQ2); 6606 CASE_BTC_POLICY_STR(OFF_EQ3); 6607 CASE_BTC_POLICY_STR(OFF_BWB0); 6608 CASE_BTC_POLICY_STR(OFF_BWB1); 6609 CASE_BTC_POLICY_STR(OFF_BWB2); 6610 CASE_BTC_POLICY_STR(OFF_BWB3); 6611 CASE_BTC_POLICY_STR(OFFB_BWB0); 6612 CASE_BTC_POLICY_STR(OFFE_DEF); 6613 CASE_BTC_POLICY_STR(OFFE_DEF2); 6614 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 6615 CASE_BTC_POLICY_STR(OFFE_2GISOB); 6616 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 6617 CASE_BTC_POLICY_STR(OFFE_WL); 6618 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 6619 CASE_BTC_POLICY_STR(FIX_TD3030); 6620 CASE_BTC_POLICY_STR(FIX_TD5050); 6621 CASE_BTC_POLICY_STR(FIX_TD2030); 6622 CASE_BTC_POLICY_STR(FIX_TD4010); 6623 CASE_BTC_POLICY_STR(FIX_TD7010); 6624 CASE_BTC_POLICY_STR(FIX_TD2060); 6625 CASE_BTC_POLICY_STR(FIX_TD3060); 6626 CASE_BTC_POLICY_STR(FIX_TD2080); 6627 CASE_BTC_POLICY_STR(FIX_TDW1B1); 6628 CASE_BTC_POLICY_STR(FIX_TD4020); 6629 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 6630 CASE_BTC_POLICY_STR(PFIX_TD3030); 6631 CASE_BTC_POLICY_STR(PFIX_TD5050); 6632 CASE_BTC_POLICY_STR(PFIX_TD2030); 6633 CASE_BTC_POLICY_STR(PFIX_TD2060); 6634 CASE_BTC_POLICY_STR(PFIX_TD3070); 6635 CASE_BTC_POLICY_STR(PFIX_TD2080); 6636 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 6637 CASE_BTC_POLICY_STR(AUTO_TD50B1); 6638 CASE_BTC_POLICY_STR(AUTO_TD60B1); 6639 CASE_BTC_POLICY_STR(AUTO_TD20B1); 6640 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 6641 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 6642 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 6643 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 6644 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 6645 CASE_BTC_POLICY_STR(AUTO2_TD3050); 6646 CASE_BTC_POLICY_STR(AUTO2_TD3070); 6647 CASE_BTC_POLICY_STR(AUTO2_TD5050); 6648 CASE_BTC_POLICY_STR(AUTO2_TD6060); 6649 CASE_BTC_POLICY_STR(AUTO2_TD2080); 6650 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 6651 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 6652 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 6653 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 6654 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 6655 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 6656 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 6657 default: 6658 return "unknown step"; 6659 } 6660 } 6661 6662 static const char *id_to_slot(u32 id) 6663 { 6664 switch (id) { 6665 CASE_BTC_SLOT_STR(OFF); 6666 CASE_BTC_SLOT_STR(B2W); 6667 CASE_BTC_SLOT_STR(W1); 6668 CASE_BTC_SLOT_STR(W2); 6669 CASE_BTC_SLOT_STR(W2B); 6670 CASE_BTC_SLOT_STR(B1); 6671 CASE_BTC_SLOT_STR(B2); 6672 CASE_BTC_SLOT_STR(B3); 6673 CASE_BTC_SLOT_STR(B4); 6674 CASE_BTC_SLOT_STR(LK); 6675 CASE_BTC_SLOT_STR(BLK); 6676 CASE_BTC_SLOT_STR(E2G); 6677 CASE_BTC_SLOT_STR(E5G); 6678 CASE_BTC_SLOT_STR(EBT); 6679 CASE_BTC_SLOT_STR(ENULL); 6680 CASE_BTC_SLOT_STR(WLK); 6681 CASE_BTC_SLOT_STR(W1FDD); 6682 CASE_BTC_SLOT_STR(B1FDD); 6683 default: 6684 return "unknown"; 6685 } 6686 } 6687 6688 static const char *id_to_evt(u32 id) 6689 { 6690 switch (id) { 6691 CASE_BTC_EVT_STR(TDMA_ENTRY); 6692 CASE_BTC_EVT_STR(WL_TMR); 6693 CASE_BTC_EVT_STR(B1_TMR); 6694 CASE_BTC_EVT_STR(B2_TMR); 6695 CASE_BTC_EVT_STR(B3_TMR); 6696 CASE_BTC_EVT_STR(B4_TMR); 6697 CASE_BTC_EVT_STR(W2B_TMR); 6698 CASE_BTC_EVT_STR(B2W_TMR); 6699 CASE_BTC_EVT_STR(BCN_EARLY); 6700 CASE_BTC_EVT_STR(A2DP_EMPTY); 6701 CASE_BTC_EVT_STR(LK_END); 6702 CASE_BTC_EVT_STR(RX_ISR); 6703 CASE_BTC_EVT_STR(RX_FC0); 6704 CASE_BTC_EVT_STR(RX_FC1); 6705 CASE_BTC_EVT_STR(BT_RELINK); 6706 CASE_BTC_EVT_STR(BT_RETRY); 6707 CASE_BTC_EVT_STR(E2G); 6708 CASE_BTC_EVT_STR(E5G); 6709 CASE_BTC_EVT_STR(EBT); 6710 CASE_BTC_EVT_STR(ENULL); 6711 CASE_BTC_EVT_STR(DRV_WLK); 6712 CASE_BTC_EVT_STR(BCN_OK); 6713 CASE_BTC_EVT_STR(BT_CHANGE); 6714 CASE_BTC_EVT_STR(EBT_EXTEND); 6715 CASE_BTC_EVT_STR(E2G_NULL1); 6716 CASE_BTC_EVT_STR(B1FDD_TMR); 6717 default: 6718 return "unknown"; 6719 } 6720 } 6721 6722 static 6723 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data, 6724 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 6725 { 6726 u8 i; 6727 u8 cur_index; 6728 6729 for (i = 0; i < len ; i++) { 6730 if ((i % seg_len) == 0) 6731 seq_printf(m, " %-15s : ", prefix); 6732 cur_index = (start_idx + i) % ring_len; 6733 if (i % 3 == 0) 6734 seq_printf(m, "-> %-20s", 6735 steps_to_str(*(data + cur_index))); 6736 else if (i % 3 == 1) 6737 seq_printf(m, "-> %-15s", 6738 steps_to_str(*(data + cur_index))); 6739 else 6740 seq_printf(m, "-> %-13s", 6741 steps_to_str(*(data + cur_index))); 6742 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 6743 seq_puts(m, "\n"); 6744 } 6745 } 6746 6747 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m) 6748 { 6749 struct rtw89_btc *btc = &rtwdev->btc; 6750 struct rtw89_btc_dm *dm = &btc->dm; 6751 u8 start_idx; 6752 u8 len; 6753 6754 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 6755 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 6756 6757 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx, 6758 ARRAY_SIZE(dm->dm_step.step)); 6759 } 6760 6761 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6762 { 6763 struct rtw89_btc *btc = &rtwdev->btc; 6764 struct rtw89_btc_module *module = &btc->mdinfo; 6765 struct rtw89_btc_dm *dm = &btc->dm; 6766 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6767 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6768 6769 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 6770 return; 6771 6772 seq_printf(m, "========== [Mechanism Status %s] ==========\n", 6773 (btc->ctrl.manual ? "(Manual)" : "(Auto)")); 6774 6775 seq_printf(m, 6776 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n", 6777 "[status]", 6778 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated", 6779 steps_to_str(dm->run_reason), 6780 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 6781 FIELD_GET(GENMASK(7, 0), dm->set_ant_path), 6782 dm->cnt_dm[BTC_DCNT_RUN]); 6783 6784 _show_dm_step(rtwdev, m); 6785 6786 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 6787 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt, 6788 dm->freerun, btc->lps, dm->wl_mimo_ps); 6789 6790 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap, 6791 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 6792 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 6793 "" : "(Mismatch!!)")); 6794 6795 if (dm->rf_trx_para.wl_tx_power == 0xff) 6796 seq_printf(m, 6797 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ", 6798 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level); 6799 6800 else 6801 seq_printf(m, 6802 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ", 6803 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level, 6804 dm->rf_trx_para.wl_tx_power); 6805 6806 seq_printf(m, 6807 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n", 6808 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power, 6809 dm->rf_trx_para.bt_rx_gain, 6810 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx); 6811 6812 seq_printf(m, 6813 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 6814 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time, 6815 dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri); 6816 } 6817 6818 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m) 6819 { 6820 struct rtw89_btc *btc = &rtwdev->btc; 6821 const struct rtw89_btc_ver *ver = btc->ver; 6822 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6823 union rtw89_btc_fbtc_cysta_info *pcysta; 6824 u32 except_cnt, exception_map; 6825 6826 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 6827 if (ver->fcxcysta == 2) { 6828 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 6829 except_cnt = le32_to_cpu(pcysta->v2.except_cnt); 6830 exception_map = le32_to_cpu(pcysta->v2.exception); 6831 } else if (ver->fcxcysta == 3) { 6832 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 6833 except_cnt = le32_to_cpu(pcysta->v3.except_cnt); 6834 exception_map = le32_to_cpu(pcysta->v3.except_map); 6835 } else if (ver->fcxcysta == 4) { 6836 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 6837 except_cnt = pcysta->v4.except_cnt; 6838 exception_map = le32_to_cpu(pcysta->v4.except_map); 6839 } else if (ver->fcxcysta == 5) { 6840 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 6841 except_cnt = pcysta->v5.except_cnt; 6842 exception_map = le32_to_cpu(pcysta->v5.except_map); 6843 } else { 6844 return; 6845 } 6846 6847 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 6848 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 6849 return; 6850 6851 seq_printf(m, " %-15s : ", "[error]"); 6852 6853 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 6854 seq_printf(m, 6855 "overflow-cnt: %d, ", 6856 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 6857 } 6858 6859 if (pfwinfo->len_mismch) { 6860 seq_printf(m, 6861 "len-mismatch: 0x%x, ", 6862 pfwinfo->len_mismch); 6863 } 6864 6865 if (pfwinfo->fver_mismch) { 6866 seq_printf(m, 6867 "fver-mismatch: 0x%x, ", 6868 pfwinfo->fver_mismch); 6869 } 6870 6871 /* cycle statistics exceptions */ 6872 if (exception_map || except_cnt) { 6873 seq_printf(m, 6874 "exception-type: 0x%x, exception-cnt = %d", 6875 exception_map, except_cnt); 6876 } 6877 seq_puts(m, "\n"); 6878 } 6879 6880 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m) 6881 { 6882 struct rtw89_btc *btc = &rtwdev->btc; 6883 const struct rtw89_btc_ver *ver = btc->ver; 6884 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6885 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6886 struct rtw89_btc_fbtc_tdma *t = NULL; 6887 6888 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 6889 if (!pcinfo->valid) 6890 return; 6891 6892 if (ver->fcxtdma == 1) 6893 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 6894 else 6895 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma; 6896 6897 seq_printf(m, 6898 " %-15s : ", "[tdma_policy]"); 6899 seq_printf(m, 6900 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ", 6901 (u32)t->type, 6902 t->rxflctrl, t->txpause); 6903 6904 seq_printf(m, 6905 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ", 6906 t->wtgle_n, t->leak_n, t->ext_ctrl); 6907 6908 seq_printf(m, 6909 "policy_type:%d", 6910 (u32)btc->policy_type); 6911 6912 seq_puts(m, "\n"); 6913 } 6914 6915 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m) 6916 { 6917 struct rtw89_btc *btc = &rtwdev->btc; 6918 struct rtw89_btc_dm *dm = &btc->dm; 6919 struct rtw89_btc_fbtc_slot *s; 6920 u8 i = 0; 6921 6922 for (i = 0; i < CXST_MAX; i++) { 6923 s = &dm->slot_now[i]; 6924 if (i % 5 == 0) 6925 seq_printf(m, 6926 " %-15s : %5s[%03d/0x%x/%d]", 6927 "[slot_list]", 6928 id_to_slot((u32)i), 6929 s->dur, s->cxtbl, s->cxtype); 6930 else 6931 seq_printf(m, 6932 ", %5s[%03d/0x%x/%d]", 6933 id_to_slot((u32)i), 6934 s->dur, s->cxtbl, s->cxtype); 6935 if (i % 5 == 4) 6936 seq_puts(m, "\n"); 6937 } 6938 seq_puts(m, "\n"); 6939 } 6940 6941 static void _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, struct seq_file *m) 6942 { 6943 struct rtw89_btc *btc = &rtwdev->btc; 6944 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6945 struct rtw89_btc_dm *dm = &btc->dm; 6946 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 6947 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6948 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL; 6949 union rtw89_btc_fbtc_rxflct r; 6950 u8 i, cnt = 0, slot_pair; 6951 u16 cycle, c_begin, c_end, store_index; 6952 6953 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 6954 if (!pcinfo->valid) 6955 return; 6956 6957 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 6958 seq_printf(m, 6959 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 6960 "[cycle_cnt]", 6961 le16_to_cpu(pcysta_le32->cycles), 6962 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]), 6963 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]), 6964 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]), 6965 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK])); 6966 6967 for (i = 0; i < CXST_MAX; i++) { 6968 if (!le32_to_cpu(pcysta_le32->slot_cnt[i])) 6969 continue; 6970 seq_printf(m, ", %s:%d", id_to_slot((u32)i), 6971 le32_to_cpu(pcysta_le32->slot_cnt[i])); 6972 } 6973 6974 if (dm->tdma_now.rxflctrl) { 6975 seq_printf(m, ", leak_rx:%d", 6976 le32_to_cpu(pcysta_le32->leakrx_cnt)); 6977 } 6978 6979 if (le32_to_cpu(pcysta_le32->collision_cnt)) { 6980 seq_printf(m, ", collision:%d", 6981 le32_to_cpu(pcysta_le32->collision_cnt)); 6982 } 6983 6984 if (le32_to_cpu(pcysta_le32->skip_cnt)) { 6985 seq_printf(m, ", skip:%d", 6986 le32_to_cpu(pcysta_le32->skip_cnt)); 6987 } 6988 seq_puts(m, "\n"); 6989 6990 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 6991 "[cycle_time]", 6992 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]), 6993 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]), 6994 le16_to_cpu(pcysta_le32->tavg_lk) / 1000, 6995 le16_to_cpu(pcysta_le32->tavg_lk) % 1000); 6996 seq_printf(m, ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 6997 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]), 6998 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]), 6999 le16_to_cpu(pcysta_le32->tmax_lk) / 1000, 7000 le16_to_cpu(pcysta_le32->tmax_lk) % 1000); 7001 seq_printf(m, ", maxdiff_t[wl:%d/bt:%d]\n", 7002 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]), 7003 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT])); 7004 7005 if (le16_to_cpu(pcysta_le32->cycles) <= 1) 7006 return; 7007 7008 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7009 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7010 7011 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair) 7012 c_begin = 1; 7013 else 7014 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1; 7015 7016 c_end = le16_to_cpu(pcysta_le32->cycles); 7017 7018 for (cycle = c_begin; cycle <= c_end; cycle++) { 7019 cnt++; 7020 store_index = ((cycle - 1) % slot_pair) * 2; 7021 7022 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 7023 seq_printf(m, 7024 " %-15s : ->b%02d->w%02d", "[cycle_step]", 7025 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 7026 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 7027 else 7028 seq_printf(m, 7029 "->b%02d->w%02d", 7030 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 7031 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 7032 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 7033 seq_puts(m, "\n"); 7034 } 7035 7036 if (a2dp->exist) { 7037 seq_printf(m, 7038 " %-15s : a2dp_ept:%d, a2dp_late:%d", 7039 "[a2dp_t_sta]", 7040 le16_to_cpu(pcysta_le32->a2dpept), 7041 le16_to_cpu(pcysta_le32->a2dpeptto)); 7042 7043 seq_printf(m, 7044 ", avg_t:%d, max_t:%d", 7045 le16_to_cpu(pcysta_le32->tavg_a2dpept), 7046 le16_to_cpu(pcysta_le32->tmax_a2dpept)); 7047 r.val = dm->tdma_now.rxflctrl; 7048 7049 if (r.type && r.tgln_n) { 7050 seq_printf(m, 7051 ", cycle[PSTDMA:%d/TDMA:%d], ", 7052 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]), 7053 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF])); 7054 7055 seq_printf(m, 7056 "avg_t[PSTDMA:%d/TDMA:%d], ", 7057 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]), 7058 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF])); 7059 7060 seq_printf(m, 7061 "max_t[PSTDMA:%d/TDMA:%d]", 7062 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]), 7063 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF])); 7064 } 7065 seq_puts(m, "\n"); 7066 } 7067 } 7068 7069 static void _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, struct seq_file *m) 7070 { 7071 struct rtw89_btc *btc = &rtwdev->btc; 7072 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7073 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7074 struct rtw89_btc_dm *dm = &btc->dm; 7075 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 7076 struct rtw89_btc_fbtc_cysta_v3 *pcysta; 7077 struct rtw89_btc_rpt_cmn_info *pcinfo; 7078 u8 i, cnt = 0, slot_pair, divide_cnt; 7079 u16 cycle, c_begin, c_end, store_index; 7080 7081 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7082 if (!pcinfo->valid) 7083 return; 7084 7085 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 7086 seq_printf(m, 7087 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7088 "[cycle_cnt]", 7089 le16_to_cpu(pcysta->cycles), 7090 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 7091 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 7092 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 7093 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 7094 7095 for (i = 0; i < CXST_MAX; i++) { 7096 if (!le32_to_cpu(pcysta->slot_cnt[i])) 7097 continue; 7098 7099 seq_printf(m, ", %s:%d", id_to_slot(i), 7100 le32_to_cpu(pcysta->slot_cnt[i])); 7101 } 7102 7103 if (dm->tdma_now.rxflctrl) 7104 seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 7105 7106 if (le32_to_cpu(pcysta->collision_cnt)) 7107 seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt)); 7108 7109 if (le32_to_cpu(pcysta->skip_cnt)) 7110 seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt)); 7111 7112 seq_puts(m, "\n"); 7113 7114 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7115 "[cycle_time]", 7116 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 7117 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 7118 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 7119 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 7120 seq_printf(m, 7121 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 7122 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 7123 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 7124 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 7125 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 7126 seq_printf(m, 7127 ", maxdiff_t[wl:%d/bt:%d]\n", 7128 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 7129 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 7130 7131 cycle = le16_to_cpu(pcysta->cycles); 7132 if (cycle <= 1) 7133 return; 7134 7135 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7136 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7137 7138 if (cycle <= slot_pair) 7139 c_begin = 1; 7140 else 7141 c_begin = cycle - slot_pair + 1; 7142 7143 c_end = cycle; 7144 7145 if (a2dp->exist) 7146 divide_cnt = 3; 7147 else 7148 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 7149 7150 for (cycle = c_begin; cycle <= c_end; cycle++) { 7151 cnt++; 7152 store_index = ((cycle - 1) % slot_pair) * 2; 7153 7154 if (cnt % divide_cnt == 1) 7155 seq_printf(m, " %-15s : ", "[cycle_step]"); 7156 7157 seq_printf(m, "->b%02d", 7158 le16_to_cpu(pcysta->slot_step_time[store_index])); 7159 if (a2dp->exist) { 7160 a2dp_trx = &pcysta->a2dp_trx[store_index]; 7161 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7162 a2dp_trx->empty_cnt, 7163 a2dp_trx->retry_cnt, 7164 a2dp_trx->tx_rate ? 3 : 2, 7165 a2dp_trx->tx_cnt, 7166 a2dp_trx->ack_cnt, 7167 a2dp_trx->nack_cnt); 7168 } 7169 seq_printf(m, "->w%02d", 7170 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 7171 if (a2dp->exist) { 7172 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 7173 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7174 a2dp_trx->empty_cnt, 7175 a2dp_trx->retry_cnt, 7176 a2dp_trx->tx_rate ? 3 : 2, 7177 a2dp_trx->tx_cnt, 7178 a2dp_trx->ack_cnt, 7179 a2dp_trx->nack_cnt); 7180 } 7181 if (cnt % divide_cnt == 0 || cnt == c_end) 7182 seq_puts(m, "\n"); 7183 } 7184 7185 if (a2dp->exist) { 7186 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d", 7187 "[a2dp_t_sta]", 7188 le16_to_cpu(pcysta->a2dp_ept.cnt), 7189 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 7190 7191 seq_printf(m, ", avg_t:%d, max_t:%d", 7192 le16_to_cpu(pcysta->a2dp_ept.tavg), 7193 le16_to_cpu(pcysta->a2dp_ept.tmax)); 7194 7195 seq_puts(m, "\n"); 7196 } 7197 } 7198 7199 static void _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, struct seq_file *m) 7200 { 7201 struct rtw89_btc *btc = &rtwdev->btc; 7202 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7203 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7204 struct rtw89_btc_dm *dm = &btc->dm; 7205 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 7206 struct rtw89_btc_fbtc_cysta_v4 *pcysta; 7207 struct rtw89_btc_rpt_cmn_info *pcinfo; 7208 u8 i, cnt = 0, slot_pair, divide_cnt; 7209 u16 cycle, c_begin, c_end, store_index; 7210 7211 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7212 if (!pcinfo->valid) 7213 return; 7214 7215 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 7216 seq_printf(m, 7217 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7218 "[cycle_cnt]", 7219 le16_to_cpu(pcysta->cycles), 7220 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 7221 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 7222 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 7223 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 7224 7225 for (i = 0; i < CXST_MAX; i++) { 7226 if (!le16_to_cpu(pcysta->slot_cnt[i])) 7227 continue; 7228 7229 seq_printf(m, ", %s:%d", id_to_slot(i), 7230 le16_to_cpu(pcysta->slot_cnt[i])); 7231 } 7232 7233 if (dm->tdma_now.rxflctrl) 7234 seq_printf(m, ", leak_rx:%d", 7235 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 7236 7237 if (pcysta->collision_cnt) 7238 seq_printf(m, ", collision:%d", pcysta->collision_cnt); 7239 7240 if (le16_to_cpu(pcysta->skip_cnt)) 7241 seq_printf(m, ", skip:%d", 7242 le16_to_cpu(pcysta->skip_cnt)); 7243 7244 seq_puts(m, "\n"); 7245 7246 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7247 "[cycle_time]", 7248 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 7249 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 7250 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 7251 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 7252 seq_printf(m, 7253 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 7254 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 7255 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 7256 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 7257 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 7258 seq_printf(m, 7259 ", maxdiff_t[wl:%d/bt:%d]\n", 7260 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 7261 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 7262 7263 cycle = le16_to_cpu(pcysta->cycles); 7264 if (cycle <= 1) 7265 return; 7266 7267 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7268 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7269 7270 if (cycle <= slot_pair) 7271 c_begin = 1; 7272 else 7273 c_begin = cycle - slot_pair + 1; 7274 7275 c_end = cycle; 7276 7277 if (a2dp->exist) 7278 divide_cnt = 3; 7279 else 7280 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 7281 7282 for (cycle = c_begin; cycle <= c_end; cycle++) { 7283 cnt++; 7284 store_index = ((cycle - 1) % slot_pair) * 2; 7285 7286 if (cnt % divide_cnt == 1) 7287 seq_printf(m, " %-15s : ", "[cycle_step]"); 7288 7289 seq_printf(m, "->b%02d", 7290 le16_to_cpu(pcysta->slot_step_time[store_index])); 7291 if (a2dp->exist) { 7292 a2dp_trx = &pcysta->a2dp_trx[store_index]; 7293 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7294 a2dp_trx->empty_cnt, 7295 a2dp_trx->retry_cnt, 7296 a2dp_trx->tx_rate ? 3 : 2, 7297 a2dp_trx->tx_cnt, 7298 a2dp_trx->ack_cnt, 7299 a2dp_trx->nack_cnt); 7300 } 7301 seq_printf(m, "->w%02d", 7302 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 7303 if (a2dp->exist) { 7304 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 7305 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7306 a2dp_trx->empty_cnt, 7307 a2dp_trx->retry_cnt, 7308 a2dp_trx->tx_rate ? 3 : 2, 7309 a2dp_trx->tx_cnt, 7310 a2dp_trx->ack_cnt, 7311 a2dp_trx->nack_cnt); 7312 } 7313 if (cnt % divide_cnt == 0 || cnt == c_end) 7314 seq_puts(m, "\n"); 7315 } 7316 7317 if (a2dp->exist) { 7318 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d", 7319 "[a2dp_t_sta]", 7320 le16_to_cpu(pcysta->a2dp_ept.cnt), 7321 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 7322 7323 seq_printf(m, ", avg_t:%d, max_t:%d", 7324 le16_to_cpu(pcysta->a2dp_ept.tavg), 7325 le16_to_cpu(pcysta->a2dp_ept.tmax)); 7326 7327 seq_puts(m, "\n"); 7328 } 7329 } 7330 7331 static void _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, struct seq_file *m) 7332 { 7333 struct rtw89_btc *btc = &rtwdev->btc; 7334 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7335 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7336 struct rtw89_btc_dm *dm = &btc->dm; 7337 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 7338 struct rtw89_btc_fbtc_cysta_v5 *pcysta; 7339 struct rtw89_btc_rpt_cmn_info *pcinfo; 7340 u8 i, cnt = 0, slot_pair, divide_cnt; 7341 u16 cycle, c_begin, c_end, store_index; 7342 7343 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 7344 if (!pcinfo->valid) 7345 return; 7346 7347 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 7348 seq_printf(m, 7349 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 7350 "[cycle_cnt]", 7351 le16_to_cpu(pcysta->cycles), 7352 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 7353 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 7354 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 7355 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 7356 7357 for (i = 0; i < CXST_MAX; i++) { 7358 if (!le16_to_cpu(pcysta->slot_cnt[i])) 7359 continue; 7360 7361 seq_printf(m, ", %s:%d", id_to_slot(i), 7362 le16_to_cpu(pcysta->slot_cnt[i])); 7363 } 7364 7365 if (dm->tdma_now.rxflctrl) 7366 seq_printf(m, ", leak_rx:%d", 7367 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 7368 7369 if (pcysta->collision_cnt) 7370 seq_printf(m, ", collision:%d", pcysta->collision_cnt); 7371 7372 if (le16_to_cpu(pcysta->skip_cnt)) 7373 seq_printf(m, ", skip:%d", 7374 le16_to_cpu(pcysta->skip_cnt)); 7375 7376 seq_puts(m, "\n"); 7377 7378 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 7379 "[cycle_time]", 7380 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 7381 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 7382 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 7383 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 7384 seq_printf(m, 7385 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 7386 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 7387 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 7388 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 7389 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 7390 7391 cycle = le16_to_cpu(pcysta->cycles); 7392 if (cycle <= 1) 7393 return; 7394 7395 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 7396 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 7397 7398 if (cycle <= slot_pair) 7399 c_begin = 1; 7400 else 7401 c_begin = cycle - slot_pair + 1; 7402 7403 c_end = cycle; 7404 7405 if (a2dp->exist) 7406 divide_cnt = 3; 7407 else 7408 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 7409 7410 if (c_begin > c_end) 7411 return; 7412 7413 for (cycle = c_begin; cycle <= c_end; cycle++) { 7414 cnt++; 7415 store_index = ((cycle - 1) % slot_pair) * 2; 7416 7417 if (cnt % divide_cnt == 1) 7418 seq_printf(m, " %-15s : ", "[cycle_step]"); 7419 7420 seq_printf(m, "->b%02d", 7421 le16_to_cpu(pcysta->slot_step_time[store_index])); 7422 if (a2dp->exist) { 7423 a2dp_trx = &pcysta->a2dp_trx[store_index]; 7424 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7425 a2dp_trx->empty_cnt, 7426 a2dp_trx->retry_cnt, 7427 a2dp_trx->tx_rate ? 3 : 2, 7428 a2dp_trx->tx_cnt, 7429 a2dp_trx->ack_cnt, 7430 a2dp_trx->nack_cnt); 7431 } 7432 seq_printf(m, "->w%02d", 7433 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 7434 if (a2dp->exist) { 7435 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 7436 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 7437 a2dp_trx->empty_cnt, 7438 a2dp_trx->retry_cnt, 7439 a2dp_trx->tx_rate ? 3 : 2, 7440 a2dp_trx->tx_cnt, 7441 a2dp_trx->ack_cnt, 7442 a2dp_trx->nack_cnt); 7443 } 7444 if (cnt % divide_cnt == 0 || cnt == c_end) 7445 seq_puts(m, "\n"); 7446 } 7447 7448 if (a2dp->exist) { 7449 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d", 7450 "[a2dp_t_sta]", 7451 le16_to_cpu(pcysta->a2dp_ept.cnt), 7452 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 7453 7454 seq_printf(m, ", avg_t:%d, max_t:%d", 7455 le16_to_cpu(pcysta->a2dp_ept.tavg), 7456 le16_to_cpu(pcysta->a2dp_ept.tmax)); 7457 7458 seq_puts(m, "\n"); 7459 } 7460 } 7461 7462 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m) 7463 { 7464 struct rtw89_btc *btc = &rtwdev->btc; 7465 const struct rtw89_btc_ver *ver = btc->ver; 7466 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7467 struct rtw89_btc_rpt_cmn_info *pcinfo; 7468 union rtw89_btc_fbtc_cynullsta_info *ns; 7469 u8 i = 0; 7470 7471 if (!btc->dm.tdma_now.rxflctrl) 7472 return; 7473 7474 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 7475 if (!pcinfo->valid) 7476 return; 7477 7478 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 7479 if (ver->fcxnullsta == 1) { 7480 for (i = 0; i < 2; i++) { 7481 seq_printf(m, " %-15s : ", "[NULL-STA]"); 7482 seq_printf(m, "null-%d", i); 7483 seq_printf(m, "[ok:%d/", 7484 le32_to_cpu(ns->v1.result[i][1])); 7485 seq_printf(m, "fail:%d/", 7486 le32_to_cpu(ns->v1.result[i][0])); 7487 seq_printf(m, "on_time:%d/", 7488 le32_to_cpu(ns->v1.result[i][2])); 7489 seq_printf(m, "retry:%d/", 7490 le32_to_cpu(ns->v1.result[i][3])); 7491 seq_printf(m, "avg_t:%d.%03d/", 7492 le32_to_cpu(ns->v1.avg_t[i]) / 1000, 7493 le32_to_cpu(ns->v1.avg_t[i]) % 1000); 7494 seq_printf(m, "max_t:%d.%03d]\n", 7495 le32_to_cpu(ns->v1.max_t[i]) / 1000, 7496 le32_to_cpu(ns->v1.max_t[i]) % 1000); 7497 } 7498 } else { 7499 for (i = 0; i < 2; i++) { 7500 seq_printf(m, " %-15s : ", "[NULL-STA]"); 7501 seq_printf(m, "null-%d", i); 7502 seq_printf(m, "[Tx:%d/", 7503 le32_to_cpu(ns->v2.result[i][4])); 7504 seq_printf(m, "[ok:%d/", 7505 le32_to_cpu(ns->v2.result[i][1])); 7506 seq_printf(m, "fail:%d/", 7507 le32_to_cpu(ns->v2.result[i][0])); 7508 seq_printf(m, "on_time:%d/", 7509 le32_to_cpu(ns->v2.result[i][2])); 7510 seq_printf(m, "retry:%d/", 7511 le32_to_cpu(ns->v2.result[i][3])); 7512 seq_printf(m, "avg_t:%d.%03d/", 7513 le32_to_cpu(ns->v2.avg_t[i]) / 1000, 7514 le32_to_cpu(ns->v2.avg_t[i]) % 1000); 7515 seq_printf(m, "max_t:%d.%03d]\n", 7516 le32_to_cpu(ns->v2.max_t[i]) / 1000, 7517 le32_to_cpu(ns->v2.max_t[i]) % 1000); 7518 } 7519 } 7520 } 7521 7522 static void _show_fbtc_step_v2(struct rtw89_dev *rtwdev, struct seq_file *m) 7523 { 7524 struct rtw89_btc *btc = &rtwdev->btc; 7525 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7526 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 7527 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL; 7528 u8 type, val, cnt = 0, state = 0; 7529 bool outloop = false; 7530 u16 i, diff_t, n_start = 0, n_stop = 0; 7531 u16 pos_old, pos_new; 7532 7533 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 7534 if (!pcinfo->valid) 7535 return; 7536 7537 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2; 7538 pos_old = le16_to_cpu(pstep->pos_old); 7539 pos_new = le16_to_cpu(pstep->pos_new); 7540 7541 if (pcinfo->req_fver != pstep->fver) 7542 return; 7543 7544 /* store step info by using ring instead of FIFO*/ 7545 do { 7546 switch (state) { 7547 case 0: 7548 n_start = pos_old; 7549 if (pos_new >= pos_old) 7550 n_stop = pos_new; 7551 else 7552 n_stop = btc->ctrl.trace_step - 1; 7553 7554 state = 1; 7555 break; 7556 case 1: 7557 for (i = n_start; i <= n_stop; i++) { 7558 type = pstep->step[i].type; 7559 val = pstep->step[i].val; 7560 diff_t = le16_to_cpu(pstep->step[i].difft); 7561 7562 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 7563 continue; 7564 7565 if (cnt % 10 == 0) 7566 seq_printf(m, " %-15s : ", "[steps]"); 7567 7568 seq_printf(m, "-> %s(%02d)(%02d)", 7569 (type == CXSTEP_SLOT ? "SLT" : 7570 "EVT"), (u32)val, diff_t); 7571 if (cnt % 10 == 9) 7572 seq_puts(m, "\n"); 7573 cnt++; 7574 } 7575 7576 state = 2; 7577 break; 7578 case 2: 7579 if (pos_new < pos_old && n_start != 0) { 7580 n_start = 0; 7581 n_stop = pos_new; 7582 state = 1; 7583 } else { 7584 outloop = true; 7585 } 7586 break; 7587 } 7588 } while (!outloop); 7589 } 7590 7591 static void _show_fbtc_step_v3(struct rtw89_dev *rtwdev, struct seq_file *m) 7592 { 7593 struct rtw89_btc *btc = &rtwdev->btc; 7594 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7595 struct rtw89_btc_rpt_cmn_info *pcinfo; 7596 struct rtw89_btc_fbtc_steps_v3 *pstep; 7597 u32 i, n_begin, n_end, array_idx, cnt = 0; 7598 u8 type, val; 7599 u16 diff_t; 7600 7601 if ((pfwinfo->rpt_en_map & 7602 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0) 7603 return; 7604 7605 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 7606 if (!pcinfo->valid) 7607 return; 7608 7609 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3; 7610 if (pcinfo->req_fver != pstep->fver) 7611 return; 7612 7613 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP) 7614 n_begin = 1; 7615 else 7616 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1; 7617 7618 n_end = le32_to_cpu(pstep->cnt); 7619 7620 if (n_begin > n_end) 7621 return; 7622 7623 /* restore step info by using ring instead of FIFO */ 7624 for (i = n_begin; i <= n_end; i++) { 7625 array_idx = (i - 1) % FCXDEF_STEP; 7626 type = pstep->step[array_idx].type; 7627 val = pstep->step[array_idx].val; 7628 diff_t = le16_to_cpu(pstep->step[array_idx].difft); 7629 7630 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 7631 continue; 7632 7633 if (cnt % 10 == 0) 7634 seq_printf(m, " %-15s : ", "[steps]"); 7635 7636 seq_printf(m, "-> %s(%02d)", 7637 (type == CXSTEP_SLOT ? 7638 id_to_slot((u32)val) : 7639 id_to_evt((u32)val)), diff_t); 7640 7641 if (cnt % 10 == 9) 7642 seq_puts(m, "\n"); 7643 7644 cnt++; 7645 } 7646 } 7647 7648 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m) 7649 { 7650 struct rtw89_btc *btc = &rtwdev->btc; 7651 const struct rtw89_btc_ver *ver = btc->ver; 7652 7653 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 7654 return; 7655 7656 _show_error(rtwdev, m); 7657 _show_fbtc_tdma(rtwdev, m); 7658 _show_fbtc_slots(rtwdev, m); 7659 7660 if (ver->fcxcysta == 2) 7661 _show_fbtc_cysta_v2(rtwdev, m); 7662 else if (ver->fcxcysta == 3) 7663 _show_fbtc_cysta_v3(rtwdev, m); 7664 else if (ver->fcxcysta == 4) 7665 _show_fbtc_cysta_v4(rtwdev, m); 7666 else if (ver->fcxcysta == 5) 7667 _show_fbtc_cysta_v5(rtwdev, m); 7668 7669 _show_fbtc_nullsta(rtwdev, m); 7670 7671 if (ver->fcxstep == 2) 7672 _show_fbtc_step_v2(rtwdev, m); 7673 else if (ver->fcxstep == 3) 7674 _show_fbtc_step_v3(rtwdev, m); 7675 7676 } 7677 7678 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 7679 { 7680 const struct rtw89_chip_info *chip = rtwdev->chip; 7681 struct rtw89_mac_ax_gnt *gnt; 7682 u32 val, status; 7683 7684 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B) { 7685 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 7686 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 7687 7688 gnt = &gnt_cfg->band[0]; 7689 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 7690 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 7691 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 7692 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 7693 7694 gnt = &gnt_cfg->band[1]; 7695 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 7696 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 7697 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 7698 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 7699 } else if (chip->chip_id == RTL8852C) { 7700 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 7701 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 7702 7703 gnt = &gnt_cfg->band[0]; 7704 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 7705 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 7706 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 7707 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 7708 7709 gnt = &gnt_cfg->band[1]; 7710 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 7711 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 7712 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 7713 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 7714 } else { 7715 return; 7716 } 7717 } 7718 7719 static void _show_mreg_v1(struct rtw89_dev *rtwdev, struct seq_file *m) 7720 { 7721 const struct rtw89_chip_info *chip = rtwdev->chip; 7722 struct rtw89_btc *btc = &rtwdev->btc; 7723 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7724 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 7725 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL; 7726 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 7727 struct rtw89_btc_cx *cx = &btc->cx; 7728 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7729 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7730 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 7731 struct rtw89_mac_ax_gnt gnt; 7732 u8 i = 0, type = 0, cnt = 0; 7733 u32 val, offset; 7734 7735 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 7736 return; 7737 7738 seq_puts(m, "========== [HW Status] ==========\n"); 7739 7740 seq_printf(m, 7741 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 7742 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 7743 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 7744 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 7745 7746 /* To avoid I/O if WL LPS or power-off */ 7747 if (!wl->status.map.lps && !wl->status.map.rf_off) { 7748 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 7749 7750 _get_gnt(rtwdev, &gnt_cfg); 7751 gnt = gnt_cfg.band[0]; 7752 seq_printf(m, 7753 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 7754 "[gnt_status]", 7755 chip->chip_id == RTL8852C ? "HW" : 7756 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 7757 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 7758 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 7759 7760 gnt = gnt_cfg.band[1]; 7761 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 7762 gnt.gnt_wl_sw_en ? "SW" : "HW", 7763 gnt.gnt_wl, 7764 gnt.gnt_bt_sw_en ? "SW" : "HW", 7765 gnt.gnt_bt); 7766 } 7767 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 7768 if (!pcinfo->valid) { 7769 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7770 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 7771 __func__); 7772 return; 7773 } 7774 7775 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 7776 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7777 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 7778 __func__, pmreg->reg_num); 7779 7780 for (i = 0; i < pmreg->reg_num; i++) { 7781 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 7782 offset = le32_to_cpu(chip->mon_reg[i].offset); 7783 val = le32_to_cpu(pmreg->mreg_val[i]); 7784 7785 if (cnt % 6 == 0) 7786 seq_printf(m, " %-15s : %d_0x%04x=0x%08x", 7787 "[reg]", (u32)type, offset, val); 7788 else 7789 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type, 7790 offset, val); 7791 if (cnt % 6 == 5) 7792 seq_puts(m, "\n"); 7793 cnt++; 7794 7795 if (i >= pmreg->reg_num) 7796 seq_puts(m, "\n"); 7797 } 7798 7799 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 7800 if (!pcinfo->valid) { 7801 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7802 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 7803 __func__); 7804 seq_puts(m, "\n"); 7805 return; 7806 } 7807 7808 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 7809 if (!gdbg->en_map) 7810 return; 7811 7812 seq_printf(m, " %-15s : enable_map:0x%08x", 7813 "[gpio_dbg]", gdbg->en_map); 7814 7815 for (i = 0; i < BTC_DBG_MAX1; i++) { 7816 if (!(gdbg->en_map & BIT(i))) 7817 continue; 7818 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]); 7819 } 7820 seq_puts(m, "\n"); 7821 } 7822 7823 static void _show_mreg_v2(struct rtw89_dev *rtwdev, struct seq_file *m) 7824 { 7825 const struct rtw89_chip_info *chip = rtwdev->chip; 7826 struct rtw89_btc *btc = &rtwdev->btc; 7827 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7828 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 7829 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL; 7830 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 7831 struct rtw89_btc_cx *cx = &btc->cx; 7832 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7833 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7834 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 7835 struct rtw89_mac_ax_gnt gnt; 7836 u8 i = 0, type = 0, cnt = 0; 7837 u32 val, offset; 7838 7839 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 7840 return; 7841 7842 seq_puts(m, "========== [HW Status] ==========\n"); 7843 7844 seq_printf(m, 7845 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 7846 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 7847 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 7848 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 7849 7850 /* To avoid I/O if WL LPS or power-off */ 7851 if (!wl->status.map.lps && !wl->status.map.rf_off) { 7852 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 7853 7854 _get_gnt(rtwdev, &gnt_cfg); 7855 gnt = gnt_cfg.band[0]; 7856 seq_printf(m, 7857 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 7858 "[gnt_status]", 7859 chip->chip_id == RTL8852C ? "HW" : 7860 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 7861 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 7862 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 7863 7864 gnt = gnt_cfg.band[1]; 7865 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 7866 gnt.gnt_wl_sw_en ? "SW" : "HW", 7867 gnt.gnt_wl, 7868 gnt.gnt_bt_sw_en ? "SW" : "HW", 7869 gnt.gnt_bt); 7870 } 7871 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 7872 if (!pcinfo->valid) { 7873 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7874 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 7875 __func__); 7876 return; 7877 } 7878 7879 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 7880 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7881 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 7882 __func__, pmreg->reg_num); 7883 7884 for (i = 0; i < pmreg->reg_num; i++) { 7885 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 7886 offset = le32_to_cpu(chip->mon_reg[i].offset); 7887 val = le32_to_cpu(pmreg->mreg_val[i]); 7888 7889 if (cnt % 6 == 0) 7890 seq_printf(m, " %-15s : %d_0x%04x=0x%08x", 7891 "[reg]", (u32)type, offset, val); 7892 else 7893 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type, 7894 offset, val); 7895 if (cnt % 6 == 5) 7896 seq_puts(m, "\n"); 7897 cnt++; 7898 7899 if (i >= pmreg->reg_num) 7900 seq_puts(m, "\n"); 7901 } 7902 7903 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 7904 if (!pcinfo->valid) { 7905 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7906 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 7907 __func__); 7908 seq_puts(m, "\n"); 7909 return; 7910 } 7911 7912 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 7913 if (!gdbg->en_map) 7914 return; 7915 7916 seq_printf(m, " %-15s : enable_map:0x%08x", 7917 "[gpio_dbg]", gdbg->en_map); 7918 7919 for (i = 0; i < BTC_DBG_MAX1; i++) { 7920 if (!(gdbg->en_map & BIT(i))) 7921 continue; 7922 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]); 7923 } 7924 seq_puts(m, "\n"); 7925 } 7926 7927 static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m) 7928 { 7929 struct rtw89_btc *btc = &rtwdev->btc; 7930 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 7931 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 7932 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL; 7933 struct rtw89_btc_cx *cx = &btc->cx; 7934 struct rtw89_btc_dm *dm = &btc->dm; 7935 struct rtw89_btc_wl_info *wl = &cx->wl; 7936 struct rtw89_btc_bt_info *bt = &cx->bt; 7937 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 7938 u8 i; 7939 7940 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 7941 return; 7942 7943 seq_puts(m, "========== [Statistics] ==========\n"); 7944 7945 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 7946 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 7947 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1; 7948 7949 seq_printf(m, 7950 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 7951 "[summary]", pfwinfo->cnt_h2c, 7952 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 7953 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 7954 7955 seq_printf(m, 7956 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 7957 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt, 7958 prptctrl->rpt_enable, dm->error.val); 7959 7960 if (dm->error.map.wl_fw_hang) 7961 seq_puts(m, " (WL FW Hang!!)"); 7962 seq_puts(m, "\n"); 7963 seq_printf(m, 7964 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 7965 "[mailbox]", prptctrl->mb_send_ok_cnt, 7966 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt); 7967 7968 seq_printf(m, 7969 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 7970 prptctrl->mb_a2dp_empty_cnt, 7971 prptctrl->mb_a2dp_flct_cnt, 7972 prptctrl->mb_a2dp_full_cnt); 7973 7974 seq_printf(m, 7975 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 7976 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 7977 cx->cnt_wl[BTC_WCNT_RFK_GO], 7978 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 7979 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 7980 7981 seq_printf(m, 7982 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 7983 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 7984 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 7985 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 7986 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 7987 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 7988 7989 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 7990 bt->rfk_info.map.timeout = 1; 7991 else 7992 bt->rfk_info.map.timeout = 0; 7993 7994 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 7995 } else { 7996 seq_printf(m, 7997 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 7998 "[summary]", pfwinfo->cnt_h2c, 7999 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 8000 pfwinfo->event[BTF_EVNT_RPT], 8001 btc->fwinfo.rpt_en_map); 8002 seq_puts(m, " (WL FW report invalid!!)\n"); 8003 } 8004 8005 for (i = 0; i < BTC_NCNT_NUM; i++) 8006 cnt_sum += dm->cnt_notify[i]; 8007 8008 seq_printf(m, 8009 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8010 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8011 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8012 8013 seq_printf(m, 8014 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 8015 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8016 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8017 cnt[BTC_NCNT_WL_STA]); 8018 8019 seq_printf(m, 8020 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8021 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 8022 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 8023 cnt[BTC_NCNT_SPECIAL_PACKET]); 8024 8025 seq_printf(m, 8026 "timer=%d, control=%d, customerize=%d\n", 8027 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8028 cnt[BTC_NCNT_CUSTOMERIZE]); 8029 } 8030 8031 static void _show_summary_v4(struct rtw89_dev *rtwdev, struct seq_file *m) 8032 { 8033 struct rtw89_btc *btc = &rtwdev->btc; 8034 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8035 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl; 8036 struct rtw89_btc_rpt_cmn_info *pcinfo; 8037 struct rtw89_btc_cx *cx = &btc->cx; 8038 struct rtw89_btc_dm *dm = &btc->dm; 8039 struct rtw89_btc_wl_info *wl = &cx->wl; 8040 struct rtw89_btc_bt_info *bt = &cx->bt; 8041 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8042 u8 i; 8043 8044 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8045 return; 8046 8047 seq_puts(m, "========== [Statistics] ==========\n"); 8048 8049 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8050 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8051 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4; 8052 8053 seq_printf(m, 8054 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 8055 "[summary]", pfwinfo->cnt_h2c, 8056 pfwinfo->cnt_h2c_fail, 8057 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 8058 pfwinfo->cnt_c2h, 8059 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 8060 8061 seq_printf(m, 8062 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 8063 pfwinfo->event[BTF_EVNT_RPT], 8064 le32_to_cpu(prptctrl->rpt_info.cnt), 8065 le32_to_cpu(prptctrl->rpt_info.en), 8066 dm->error.val); 8067 8068 if (dm->error.map.wl_fw_hang) 8069 seq_puts(m, " (WL FW Hang!!)"); 8070 seq_puts(m, "\n"); 8071 seq_printf(m, 8072 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 8073 "[mailbox]", 8074 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 8075 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 8076 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 8077 8078 seq_printf(m, 8079 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 8080 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 8081 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 8082 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 8083 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 8084 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 8085 8086 seq_printf(m, 8087 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 8088 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8089 cx->cnt_wl[BTC_WCNT_RFK_GO], 8090 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8091 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8092 8093 seq_printf(m, 8094 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 8095 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 8096 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 8097 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 8098 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 8099 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 8100 8101 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 8102 bt->rfk_info.map.timeout = 1; 8103 else 8104 bt->rfk_info.map.timeout = 0; 8105 8106 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 8107 } else { 8108 seq_printf(m, 8109 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 8110 "[summary]", pfwinfo->cnt_h2c, 8111 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 8112 pfwinfo->event[BTF_EVNT_RPT], 8113 btc->fwinfo.rpt_en_map); 8114 seq_puts(m, " (WL FW report invalid!!)\n"); 8115 } 8116 8117 for (i = 0; i < BTC_NCNT_NUM; i++) 8118 cnt_sum += dm->cnt_notify[i]; 8119 8120 seq_printf(m, 8121 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8122 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8123 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8124 8125 seq_printf(m, 8126 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 8127 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8128 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8129 cnt[BTC_NCNT_WL_STA]); 8130 8131 seq_printf(m, 8132 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8133 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 8134 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 8135 cnt[BTC_NCNT_SPECIAL_PACKET]); 8136 8137 seq_printf(m, 8138 "timer=%d, control=%d, customerize=%d\n", 8139 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8140 cnt[BTC_NCNT_CUSTOMERIZE]); 8141 } 8142 8143 static void _show_summary_v5(struct rtw89_dev *rtwdev, struct seq_file *m) 8144 { 8145 struct rtw89_btc *btc = &rtwdev->btc; 8146 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8147 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl; 8148 struct rtw89_btc_rpt_cmn_info *pcinfo; 8149 struct rtw89_btc_cx *cx = &btc->cx; 8150 struct rtw89_btc_dm *dm = &btc->dm; 8151 struct rtw89_btc_wl_info *wl = &cx->wl; 8152 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8153 u8 i; 8154 8155 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8156 return; 8157 8158 seq_puts(m, "========== [Statistics] ==========\n"); 8159 8160 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8161 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8162 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5; 8163 8164 seq_printf(m, 8165 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 8166 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 8167 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 8168 pfwinfo->cnt_c2h, 8169 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 8170 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 8171 8172 seq_printf(m, 8173 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 8174 pfwinfo->event[BTF_EVNT_RPT], 8175 le16_to_cpu(prptctrl->rpt_info.cnt), 8176 le32_to_cpu(prptctrl->rpt_info.en)); 8177 8178 if (dm->error.map.wl_fw_hang) 8179 seq_puts(m, " (WL FW Hang!!)"); 8180 seq_puts(m, "\n"); 8181 seq_printf(m, 8182 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 8183 "[mailbox]", 8184 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 8185 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 8186 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 8187 8188 seq_printf(m, 8189 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 8190 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 8191 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 8192 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 8193 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 8194 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 8195 8196 seq_printf(m, 8197 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 8198 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8199 cx->cnt_wl[BTC_WCNT_RFK_GO], 8200 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8201 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8202 8203 seq_printf(m, 8204 ", bt_rfk[req:%d]", 8205 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 8206 8207 seq_printf(m, 8208 ", AOAC[RF_on:%d/RF_off:%d]", 8209 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 8210 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 8211 } else { 8212 seq_printf(m, 8213 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 8214 "[summary]", pfwinfo->cnt_h2c, 8215 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 8216 } 8217 8218 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 8219 pfwinfo->err[BTFRE_EXCEPTION]) { 8220 seq_puts(m, "\n"); 8221 seq_printf(m, 8222 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 8223 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 8224 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 8225 pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION], 8226 wl->status.map.lps, wl->status.map.rf_off); 8227 } 8228 8229 for (i = 0; i < BTC_NCNT_NUM; i++) 8230 cnt_sum += dm->cnt_notify[i]; 8231 8232 seq_puts(m, "\n"); 8233 seq_printf(m, 8234 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8235 "[notify_cnt]", 8236 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8237 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8238 8239 seq_printf(m, 8240 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 8241 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8242 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8243 cnt[BTC_NCNT_WL_STA]); 8244 8245 seq_puts(m, "\n"); 8246 seq_printf(m, 8247 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8248 "[notify_cnt]", 8249 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 8250 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]); 8251 8252 seq_printf(m, 8253 "timer=%d, control=%d, customerize=%d", 8254 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8255 cnt[BTC_NCNT_CUSTOMERIZE]); 8256 } 8257 8258 static void _show_summary_v105(struct rtw89_dev *rtwdev, struct seq_file *m) 8259 { 8260 struct rtw89_btc *btc = &rtwdev->btc; 8261 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8262 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl; 8263 struct rtw89_btc_rpt_cmn_info *pcinfo; 8264 struct rtw89_btc_cx *cx = &btc->cx; 8265 struct rtw89_btc_dm *dm = &btc->dm; 8266 struct rtw89_btc_wl_info *wl = &cx->wl; 8267 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 8268 u8 i; 8269 8270 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 8271 return; 8272 8273 seq_puts(m, "========== [Statistics] ==========\n"); 8274 8275 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 8276 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 8277 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105; 8278 8279 seq_printf(m, 8280 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 8281 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 8282 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 8283 pfwinfo->cnt_c2h, 8284 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 8285 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 8286 8287 seq_printf(m, 8288 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 8289 pfwinfo->event[BTF_EVNT_RPT], 8290 le16_to_cpu(prptctrl->rpt_info.cnt), 8291 le32_to_cpu(prptctrl->rpt_info.en)); 8292 8293 if (dm->error.map.wl_fw_hang) 8294 seq_puts(m, " (WL FW Hang!!)"); 8295 seq_puts(m, "\n"); 8296 seq_printf(m, 8297 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 8298 "[mailbox]", 8299 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 8300 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 8301 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 8302 8303 seq_printf(m, 8304 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 8305 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 8306 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 8307 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 8308 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 8309 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 8310 8311 seq_printf(m, 8312 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 8313 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 8314 cx->cnt_wl[BTC_WCNT_RFK_GO], 8315 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 8316 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 8317 8318 seq_printf(m, 8319 ", bt_rfk[req:%d]", 8320 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 8321 8322 seq_printf(m, 8323 ", AOAC[RF_on:%d/RF_off:%d]", 8324 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 8325 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 8326 } else { 8327 seq_printf(m, 8328 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 8329 "[summary]", pfwinfo->cnt_h2c, 8330 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 8331 } 8332 8333 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 8334 pfwinfo->err[BTFRE_EXCEPTION]) { 8335 seq_puts(m, "\n"); 8336 seq_printf(m, 8337 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 8338 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 8339 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 8340 pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION], 8341 wl->status.map.lps, wl->status.map.rf_off); 8342 } 8343 8344 for (i = 0; i < BTC_NCNT_NUM; i++) 8345 cnt_sum += dm->cnt_notify[i]; 8346 8347 seq_puts(m, "\n"); 8348 seq_printf(m, 8349 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 8350 "[notify_cnt]", 8351 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 8352 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 8353 8354 seq_printf(m, 8355 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 8356 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 8357 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 8358 cnt[BTC_NCNT_WL_STA]); 8359 8360 seq_puts(m, "\n"); 8361 seq_printf(m, 8362 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 8363 "[notify_cnt]", 8364 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 8365 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]); 8366 8367 seq_printf(m, 8368 "timer=%d, control=%d, customerize=%d", 8369 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 8370 cnt[BTC_NCNT_CUSTOMERIZE]); 8371 } 8372 8373 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m) 8374 { 8375 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal; 8376 struct rtw89_btc *btc = &rtwdev->btc; 8377 const struct rtw89_btc_ver *ver = btc->ver; 8378 struct rtw89_btc_cx *cx = &btc->cx; 8379 struct rtw89_btc_bt_info *bt = &cx->bt; 8380 8381 seq_puts(m, "=========================================\n"); 8382 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n", 8383 fw_suit->major_ver, fw_suit->minor_ver, 8384 fw_suit->sub_ver, fw_suit->sub_idex); 8385 seq_printf(m, "manual %d\n", btc->ctrl.manual); 8386 8387 seq_puts(m, "=========================================\n"); 8388 8389 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)", 8390 "[bt_info]", 8391 bt->raw_info[2], bt->raw_info[3], 8392 bt->raw_info[4], bt->raw_info[5], 8393 bt->raw_info[6], bt->raw_info[7], 8394 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 8395 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 8396 cx->cnt_bt[BTC_BCNT_INFOSAME]); 8397 8398 seq_puts(m, "\n=========================================\n"); 8399 8400 _show_cx_info(rtwdev, m); 8401 _show_wl_info(rtwdev, m); 8402 _show_bt_info(rtwdev, m); 8403 _show_dm_info(rtwdev, m); 8404 _show_fw_dm_msg(rtwdev, m); 8405 8406 if (ver->fcxmreg == 1) 8407 _show_mreg_v1(rtwdev, m); 8408 else if (ver->fcxmreg == 2) 8409 _show_mreg_v2(rtwdev, m); 8410 8411 if (ver->fcxbtcrpt == 1) 8412 _show_summary_v1(rtwdev, m); 8413 else if (ver->fcxbtcrpt == 4) 8414 _show_summary_v4(rtwdev, m); 8415 else if (ver->fcxbtcrpt == 5) 8416 _show_summary_v5(rtwdev, m); 8417 else if (ver->fcxbtcrpt == 105) 8418 _show_summary_v105(rtwdev, m); 8419 } 8420 8421 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) 8422 { 8423 const struct rtw89_chip_info *chip = rtwdev->chip; 8424 struct rtw89_btc *btc = &rtwdev->btc; 8425 const struct rtw89_btc_ver *btc_ver_def; 8426 const struct rtw89_fw_suit *fw_suit; 8427 u32 suit_ver_code; 8428 int i; 8429 8430 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); 8431 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); 8432 8433 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) { 8434 btc_ver_def = &rtw89_btc_ver_defs[i]; 8435 8436 if (chip->chip_id != btc_ver_def->chip_id) 8437 continue; 8438 8439 if (suit_ver_code >= btc_ver_def->fw_ver_code) { 8440 btc->ver = btc_ver_def; 8441 goto out; 8442 } 8443 } 8444 8445 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX]; 8446 8447 out: 8448 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", 8449 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); 8450 } 8451