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