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