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