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