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