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