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_rf_trx_para para; 1813 u32 wl_stb_chg = 0; 1814 u8 level_id = 0; 1815 1816 if (!dm->freerun) { 1817 dm->trx_para_level = 0; 1818 chip->ops->btc_bt_aci_imp(rtwdev); 1819 } 1820 1821 level_id = (u8)dm->trx_para_level; 1822 1823 if (level_id >= chip->rf_para_dlink_num || 1824 level_id >= chip->rf_para_ulink_num) { 1825 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1826 "[BTC], %s(): invalid level_id: %d\n", 1827 __func__, level_id); 1828 return; 1829 } 1830 1831 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 1832 para = chip->rf_para_ulink[level_id]; 1833 else 1834 para = chip->rf_para_dlink[level_id]; 1835 1836 if (para.wl_tx_power != RTW89_BTC_WL_DEF_TX_PWR) 1837 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1838 "[BTC], %s(): wl_tx_power=%d\n", 1839 __func__, para.wl_tx_power); 1840 _set_wl_tx_power(rtwdev, para.wl_tx_power); 1841 _set_wl_rx_gain(rtwdev, para.wl_rx_gain); 1842 _set_bt_tx_power(rtwdev, para.bt_tx_power); 1843 _set_bt_rx_gain(rtwdev, para.bt_rx_gain); 1844 1845 if (bt->enable.now == 0 || wl->status.map.rf_off == 1 || 1846 wl->status.map.lps == BTC_LPS_RF_OFF) 1847 wl_stb_chg = 0; 1848 else 1849 wl_stb_chg = 1; 1850 1851 if (wl_stb_chg != dm->wl_stb_chg) { 1852 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1853 "[BTC], %s(): wl_stb_chg=%d\n", 1854 __func__, wl_stb_chg); 1855 dm->wl_stb_chg = wl_stb_chg; 1856 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 1857 } 1858 } 1859 1860 static void _update_btc_state_map(struct rtw89_dev *rtwdev) 1861 { 1862 struct rtw89_btc *btc = &rtwdev->btc; 1863 struct rtw89_btc_cx *cx = &btc->cx; 1864 struct rtw89_btc_wl_info *wl = &cx->wl; 1865 struct rtw89_btc_bt_info *bt = &cx->bt; 1866 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 1867 1868 if (wl->status.map.connecting || wl->status.map._4way || 1869 wl->status.map.roaming) { 1870 cx->state_map = BTC_WLINKING; 1871 } else if (wl->status.map.scan) { /* wl scan */ 1872 if (bt_linfo->status.map.inq_pag) 1873 cx->state_map = BTC_WSCAN_BSCAN; 1874 else 1875 cx->state_map = BTC_WSCAN_BNOSCAN; 1876 } else if (wl->status.map.busy) { /* only busy */ 1877 if (bt_linfo->status.map.inq_pag) 1878 cx->state_map = BTC_WBUSY_BSCAN; 1879 else 1880 cx->state_map = BTC_WBUSY_BNOSCAN; 1881 } else { /* wl idle */ 1882 cx->state_map = BTC_WIDLE; 1883 } 1884 } 1885 1886 static void _set_bt_afh_info(struct rtw89_dev *rtwdev) 1887 { 1888 const struct rtw89_chip_info *chip = rtwdev->chip; 1889 struct rtw89_btc *btc = &rtwdev->btc; 1890 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1891 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 1892 struct rtw89_btc_bt_link_info *b = &bt->link_info; 1893 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 1894 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 1895 struct rtw89_btc_wl_active_role *r; 1896 struct rtw89_btc_wl_active_role_v1 *r1; 1897 u8 en = 0, i, ch = 0, bw = 0; 1898 u8 mode, connect_cnt; 1899 1900 if (btc->ctrl.manual || wl->status.map.scan) 1901 return; 1902 1903 if (chip->chip_id == RTL8852A) { 1904 mode = wl_rinfo->link_mode; 1905 connect_cnt = wl_rinfo->connect_cnt; 1906 } else { 1907 mode = wl_rinfo_v1->link_mode; 1908 connect_cnt = wl_rinfo_v1->connect_cnt; 1909 } 1910 1911 if (wl->status.map.rf_off || bt->whql_test || 1912 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G || 1913 connect_cnt > BTC_TDMA_WLROLE_MAX) { 1914 en = false; 1915 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) { 1916 en = true; 1917 /* get p2p channel */ 1918 for (i = 0; i < RTW89_PORT_NUM; i++) { 1919 r = &wl_rinfo->active_role[i]; 1920 r1 = &wl_rinfo_v1->active_role_v1[i]; 1921 1922 if (chip->chip_id == RTL8852A && 1923 (r->role == RTW89_WIFI_ROLE_P2P_GO || 1924 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 1925 ch = r->ch; 1926 bw = r->bw; 1927 break; 1928 } else if (chip->chip_id != RTL8852A && 1929 (r1->role == RTW89_WIFI_ROLE_P2P_GO || 1930 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 1931 ch = r1->ch; 1932 bw = r1->bw; 1933 break; 1934 } 1935 } 1936 } else { 1937 en = true; 1938 /* get 2g channel */ 1939 for (i = 0; i < RTW89_PORT_NUM; i++) { 1940 r = &wl_rinfo->active_role[i]; 1941 r1 = &wl_rinfo_v1->active_role_v1[i]; 1942 1943 if (chip->chip_id == RTL8852A && 1944 r->connected && r->band == RTW89_BAND_2G) { 1945 ch = r->ch; 1946 bw = r->bw; 1947 break; 1948 } else if (chip->chip_id != RTL8852A && 1949 r1->connected && r1->band == RTW89_BAND_2G) { 1950 ch = r1->ch; 1951 bw = r1->bw; 1952 break; 1953 } 1954 } 1955 } 1956 1957 switch (bw) { 1958 case RTW89_CHANNEL_WIDTH_20: 1959 bw = 20 + chip->afh_guard_ch * 2; 1960 break; 1961 case RTW89_CHANNEL_WIDTH_40: 1962 bw = 40 + chip->afh_guard_ch * 2; 1963 break; 1964 case RTW89_CHANNEL_WIDTH_5: 1965 bw = 5 + chip->afh_guard_ch * 2; 1966 break; 1967 case RTW89_CHANNEL_WIDTH_10: 1968 bw = 10 + chip->afh_guard_ch * 2; 1969 break; 1970 default: 1971 bw = 0; 1972 en = false; /* turn off AFH info if BW > 40 */ 1973 break; 1974 } 1975 1976 if (wl->afh_info.en == en && 1977 wl->afh_info.ch == ch && 1978 wl->afh_info.bw == bw && 1979 b->profile_cnt.last == b->profile_cnt.now) { 1980 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1981 "[BTC], %s(): return because no change!\n", 1982 __func__); 1983 return; 1984 } 1985 1986 wl->afh_info.en = en; 1987 wl->afh_info.ch = ch; 1988 wl->afh_info.bw = bw; 1989 1990 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3); 1991 1992 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1993 "[BTC], %s(): en=%d, ch=%d, bw=%d\n", 1994 __func__, en, ch, bw); 1995 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; 1996 } 1997 1998 static bool _check_freerun(struct rtw89_dev *rtwdev) 1999 { 2000 struct rtw89_btc *btc = &rtwdev->btc; 2001 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2002 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 2003 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 2004 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 2005 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 2006 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc; 2007 2008 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 2009 btc->dm.trx_para_level = 0; 2010 return false; 2011 } 2012 2013 /* The below is dedicated antenna case */ 2014 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX || 2015 wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) { 2016 btc->dm.trx_para_level = 5; 2017 return true; 2018 } 2019 2020 if (bt_linfo->profile_cnt.now == 0) { 2021 btc->dm.trx_para_level = 5; 2022 return true; 2023 } 2024 2025 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) { 2026 btc->dm.trx_para_level = 5; 2027 return true; 2028 } 2029 2030 /* TODO get isolation by BT psd */ 2031 if (btc->mdinfo.ant.isolation >= BTC_FREERUN_ANTISO_MIN) { 2032 btc->dm.trx_para_level = 5; 2033 return true; 2034 } 2035 2036 if (!wl->status.map.busy) {/* wl idle -> freerun */ 2037 btc->dm.trx_para_level = 5; 2038 return true; 2039 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */ 2040 btc->dm.trx_para_level = 0; 2041 return false; 2042 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 2043 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) { 2044 btc->dm.trx_para_level = 6; 2045 return true; 2046 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) { 2047 btc->dm.trx_para_level = 7; 2048 return true; 2049 } 2050 btc->dm.trx_para_level = 0; 2051 return false; 2052 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) { 2053 if (bt_linfo->rssi > 28) { 2054 btc->dm.trx_para_level = 6; 2055 return true; 2056 } 2057 } 2058 2059 btc->dm.trx_para_level = 0; 2060 return false; 2061 } 2062 2063 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; }) 2064 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; }) 2065 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; }) 2066 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; }) 2067 2068 #define _slot_set(btc, sid, dura, tbl, type) \ 2069 do { \ 2070 typeof(sid) _sid = (sid); \ 2071 typeof(btc) _btc = (btc); \ 2072 _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\ 2073 _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \ 2074 _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \ 2075 } while (0) 2076 2077 #define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura) 2078 #define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl) 2079 #define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type) 2080 2081 struct btc_btinfo_lb2 { 2082 u8 connect: 1; 2083 u8 sco_busy: 1; 2084 u8 inq_pag: 1; 2085 u8 acl_busy: 1; 2086 u8 hfp: 1; 2087 u8 hid: 1; 2088 u8 a2dp: 1; 2089 u8 pan: 1; 2090 }; 2091 2092 struct btc_btinfo_lb3 { 2093 u8 retry: 4; 2094 u8 cqddr: 1; 2095 u8 inq: 1; 2096 u8 mesh_busy: 1; 2097 u8 pag: 1; 2098 }; 2099 2100 struct btc_btinfo_hb0 { 2101 s8 rssi; 2102 }; 2103 2104 struct btc_btinfo_hb1 { 2105 u8 ble_connect: 1; 2106 u8 reinit: 1; 2107 u8 relink: 1; 2108 u8 igno_wl: 1; 2109 u8 voice: 1; 2110 u8 ble_scan: 1; 2111 u8 role_sw: 1; 2112 u8 multi_link: 1; 2113 }; 2114 2115 struct btc_btinfo_hb2 { 2116 u8 pan_active: 1; 2117 u8 afh_update: 1; 2118 u8 a2dp_active: 1; 2119 u8 slave: 1; 2120 u8 hid_slot: 2; 2121 u8 hid_cnt: 2; 2122 }; 2123 2124 struct btc_btinfo_hb3 { 2125 u8 a2dp_bitpool: 6; 2126 u8 tx_3m: 1; 2127 u8 a2dp_sink: 1; 2128 }; 2129 2130 union btc_btinfo { 2131 u8 val; 2132 struct btc_btinfo_lb2 lb2; 2133 struct btc_btinfo_lb3 lb3; 2134 struct btc_btinfo_hb0 hb0; 2135 struct btc_btinfo_hb1 hb1; 2136 struct btc_btinfo_hb2 hb2; 2137 struct btc_btinfo_hb3 hb3; 2138 }; 2139 2140 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 2141 enum btc_reason_and_action action) 2142 { 2143 const struct rtw89_chip_info *chip = rtwdev->chip; 2144 2145 chip->ops->btc_set_policy(rtwdev, policy_type); 2146 _fw_set_policy(rtwdev, policy_type, action); 2147 } 2148 2149 #define BTC_B1_MAX 250 /* unit ms */ 2150 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type) 2151 { 2152 struct rtw89_btc *btc = &rtwdev->btc; 2153 struct rtw89_btc_dm *dm = &btc->dm; 2154 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 2155 struct rtw89_btc_fbtc_slot *s = dm->slot; 2156 u8 type; 2157 u32 tbl_w1, tbl_b1, tbl_b4; 2158 2159 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 2160 if (btc->cx.wl.status.map._4way) 2161 tbl_w1 = cxtbl[1]; 2162 else 2163 tbl_w1 = cxtbl[8]; 2164 tbl_b1 = cxtbl[3]; 2165 tbl_b4 = cxtbl[3]; 2166 } else { 2167 tbl_w1 = cxtbl[16]; 2168 tbl_b1 = cxtbl[17]; 2169 tbl_b4 = cxtbl[17]; 2170 } 2171 2172 type = (u8)((policy_type & BTC_CXP_MASK) >> 8); 2173 btc->bt_req_en = false; 2174 2175 switch (type) { 2176 case BTC_CXP_USERDEF0: 2177 *t = t_def[CXTD_OFF]; 2178 s[CXST_OFF] = s_def[CXST_OFF]; 2179 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2180 btc->update_policy_force = true; 2181 break; 2182 case BTC_CXP_OFF: /* TDMA off */ 2183 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2184 *t = t_def[CXTD_OFF]; 2185 s[CXST_OFF] = s_def[CXST_OFF]; 2186 2187 switch (policy_type) { 2188 case BTC_CXP_OFF_BT: 2189 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2190 break; 2191 case BTC_CXP_OFF_WL: 2192 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 2193 break; 2194 case BTC_CXP_OFF_EQ0: 2195 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 2196 break; 2197 case BTC_CXP_OFF_EQ1: 2198 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 2199 break; 2200 case BTC_CXP_OFF_EQ2: 2201 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 2202 break; 2203 case BTC_CXP_OFF_EQ3: 2204 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 2205 break; 2206 case BTC_CXP_OFF_BWB0: 2207 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 2208 break; 2209 case BTC_CXP_OFF_BWB1: 2210 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2211 break; 2212 case BTC_CXP_OFF_BWB3: 2213 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 2214 break; 2215 } 2216 break; 2217 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 2218 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2219 *t = t_def[CXTD_OFF_B2]; 2220 s[CXST_OFF] = s_def[CXST_OFF]; 2221 switch (policy_type) { 2222 case BTC_CXP_OFFB_BWB0: 2223 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2224 break; 2225 } 2226 break; 2227 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 2228 btc->bt_req_en = true; 2229 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2230 *t = t_def[CXTD_OFF_EXT]; 2231 switch (policy_type) { 2232 case BTC_CXP_OFFE_DEF: 2233 s[CXST_E2G] = s_def[CXST_E2G]; 2234 s[CXST_E5G] = s_def[CXST_E5G]; 2235 s[CXST_EBT] = s_def[CXST_EBT]; 2236 s[CXST_ENULL] = s_def[CXST_ENULL]; 2237 break; 2238 case BTC_CXP_OFFE_DEF2: 2239 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 2240 s[CXST_E5G] = s_def[CXST_E5G]; 2241 s[CXST_EBT] = s_def[CXST_EBT]; 2242 s[CXST_ENULL] = s_def[CXST_ENULL]; 2243 break; 2244 } 2245 break; 2246 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 2247 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2248 *t = t_def[CXTD_FIX]; 2249 switch (policy_type) { 2250 case BTC_CXP_FIX_TD3030: 2251 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2252 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2253 break; 2254 case BTC_CXP_FIX_TD5050: 2255 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2256 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2257 break; 2258 case BTC_CXP_FIX_TD2030: 2259 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2260 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2261 break; 2262 case BTC_CXP_FIX_TD4010: 2263 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 2264 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2265 break; 2266 case BTC_CXP_FIX_TD4020: 2267 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX); 2268 _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX); 2269 break; 2270 case BTC_CXP_FIX_TD7010: 2271 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 2272 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2273 break; 2274 case BTC_CXP_FIX_TD2060: 2275 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2276 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2277 break; 2278 case BTC_CXP_FIX_TD3060: 2279 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2280 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2281 break; 2282 case BTC_CXP_FIX_TD2080: 2283 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2284 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2285 break; 2286 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 2287 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2288 tbl_w1, SLOT_ISO); 2289 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2290 tbl_b1, SLOT_MIX); 2291 break; 2292 } 2293 break; 2294 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 2295 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2296 *t = t_def[CXTD_PFIX]; 2297 if (btc->cx.wl.role_info.role_map.role.ap) 2298 _tdma_set_flctrl(btc, CXFLC_QOSNULL); 2299 2300 switch (policy_type) { 2301 case BTC_CXP_PFIX_TD3030: 2302 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2303 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2304 break; 2305 case BTC_CXP_PFIX_TD5050: 2306 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2307 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2308 break; 2309 case BTC_CXP_PFIX_TD2030: 2310 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2311 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2312 break; 2313 case BTC_CXP_PFIX_TD2060: 2314 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2315 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2316 break; 2317 case BTC_CXP_PFIX_TD3070: 2318 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2319 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2320 break; 2321 case BTC_CXP_PFIX_TD2080: 2322 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2323 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2324 break; 2325 } 2326 break; 2327 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 2328 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2329 *t = t_def[CXTD_AUTO]; 2330 switch (policy_type) { 2331 case BTC_CXP_AUTO_TD50B1: 2332 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2333 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2334 break; 2335 case BTC_CXP_AUTO_TD60B1: 2336 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2337 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2338 break; 2339 case BTC_CXP_AUTO_TD20B1: 2340 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2341 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2342 break; 2343 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 2344 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2345 tbl_w1, SLOT_ISO); 2346 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2347 tbl_b1, SLOT_MIX); 2348 break; 2349 } 2350 break; 2351 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 2352 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2353 *t = t_def[CXTD_PAUTO]; 2354 switch (policy_type) { 2355 case BTC_CXP_PAUTO_TD50B1: 2356 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2357 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2358 break; 2359 case BTC_CXP_PAUTO_TD60B1: 2360 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2361 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2362 break; 2363 case BTC_CXP_PAUTO_TD20B1: 2364 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2365 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2366 break; 2367 case BTC_CXP_PAUTO_TDW1B1: 2368 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2369 tbl_w1, SLOT_ISO); 2370 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2371 tbl_b1, SLOT_MIX); 2372 break; 2373 } 2374 break; 2375 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 2376 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2377 *t = t_def[CXTD_AUTO2]; 2378 switch (policy_type) { 2379 case BTC_CXP_AUTO2_TD3050: 2380 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2381 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2382 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2383 break; 2384 case BTC_CXP_AUTO2_TD3070: 2385 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2386 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 2387 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2388 break; 2389 case BTC_CXP_AUTO2_TD5050: 2390 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2391 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2392 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2393 break; 2394 case BTC_CXP_AUTO2_TD6060: 2395 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2396 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 2397 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2398 break; 2399 case BTC_CXP_AUTO2_TD2080: 2400 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2401 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 2402 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2403 break; 2404 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 2405 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2406 tbl_w1, SLOT_ISO); 2407 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 2408 tbl_b4, SLOT_MIX); 2409 break; 2410 } 2411 break; 2412 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 2413 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2414 *t = t_def[CXTD_PAUTO2]; 2415 switch (policy_type) { 2416 case BTC_CXP_PAUTO2_TD3050: 2417 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2418 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2419 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2420 break; 2421 case BTC_CXP_PAUTO2_TD3070: 2422 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2423 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 2424 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2425 break; 2426 case BTC_CXP_PAUTO2_TD5050: 2427 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2428 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2429 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2430 break; 2431 case BTC_CXP_PAUTO2_TD6060: 2432 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2433 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 2434 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2435 break; 2436 case BTC_CXP_PAUTO2_TD2080: 2437 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2438 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 2439 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2440 break; 2441 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 2442 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2443 tbl_w1, SLOT_ISO); 2444 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 2445 tbl_b4, SLOT_MIX); 2446 break; 2447 } 2448 break; 2449 } 2450 } 2451 EXPORT_SYMBOL(rtw89_btc_set_policy); 2452 2453 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) 2454 { 2455 struct rtw89_btc *btc = &rtwdev->btc; 2456 struct rtw89_btc_dm *dm = &btc->dm; 2457 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 2458 struct rtw89_btc_fbtc_slot *s = dm->slot; 2459 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1; 2460 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc; 2461 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc; 2462 u8 type, null_role; 2463 u32 tbl_w1, tbl_b1, tbl_b4; 2464 2465 type = FIELD_GET(BTC_CXP_MASK, policy_type); 2466 2467 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 2468 if (btc->cx.wl.status.map._4way) 2469 tbl_w1 = cxtbl[1]; 2470 else if (hid->exist && hid->type == BTC_HID_218) 2471 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */ 2472 else 2473 tbl_w1 = cxtbl[8]; 2474 2475 if (dm->leak_ap && 2476 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) { 2477 tbl_b1 = cxtbl[3]; 2478 tbl_b4 = cxtbl[3]; 2479 } else if (hid->exist && hid->type == BTC_HID_218) { 2480 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */ 2481 tbl_b4 = cxtbl[4]; 2482 } else { 2483 tbl_b1 = cxtbl[2]; 2484 tbl_b4 = cxtbl[2]; 2485 } 2486 } else { 2487 tbl_w1 = cxtbl[16]; 2488 tbl_b1 = cxtbl[17]; 2489 tbl_b4 = cxtbl[17]; 2490 } 2491 2492 btc->bt_req_en = false; 2493 2494 switch (type) { 2495 case BTC_CXP_USERDEF0: 2496 btc->update_policy_force = true; 2497 *t = t_def[CXTD_OFF]; 2498 s[CXST_OFF] = s_def[CXST_OFF]; 2499 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2500 break; 2501 case BTC_CXP_OFF: /* TDMA off */ 2502 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2503 *t = t_def[CXTD_OFF]; 2504 s[CXST_OFF] = s_def[CXST_OFF]; 2505 2506 switch (policy_type) { 2507 case BTC_CXP_OFF_BT: 2508 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 2509 break; 2510 case BTC_CXP_OFF_WL: 2511 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 2512 break; 2513 case BTC_CXP_OFF_EQ0: 2514 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 2515 break; 2516 case BTC_CXP_OFF_EQ1: 2517 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 2518 break; 2519 case BTC_CXP_OFF_EQ2: 2520 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 2521 break; 2522 case BTC_CXP_OFF_EQ3: 2523 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 2524 break; 2525 case BTC_CXP_OFF_BWB0: 2526 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 2527 break; 2528 case BTC_CXP_OFF_BWB1: 2529 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2530 break; 2531 case BTC_CXP_OFF_BWB2: 2532 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 2533 break; 2534 case BTC_CXP_OFF_BWB3: 2535 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 2536 break; 2537 default: 2538 break; 2539 } 2540 break; 2541 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 2542 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 2543 *t = t_def[CXTD_OFF_B2]; 2544 s[CXST_OFF] = s_def[CXST_OFF]; 2545 2546 switch (policy_type) { 2547 case BTC_CXP_OFFB_BWB0: 2548 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 2549 break; 2550 default: 2551 break; 2552 } 2553 break; 2554 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 2555 btc->bt_req_en = true; 2556 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2557 *t = t_def[CXTD_OFF_EXT]; 2558 2559 /* To avoid wl-s0 tx break by hid/hfp tx */ 2560 if (hid->exist || hfp->exist) 2561 tbl_w1 = cxtbl[16]; 2562 2563 switch (policy_type) { 2564 case BTC_CXP_OFFE_DEF: 2565 s[CXST_E2G] = s_def[CXST_E2G]; 2566 s[CXST_E5G] = s_def[CXST_E5G]; 2567 s[CXST_EBT] = s_def[CXST_EBT]; 2568 s[CXST_ENULL] = s_def[CXST_ENULL]; 2569 break; 2570 case BTC_CXP_OFFE_DEF2: 2571 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 2572 s[CXST_E5G] = s_def[CXST_E5G]; 2573 s[CXST_EBT] = s_def[CXST_EBT]; 2574 s[CXST_ENULL] = s_def[CXST_ENULL]; 2575 break; 2576 default: 2577 break; 2578 } 2579 break; 2580 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 2581 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2582 *t = t_def[CXTD_FIX]; 2583 2584 switch (policy_type) { 2585 case BTC_CXP_FIX_TD3030: 2586 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2587 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2588 break; 2589 case BTC_CXP_FIX_TD5050: 2590 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2591 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2592 break; 2593 case BTC_CXP_FIX_TD2030: 2594 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2595 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2596 break; 2597 case BTC_CXP_FIX_TD4010: 2598 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 2599 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2600 break; 2601 case BTC_CXP_FIX_TD4010ISO: 2602 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 2603 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2604 break; 2605 case BTC_CXP_FIX_TD7010: 2606 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 2607 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 2608 break; 2609 case BTC_CXP_FIX_TD2060: 2610 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2611 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2612 break; 2613 case BTC_CXP_FIX_TD3060: 2614 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2615 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2616 break; 2617 case BTC_CXP_FIX_TD2080: 2618 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2619 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2620 break; 2621 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 2622 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2623 tbl_w1, SLOT_ISO); 2624 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2625 tbl_b1, SLOT_MIX); 2626 break; 2627 default: 2628 break; 2629 } 2630 break; 2631 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 2632 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2633 *t = t_def[CXTD_PFIX]; 2634 2635 switch (policy_type) { 2636 case BTC_CXP_PFIX_TD3030: 2637 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2638 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2639 break; 2640 case BTC_CXP_PFIX_TD5050: 2641 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2642 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 2643 break; 2644 case BTC_CXP_PFIX_TD2030: 2645 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2646 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 2647 break; 2648 case BTC_CXP_PFIX_TD2060: 2649 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2650 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2651 break; 2652 case BTC_CXP_PFIX_TD3070: 2653 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2654 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 2655 break; 2656 case BTC_CXP_PFIX_TD2080: 2657 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2658 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 2659 break; 2660 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */ 2661 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2662 tbl_w1, SLOT_ISO); 2663 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2664 tbl_b1, SLOT_MIX); 2665 break; 2666 default: 2667 break; 2668 } 2669 break; 2670 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 2671 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2672 *t = t_def[CXTD_AUTO]; 2673 2674 switch (policy_type) { 2675 case BTC_CXP_AUTO_TD50B1: 2676 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2677 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2678 break; 2679 case BTC_CXP_AUTO_TD60B1: 2680 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2681 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2682 break; 2683 case BTC_CXP_AUTO_TD20B1: 2684 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2685 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2686 break; 2687 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 2688 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2689 tbl_w1, SLOT_ISO); 2690 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2691 tbl_b1, SLOT_MIX); 2692 break; 2693 default: 2694 break; 2695 } 2696 break; 2697 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 2698 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2699 *t = t_def[CXTD_PAUTO]; 2700 2701 switch (policy_type) { 2702 case BTC_CXP_PAUTO_TD50B1: 2703 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2704 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2705 break; 2706 case BTC_CXP_PAUTO_TD60B1: 2707 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2708 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2709 break; 2710 case BTC_CXP_PAUTO_TD20B1: 2711 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2712 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2713 break; 2714 case BTC_CXP_PAUTO_TDW1B1: 2715 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2716 tbl_w1, SLOT_ISO); 2717 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2718 tbl_b1, SLOT_MIX); 2719 break; 2720 default: 2721 break; 2722 } 2723 break; 2724 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 2725 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2726 *t = t_def[CXTD_AUTO2]; 2727 2728 switch (policy_type) { 2729 case BTC_CXP_AUTO2_TD3050: 2730 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2731 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2732 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2733 break; 2734 case BTC_CXP_AUTO2_TD3070: 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, 70, tbl_b4, SLOT_MIX); 2738 break; 2739 case BTC_CXP_AUTO2_TD5050: 2740 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2741 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2742 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2743 break; 2744 case BTC_CXP_AUTO2_TD6060: 2745 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2746 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2747 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 2748 break; 2749 case BTC_CXP_AUTO2_TD2080: 2750 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2751 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2752 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 2753 break; 2754 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 2755 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2756 tbl_w1, SLOT_ISO); 2757 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2758 tbl_b1, SLOT_MIX); 2759 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 2760 tbl_b4, SLOT_MIX); 2761 break; 2762 default: 2763 break; 2764 } 2765 break; 2766 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 2767 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 2768 *t = t_def[CXTD_PAUTO2]; 2769 2770 switch (policy_type) { 2771 case BTC_CXP_PAUTO2_TD3050: 2772 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 2773 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2774 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2775 break; 2776 case BTC_CXP_PAUTO2_TD3070: 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, 70, tbl_b4, SLOT_MIX); 2780 break; 2781 case BTC_CXP_PAUTO2_TD5050: 2782 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 2783 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2784 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 2785 break; 2786 case BTC_CXP_PAUTO2_TD6060: 2787 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 2788 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2789 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 2790 break; 2791 case BTC_CXP_PAUTO2_TD2080: 2792 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 2793 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 2794 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 2795 break; 2796 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 2797 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 2798 tbl_w1, SLOT_ISO); 2799 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 2800 tbl_b1, SLOT_MIX); 2801 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 2802 tbl_b4, SLOT_MIX); 2803 break; 2804 default: 2805 break; 2806 } 2807 break; 2808 } 2809 2810 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) { 2811 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) | 2812 FIELD_PREP(0xf0, dm->wl_scc.null_role2); 2813 _tdma_set_flctrl_role(btc, null_role); 2814 } 2815 2816 /* enter leak_slot after each null-1 */ 2817 if (dm->leak_ap && dm->tdma.leak_n > 1) 2818 _tdma_set_lek(btc, 1); 2819 2820 if (dm->tdma_instant_excute) { 2821 btc->dm.tdma.option_ctrl |= BIT(0); 2822 btc->update_policy_force = true; 2823 } 2824 } 2825 EXPORT_SYMBOL(rtw89_btc_set_policy_v1); 2826 2827 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map, 2828 u8 tx_val, u8 rx_val) 2829 { 2830 struct rtw89_mac_ax_plt plt; 2831 2832 plt.band = RTW89_MAC_0; 2833 plt.tx = tx_val; 2834 plt.rx = rx_val; 2835 2836 if (phy_map & BTC_PHY_0) 2837 rtw89_mac_cfg_plt(rtwdev, &plt); 2838 2839 if (!rtwdev->dbcc_en) 2840 return; 2841 2842 plt.band = RTW89_MAC_1; 2843 if (phy_map & BTC_PHY_1) 2844 rtw89_mac_cfg_plt(rtwdev, &plt); 2845 } 2846 2847 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec, 2848 u8 phy_map, u8 type) 2849 { 2850 struct rtw89_btc *btc = &rtwdev->btc; 2851 struct rtw89_btc_dm *dm = &btc->dm; 2852 struct rtw89_btc_cx *cx = &btc->cx; 2853 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2854 struct rtw89_btc_bt_info *bt = &cx->bt; 2855 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 2856 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0; 2857 u32 ant_path_type; 2858 2859 ant_path_type = ((phy_map << 8) + type); 2860 2861 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF || 2862 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE || 2863 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX) 2864 force_exec = FC_EXEC; 2865 2866 if (!force_exec && ant_path_type == dm->set_ant_path) { 2867 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2868 "[BTC], %s(): return by no change!!\n", 2869 __func__); 2870 return; 2871 } else if (bt->rfk_info.map.run) { 2872 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2873 "[BTC], %s(): return by bt rfk!!\n", __func__); 2874 return; 2875 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 2876 wl->rfk_info.state != BTC_WRFK_STOP) { 2877 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2878 "[BTC], %s(): return by wl rfk!!\n", __func__); 2879 return; 2880 } 2881 2882 dm->set_ant_path = ant_path_type; 2883 2884 rtw89_debug(rtwdev, 2885 RTW89_DBG_BTC, 2886 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 2887 __func__, phy_map, dm->set_ant_path & 0xff); 2888 2889 switch (type) { 2890 case BTC_ANT_WPOWERON: 2891 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 2892 break; 2893 case BTC_ANT_WINIT: 2894 if (bt->enable.now) 2895 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 2896 else 2897 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 2898 2899 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2900 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT); 2901 break; 2902 case BTC_ANT_WONLY: 2903 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 2904 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2905 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 2906 break; 2907 case BTC_ANT_WOFF: 2908 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 2909 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 2910 break; 2911 case BTC_ANT_W2G: 2912 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2913 if (rtwdev->dbcc_en) { 2914 for (i = 0; i < RTW89_PHY_MAX; i++) { 2915 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G); 2916 2917 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 2918 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 2919 /* BT should control by GNT_BT if WL_2G at S0 */ 2920 if (i == 1 && 2921 wl_dinfo->real_band[0] == RTW89_BAND_2G && 2922 wl_dinfo->real_band[1] == RTW89_BAND_5G) 2923 gnt_bt_ctrl = BTC_GNT_HW; 2924 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl); 2925 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE; 2926 _set_bt_plut(rtwdev, BIT(i), 2927 plt_ctrl, plt_ctrl); 2928 } 2929 } else { 2930 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 2931 _set_bt_plut(rtwdev, BTC_PHY_ALL, 2932 BTC_PLT_BT, BTC_PLT_BT); 2933 } 2934 break; 2935 case BTC_ANT_W5G: 2936 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2937 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW); 2938 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 2939 break; 2940 case BTC_ANT_W25G: 2941 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2942 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 2943 _set_bt_plut(rtwdev, BTC_PHY_ALL, 2944 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 2945 break; 2946 case BTC_ANT_FREERUN: 2947 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2948 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI); 2949 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 2950 break; 2951 case BTC_ANT_WRFK: 2952 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 2953 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 2954 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 2955 break; 2956 case BTC_ANT_BRFK: 2957 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 2958 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 2959 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 2960 break; 2961 default: 2962 break; 2963 } 2964 } 2965 2966 static void _action_wl_only(struct rtw89_dev *rtwdev) 2967 { 2968 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 2969 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY); 2970 } 2971 2972 static void _action_wl_init(struct rtw89_dev *rtwdev) 2973 { 2974 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 2975 2976 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT); 2977 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT); 2978 } 2979 2980 static void _action_wl_off(struct rtw89_dev *rtwdev) 2981 { 2982 struct rtw89_btc *btc = &rtwdev->btc; 2983 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2984 2985 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 2986 2987 if (wl->status.map.rf_off || btc->dm.bt_only) 2988 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF); 2989 2990 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 2991 } 2992 2993 static void _action_freerun(struct rtw89_dev *rtwdev) 2994 { 2995 struct rtw89_btc *btc = &rtwdev->btc; 2996 2997 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 2998 2999 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN); 3000 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN); 3001 3002 btc->dm.freerun = true; 3003 } 3004 3005 static void _action_bt_whql(struct rtw89_dev *rtwdev) 3006 { 3007 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3008 3009 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3010 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL); 3011 } 3012 3013 static void _action_bt_off(struct rtw89_dev *rtwdev) 3014 { 3015 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 3016 3017 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 3018 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF); 3019 } 3020 3021 static void _action_bt_idle(struct rtw89_dev *rtwdev) 3022 { 3023 struct rtw89_btc *btc = &rtwdev->btc; 3024 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info; 3025 3026 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3027 3028 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3029 switch (btc->cx.state_map) { 3030 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/ 3031 if (b->profile_cnt.now > 0) 3032 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, 3033 BTC_ACT_BT_IDLE); 3034 else 3035 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, 3036 BTC_ACT_BT_IDLE); 3037 break; 3038 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */ 3039 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, 3040 BTC_ACT_BT_IDLE); 3041 break; 3042 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */ 3043 if (b->profile_cnt.now > 0) 3044 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, 3045 BTC_ACT_BT_IDLE); 3046 else 3047 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, 3048 BTC_ACT_BT_IDLE); 3049 break; 3050 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */ 3051 _set_policy(rtwdev, BTC_CXP_FIX_TD5050, 3052 BTC_ACT_BT_IDLE); 3053 break; 3054 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */ 3055 _set_policy(rtwdev, BTC_CXP_FIX_TD7010, 3056 BTC_ACT_BT_IDLE); 3057 break; 3058 case BTC_WIDLE: /* wl-idle + bt-idle */ 3059 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE); 3060 break; 3061 } 3062 } else { /* dedicated-antenna */ 3063 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE); 3064 } 3065 } 3066 3067 static void _action_bt_hfp(struct rtw89_dev *rtwdev) 3068 { 3069 struct rtw89_btc *btc = &rtwdev->btc; 3070 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3071 3072 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3073 3074 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 3075 if (btc->cx.wl.status.map._4way) { 3076 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP); 3077 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3078 btc->cx.bt.scan_rx_low_pri = true; 3079 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP); 3080 } else { 3081 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 3082 } 3083 } else { 3084 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP); 3085 } 3086 } 3087 3088 static void _action_bt_hid(struct rtw89_dev *rtwdev) 3089 { 3090 const struct rtw89_chip_info *chip = rtwdev->chip; 3091 struct rtw89_btc *btc = &rtwdev->btc; 3092 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3093 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3094 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc; 3095 u16 policy_type = BTC_CXP_OFF_BT; 3096 3097 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3098 3099 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3100 if (wl->status.map._4way) { 3101 policy_type = BTC_CXP_OFF_WL; 3102 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3103 btc->cx.bt.scan_rx_low_pri = true; 3104 if (hid->type & BTC_HID_BLE) 3105 policy_type = BTC_CXP_OFF_BWB0; 3106 else 3107 policy_type = BTC_CXP_OFF_BWB2; 3108 } else if (hid->type == BTC_HID_218) { 3109 bt->scan_rx_low_pri = true; 3110 policy_type = BTC_CXP_OFF_BWB2; 3111 } else if (chip->para_ver == 0x1) { 3112 policy_type = BTC_CXP_OFF_BWB3; 3113 } else { 3114 policy_type = BTC_CXP_OFF_BWB1; 3115 } 3116 } else { /* dedicated-antenna */ 3117 policy_type = BTC_CXP_OFF_EQ3; 3118 } 3119 3120 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID); 3121 } 3122 3123 static void _action_bt_a2dp(struct rtw89_dev *rtwdev) 3124 { 3125 struct rtw89_btc *btc = &rtwdev->btc; 3126 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 3127 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3128 struct rtw89_btc_dm *dm = &btc->dm; 3129 3130 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3131 3132 switch (btc->cx.state_map) { 3133 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 3134 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3135 dm->slot_dur[CXST_W1] = 40; 3136 dm->slot_dur[CXST_B1] = 200; 3137 _set_policy(rtwdev, 3138 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 3139 } else { 3140 _set_policy(rtwdev, 3141 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP); 3142 } 3143 break; 3144 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 3145 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 3146 break; 3147 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 3148 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 3149 break; 3150 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 3151 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 3152 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3153 dm->slot_dur[CXST_W1] = 40; 3154 dm->slot_dur[CXST_B1] = 200; 3155 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, 3156 BTC_ACT_BT_A2DP); 3157 } else { 3158 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, 3159 BTC_ACT_BT_A2DP); 3160 } 3161 break; 3162 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 3163 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 3164 break; 3165 } 3166 } 3167 3168 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 3169 { 3170 struct rtw89_btc *btc = &rtwdev->btc; 3171 3172 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3173 3174 switch (btc->cx.state_map) { 3175 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 3176 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 3177 break; 3178 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 3179 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 3180 break; 3181 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 3182 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 3183 break; 3184 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 3185 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 3186 break; 3187 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 3188 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 3189 break; 3190 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 3191 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 3192 break; 3193 } 3194 } 3195 3196 static void _action_bt_pan(struct rtw89_dev *rtwdev) 3197 { 3198 struct rtw89_btc *btc = &rtwdev->btc; 3199 3200 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3201 3202 switch (btc->cx.state_map) { 3203 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 3204 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 3205 break; 3206 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 3207 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 3208 break; 3209 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 3210 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 3211 break; 3212 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 3213 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 3214 break; 3215 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 3216 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, BTC_ACT_BT_PAN); 3217 break; 3218 case BTC_WIDLE: /* wl-idle + bt-pan */ 3219 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 3220 break; 3221 } 3222 } 3223 3224 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 3225 { 3226 struct rtw89_btc *btc = &rtwdev->btc; 3227 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 3228 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3229 struct rtw89_btc_dm *dm = &btc->dm; 3230 3231 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3232 3233 switch (btc->cx.state_map) { 3234 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 3235 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 3236 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3237 dm->slot_dur[CXST_W1] = 40; 3238 dm->slot_dur[CXST_B1] = 200; 3239 _set_policy(rtwdev, 3240 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 3241 } else { 3242 _set_policy(rtwdev, 3243 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID); 3244 } 3245 break; 3246 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 3247 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 3248 break; 3249 3250 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 3251 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 3252 break; 3253 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 3254 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 3255 if (a2dp.vendor_id == 0x4c || dm->leak_ap) { 3256 dm->slot_dur[CXST_W1] = 40; 3257 dm->slot_dur[CXST_B1] = 200; 3258 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, 3259 BTC_ACT_BT_A2DP_HID); 3260 } else { 3261 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, 3262 BTC_ACT_BT_A2DP_HID); 3263 } 3264 break; 3265 } 3266 } 3267 3268 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 3269 { 3270 struct rtw89_btc *btc = &rtwdev->btc; 3271 3272 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3273 3274 switch (btc->cx.state_map) { 3275 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 3276 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3277 break; 3278 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 3279 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3280 break; 3281 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 3282 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 3283 break; 3284 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 3285 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 3286 break; 3287 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 3288 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 3289 break; 3290 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 3291 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 3292 break; 3293 } 3294 } 3295 3296 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 3297 { 3298 struct rtw89_btc *btc = &rtwdev->btc; 3299 3300 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3301 3302 switch (btc->cx.state_map) { 3303 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 3304 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 3305 break; 3306 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 3307 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 3308 break; 3309 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 3310 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 3311 break; 3312 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 3313 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 3314 break; 3315 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 3316 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 3317 break; 3318 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 3319 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 3320 break; 3321 } 3322 } 3323 3324 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 3325 { 3326 struct rtw89_btc *btc = &rtwdev->btc; 3327 3328 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3329 3330 switch (btc->cx.state_map) { 3331 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 3332 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 3333 BTC_ACT_BT_A2DP_PAN_HID); 3334 break; 3335 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 3336 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 3337 BTC_ACT_BT_A2DP_PAN_HID); 3338 break; 3339 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 3340 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 3341 BTC_ACT_BT_A2DP_PAN_HID); 3342 break; 3343 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 3344 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 3345 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 3346 BTC_ACT_BT_A2DP_PAN_HID); 3347 break; 3348 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 3349 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 3350 BTC_ACT_BT_A2DP_PAN_HID); 3351 break; 3352 } 3353 } 3354 3355 static void _action_wl_5g(struct rtw89_dev *rtwdev) 3356 { 3357 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 3358 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 3359 } 3360 3361 static void _action_wl_other(struct rtw89_dev *rtwdev) 3362 { 3363 struct rtw89_btc *btc = &rtwdev->btc; 3364 3365 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3366 3367 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) 3368 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 3369 else 3370 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 3371 } 3372 3373 static void _action_wl_nc(struct rtw89_dev *rtwdev) 3374 { 3375 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3376 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 3377 } 3378 3379 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 3380 { 3381 struct rtw89_btc *btc = &rtwdev->btc; 3382 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 3383 3384 if (rfk.state != BTC_WRFK_START) 3385 return; 3386 3387 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 3388 __func__, rfk.band); 3389 3390 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 3391 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 3392 } 3393 3394 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 3395 { 3396 const struct rtw89_chip_info *chip = rtwdev->chip; 3397 struct rtw89_btc *btc = &rtwdev->btc; 3398 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3399 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3400 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3401 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 3402 bool is_btg; 3403 u8 mode; 3404 3405 if (btc->ctrl.manual) 3406 return; 3407 3408 if (chip->chip_id == RTL8852A) 3409 mode = wl_rinfo->link_mode; 3410 else 3411 mode = wl_rinfo_v1->link_mode; 3412 3413 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */ 3414 if (mode == BTC_WLINK_5G) /* always 0 if 5G */ 3415 is_btg = false; 3416 else if (mode == BTC_WLINK_25G_DBCC && 3417 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 3418 is_btg = false; 3419 else 3420 is_btg = true; 3421 3422 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT && 3423 is_btg == btc->dm.wl_btg_rx) 3424 return; 3425 3426 btc->dm.wl_btg_rx = is_btg; 3427 3428 if (mode == BTC_WLINK_25G_MCC) 3429 return; 3430 3431 rtw89_ctrl_btg(rtwdev, is_btg); 3432 } 3433 3434 struct rtw89_txtime_data { 3435 struct rtw89_dev *rtwdev; 3436 int type; 3437 u32 tx_time; 3438 u8 tx_retry; 3439 u16 enable; 3440 bool reenable; 3441 }; 3442 3443 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 3444 { 3445 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 3446 struct rtw89_txtime_data *iter_data = 3447 (struct rtw89_txtime_data *)data; 3448 struct rtw89_dev *rtwdev = iter_data->rtwdev; 3449 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 3450 struct rtw89_btc *btc = &rtwdev->btc; 3451 struct rtw89_btc_cx *cx = &btc->cx; 3452 struct rtw89_btc_wl_info *wl = &cx->wl; 3453 struct rtw89_btc_wl_link_info *plink = NULL; 3454 u8 port = rtwvif->port; 3455 u32 tx_time = iter_data->tx_time; 3456 u8 tx_retry = iter_data->tx_retry; 3457 u16 enable = iter_data->enable; 3458 bool reenable = iter_data->reenable; 3459 3460 plink = &wl->link_info[port]; 3461 3462 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3463 "[BTC], %s(): port = %d\n", __func__, port); 3464 3465 if (!plink->connected) { 3466 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3467 "[BTC], %s(): connected = %d\n", 3468 __func__, plink->connected); 3469 return; 3470 } 3471 3472 /* backup the original tx time before tx-limit on */ 3473 if (reenable) { 3474 rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); 3475 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); 3476 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3477 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 3478 __func__, plink->tx_time, plink->tx_retry); 3479 } 3480 3481 /* restore the original tx time if no tx-limit */ 3482 if (!enable) { 3483 rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); 3484 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, 3485 plink->tx_retry); 3486 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3487 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 3488 __func__, plink->tx_time, plink->tx_retry); 3489 3490 } else { 3491 rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); 3492 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); 3493 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3494 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 3495 __func__, tx_time, tx_retry); 3496 } 3497 } 3498 3499 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 3500 { 3501 const struct rtw89_chip_info *chip = rtwdev->chip; 3502 struct rtw89_btc *btc = &rtwdev->btc; 3503 struct rtw89_btc_cx *cx = &btc->cx; 3504 struct rtw89_btc_dm *dm = &btc->dm; 3505 struct rtw89_btc_wl_info *wl = &cx->wl; 3506 struct rtw89_btc_bt_info *bt = &cx->bt; 3507 struct rtw89_btc_bt_link_info *b = &bt->link_info; 3508 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 3509 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 3510 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3511 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3512 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 3513 u8 mode; 3514 u8 tx_retry; 3515 u32 tx_time; 3516 u16 enable; 3517 bool reenable = false; 3518 3519 if (btc->ctrl.manual) 3520 return; 3521 3522 if (chip->chip_id == RTL8852A) 3523 mode = wl_rinfo->link_mode; 3524 else 3525 mode = wl_rinfo_v1->link_mode; 3526 3527 if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 || 3528 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) { 3529 enable = 0; 3530 tx_time = BTC_MAX_TX_TIME_DEF; 3531 tx_retry = BTC_MAX_TX_RETRY_DEF; 3532 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 3533 enable = 1; 3534 tx_time = BTC_MAX_TX_TIME_L2; 3535 tx_retry = BTC_MAX_TX_RETRY_L1; 3536 } else if (hfp->exist || hid->exist) { 3537 enable = 1; 3538 tx_time = BTC_MAX_TX_TIME_L3; 3539 tx_retry = BTC_MAX_TX_RETRY_L1; 3540 } else { 3541 enable = 0; 3542 tx_time = BTC_MAX_TX_TIME_DEF; 3543 tx_retry = BTC_MAX_TX_RETRY_DEF; 3544 } 3545 3546 if (dm->wl_tx_limit.enable == enable && 3547 dm->wl_tx_limit.tx_time == tx_time && 3548 dm->wl_tx_limit.tx_retry == tx_retry) 3549 return; 3550 3551 if (!dm->wl_tx_limit.enable && enable) 3552 reenable = true; 3553 3554 dm->wl_tx_limit.enable = enable; 3555 dm->wl_tx_limit.tx_time = tx_time; 3556 dm->wl_tx_limit.tx_retry = tx_retry; 3557 3558 data.enable = enable; 3559 data.tx_time = tx_time; 3560 data.tx_retry = tx_retry; 3561 data.reenable = reenable; 3562 3563 ieee80211_iterate_stations_atomic(rtwdev->hw, 3564 rtw89_tx_time_iter, 3565 &data); 3566 } 3567 3568 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 3569 { 3570 const struct rtw89_chip_info *chip = rtwdev->chip; 3571 struct rtw89_btc *btc = &rtwdev->btc; 3572 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3573 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3574 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3575 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3576 bool bt_hi_lna_rx = false; 3577 u8 mode; 3578 3579 if (chip->chip_id == RTL8852A) 3580 mode = wl_rinfo->link_mode; 3581 else 3582 mode = wl_rinfo_v1->link_mode; 3583 3584 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 3585 bt_hi_lna_rx = true; 3586 3587 if (bt_hi_lna_rx == bt->hi_lna_rx) 3588 return; 3589 3590 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 3591 } 3592 3593 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 3594 { 3595 struct rtw89_btc *btc = &rtwdev->btc; 3596 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3597 3598 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri)); 3599 } 3600 3601 /* TODO add these functions */ 3602 static void _action_common(struct rtw89_dev *rtwdev) 3603 { 3604 struct rtw89_btc *btc = &rtwdev->btc; 3605 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3606 3607 _set_btg_ctrl(rtwdev); 3608 _set_wl_tx_limit(rtwdev); 3609 _set_bt_afh_info(rtwdev); 3610 _set_bt_rx_agc(rtwdev); 3611 _set_rf_trx_para(rtwdev); 3612 _set_bt_rx_scan_pri(rtwdev); 3613 3614 if (wl->scbd_change) { 3615 rtw89_mac_cfg_sb(rtwdev, wl->scbd); 3616 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n", 3617 wl->scbd); 3618 wl->scbd_change = false; 3619 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++; 3620 } 3621 } 3622 3623 static void _action_by_bt(struct rtw89_dev *rtwdev) 3624 { 3625 struct rtw89_btc *btc = &rtwdev->btc; 3626 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3627 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 3628 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 3629 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 3630 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 3631 u8 profile_map = 0; 3632 3633 if (bt_linfo->hfp_desc.exist) 3634 profile_map |= BTC_BT_HFP; 3635 3636 if (bt_linfo->hid_desc.exist) 3637 profile_map |= BTC_BT_HID; 3638 3639 if (bt_linfo->a2dp_desc.exist) 3640 profile_map |= BTC_BT_A2DP; 3641 3642 if (bt_linfo->pan_desc.exist) 3643 profile_map |= BTC_BT_PAN; 3644 3645 switch (profile_map) { 3646 case BTC_BT_NOPROFILE: 3647 if (_check_freerun(rtwdev)) 3648 _action_freerun(rtwdev); 3649 else if (a2dp.active || pan.active) 3650 _action_bt_pan(rtwdev); 3651 else 3652 _action_bt_idle(rtwdev); 3653 break; 3654 case BTC_BT_HFP: 3655 if (_check_freerun(rtwdev)) 3656 _action_freerun(rtwdev); 3657 else 3658 _action_bt_hfp(rtwdev); 3659 break; 3660 case BTC_BT_HFP | BTC_BT_HID: 3661 case BTC_BT_HID: 3662 if (_check_freerun(rtwdev)) 3663 _action_freerun(rtwdev); 3664 else 3665 _action_bt_hid(rtwdev); 3666 break; 3667 case BTC_BT_A2DP: 3668 if (_check_freerun(rtwdev)) 3669 _action_freerun(rtwdev); 3670 else if (a2dp.sink) 3671 _action_bt_a2dpsink(rtwdev); 3672 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 3673 _action_bt_a2dp_pan(rtwdev); 3674 else 3675 _action_bt_a2dp(rtwdev); 3676 break; 3677 case BTC_BT_PAN: 3678 _action_bt_pan(rtwdev); 3679 break; 3680 case BTC_BT_A2DP | BTC_BT_HFP: 3681 case BTC_BT_A2DP | BTC_BT_HID: 3682 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 3683 if (_check_freerun(rtwdev)) 3684 _action_freerun(rtwdev); 3685 else 3686 _action_bt_a2dp_hid(rtwdev); 3687 break; 3688 case BTC_BT_A2DP | BTC_BT_PAN: 3689 _action_bt_a2dp_pan(rtwdev); 3690 break; 3691 case BTC_BT_PAN | BTC_BT_HFP: 3692 case BTC_BT_PAN | BTC_BT_HID: 3693 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 3694 _action_bt_pan_hid(rtwdev); 3695 break; 3696 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 3697 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 3698 default: 3699 _action_bt_a2dp_pan_hid(rtwdev); 3700 break; 3701 } 3702 } 3703 3704 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 3705 { 3706 _action_by_bt(rtwdev); 3707 } 3708 3709 static void _action_wl_scan(struct rtw89_dev *rtwdev) 3710 { 3711 struct rtw89_btc *btc = &rtwdev->btc; 3712 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3713 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 3714 3715 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { 3716 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 3717 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) 3718 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 3719 BTC_RSN_NTFY_SCAN_START); 3720 else 3721 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, 3722 BTC_RSN_NTFY_SCAN_START); 3723 3724 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 3725 } else if (rtwdev->dbcc_en) { 3726 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 3727 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 3728 _action_wl_5g(rtwdev); 3729 else 3730 _action_by_bt(rtwdev); 3731 } else { 3732 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 3733 _action_wl_5g(rtwdev); 3734 else 3735 _action_by_bt(rtwdev); 3736 } 3737 } 3738 3739 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 3740 { 3741 struct rtw89_btc *btc = &rtwdev->btc; 3742 3743 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 3744 3745 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 3746 if (btc->cx.bt.link_info.profile_cnt.now == 0) 3747 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 3748 BTC_ACT_WL_25G_MCC); 3749 else 3750 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 3751 BTC_ACT_WL_25G_MCC); 3752 } else { /* dedicated-antenna */ 3753 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC); 3754 } 3755 } 3756 3757 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 3758 { struct rtw89_btc *btc = &rtwdev->btc; 3759 3760 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3761 3762 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3763 if (btc->cx.bt.link_info.profile_cnt.now == 0) 3764 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 3765 BTC_ACT_WL_2G_MCC); 3766 else 3767 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 3768 BTC_ACT_WL_2G_MCC); 3769 } else { /* dedicated-antenna */ 3770 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 3771 } 3772 } 3773 3774 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 3775 { 3776 struct rtw89_btc *btc = &rtwdev->btc; 3777 3778 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3779 3780 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3781 if (btc->cx.bt.link_info.profile_cnt.now == 0) 3782 _set_policy(rtwdev, 3783 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC); 3784 else 3785 _set_policy(rtwdev, 3786 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC); 3787 } else { /* dedicated-antenna */ 3788 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC); 3789 } 3790 } 3791 3792 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev) 3793 { 3794 struct rtw89_btc *btc = &rtwdev->btc; 3795 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3796 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3797 struct rtw89_btc_dm *dm = &btc->dm; 3798 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 3799 u16 policy_type = BTC_CXP_OFF_BT; 3800 u32 dur; 3801 3802 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) { 3803 policy_type = BTC_CXP_OFF_EQ0; 3804 } else { 3805 /* shared-antenna */ 3806 switch (wl_rinfo->mrole_type) { 3807 case BTC_WLMROLE_STA_GC: 3808 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 3809 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 3810 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 3811 _action_by_bt(rtwdev); 3812 return; 3813 case BTC_WLMROLE_STA_STA: 3814 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 3815 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 3816 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 3817 _action_by_bt(rtwdev); 3818 return; 3819 case BTC_WLMROLE_STA_GC_NOA: 3820 case BTC_WLMROLE_STA_GO: 3821 case BTC_WLMROLE_STA_GO_NOA: 3822 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 3823 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 3824 dur = wl_rinfo->mrole_noa_duration; 3825 3826 if (wl->status.map._4way) { 3827 dm->wl_scc.ebt_null = 0; 3828 policy_type = BTC_CXP_OFFE_WL; 3829 } else if (bt->link_info.status.map.connect == 0) { 3830 dm->wl_scc.ebt_null = 0; 3831 policy_type = BTC_CXP_OFFE_2GISOB; 3832 } else if (bt->link_info.a2dp_desc.exist && 3833 dur < btc->bt_req_len) { 3834 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 3835 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 3836 } else if (bt->link_info.a2dp_desc.exist || 3837 bt->link_info.pan_desc.exist) { 3838 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 3839 policy_type = BTC_CXP_OFFE_2GBWISOB; 3840 } else { 3841 dm->wl_scc.ebt_null = 0; 3842 policy_type = BTC_CXP_OFFE_2GBWISOB; 3843 } 3844 break; 3845 default: 3846 break; 3847 } 3848 } 3849 3850 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3851 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 3852 } 3853 3854 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 3855 { 3856 struct rtw89_btc *btc = &rtwdev->btc; 3857 3858 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3859 3860 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { 3861 if (btc->cx.bt.link_info.profile_cnt.now == 0) 3862 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 3863 BTC_ACT_WL_2G_AP); 3864 else 3865 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 3866 } else {/* dedicated-antenna */ 3867 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 3868 } 3869 } 3870 3871 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 3872 { 3873 struct rtw89_btc *btc = &rtwdev->btc; 3874 3875 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3876 3877 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3878 if (btc->cx.bt.link_info.profile_cnt.now == 0) 3879 _set_policy(rtwdev, 3880 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 3881 else 3882 _set_policy(rtwdev, 3883 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 3884 } else { /* dedicated-antenna */ 3885 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 3886 } 3887 } 3888 3889 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 3890 { 3891 struct rtw89_btc *btc = &rtwdev->btc; 3892 3893 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3894 3895 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3896 _action_by_bt(rtwdev); 3897 } else {/* dedicated-antenna */ 3898 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 3899 } 3900 } 3901 3902 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 3903 { 3904 struct rtw89_btc *btc = &rtwdev->btc; 3905 3906 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 3907 3908 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */ 3909 if (btc->cx.bt.link_info.profile_cnt.now == 0) 3910 _set_policy(rtwdev, 3911 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 3912 else 3913 _set_policy(rtwdev, 3914 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 3915 } else { /* dedicated-antenna */ 3916 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 3917 } 3918 } 3919 3920 static u32 _read_scbd(struct rtw89_dev *rtwdev) 3921 { 3922 const struct rtw89_chip_info *chip = rtwdev->chip; 3923 struct rtw89_btc *btc = &rtwdev->btc; 3924 u32 scbd_val = 0; 3925 3926 if (!chip->scbd) 3927 return 0; 3928 3929 scbd_val = rtw89_mac_get_sb(rtwdev); 3930 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n", 3931 scbd_val); 3932 3933 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++; 3934 return scbd_val; 3935 } 3936 3937 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state) 3938 { 3939 const struct rtw89_chip_info *chip = rtwdev->chip; 3940 struct rtw89_btc *btc = &rtwdev->btc; 3941 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3942 u32 scbd_val = 0; 3943 u8 force_exec = false; 3944 3945 if (!chip->scbd) 3946 return; 3947 3948 scbd_val = state ? wl->scbd | val : wl->scbd & ~val; 3949 3950 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON) 3951 force_exec = true; 3952 3953 if (scbd_val != wl->scbd || force_exec) { 3954 wl->scbd = scbd_val; 3955 wl->scbd_change = true; 3956 } 3957 } 3958 3959 static u8 3960 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 3961 { 3962 const struct rtw89_chip_info *chip = rtwdev->chip; 3963 u8 next_state, tol = chip->rssi_tol; 3964 3965 if (pre_state == BTC_RSSI_ST_LOW || 3966 pre_state == BTC_RSSI_ST_STAY_LOW) { 3967 if (rssi >= (thresh + tol)) 3968 next_state = BTC_RSSI_ST_HIGH; 3969 else 3970 next_state = BTC_RSSI_ST_STAY_LOW; 3971 } else { 3972 if (rssi < thresh) 3973 next_state = BTC_RSSI_ST_LOW; 3974 else 3975 next_state = BTC_RSSI_ST_STAY_HIGH; 3976 } 3977 3978 return next_state; 3979 } 3980 3981 static 3982 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 3983 { 3984 struct rtw89_btc *btc = &rtwdev->btc; 3985 3986 btc->cx.wl.dbcc_info.real_band[phy_idx] = 3987 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 3988 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 3989 btc->cx.wl.dbcc_info.op_band[phy_idx]; 3990 } 3991 3992 static void _update_wl_info(struct rtw89_dev *rtwdev) 3993 { 3994 struct rtw89_btc *btc = &rtwdev->btc; 3995 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3996 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 3997 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3998 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 3999 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4000 u8 cnt_2g = 0, cnt_5g = 0, phy; 4001 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0}; 4002 bool b2g = false, b5g = false, client_joined = false; 4003 4004 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4005 4006 for (i = 0; i < RTW89_PORT_NUM; i++) { 4007 /* check if role active? */ 4008 if (!wl_linfo[i].active) 4009 continue; 4010 4011 cnt_active++; 4012 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role; 4013 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid; 4014 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy; 4015 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band; 4016 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4017 wl_rinfo->active_role[cnt_active - 1].connected = 0; 4018 4019 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4020 4021 phy = wl_linfo[i].phy; 4022 4023 /* check dbcc role */ 4024 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4025 wl_dinfo->role[phy] = wl_linfo[i].role; 4026 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4027 _update_dbcc_band(rtwdev, phy); 4028 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4029 } 4030 4031 if (wl_linfo[i].connected == MLME_NO_LINK) { 4032 continue; 4033 } else if (wl_linfo[i].connected == MLME_LINKING) { 4034 cnt_connecting++; 4035 } else { 4036 cnt_connect++; 4037 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4038 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4039 wl_linfo[i].client_cnt > 1) 4040 client_joined = true; 4041 } 4042 4043 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4044 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch; 4045 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw; 4046 wl_rinfo->active_role[cnt_active - 1].connected = 1; 4047 4048 /* only care 2 roles + BT coex */ 4049 if (wl_linfo[i].band != RTW89_BAND_2G) { 4050 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4051 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4052 cnt_5g++; 4053 b5g = true; 4054 } else { 4055 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4056 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4057 cnt_2g++; 4058 b2g = true; 4059 } 4060 } 4061 4062 wl_rinfo->connect_cnt = cnt_connect; 4063 4064 /* Be careful to change the following sequence!! */ 4065 if (cnt_connect == 0) { 4066 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4067 wl_rinfo->role_map.role.none = 1; 4068 } else if (!b2g && b5g) { 4069 wl_rinfo->link_mode = BTC_WLINK_5G; 4070 } else if (wl_rinfo->role_map.role.nan) { 4071 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4072 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4073 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4074 } else if (b2g && b5g && cnt_connect == 2) { 4075 if (rtwdev->dbcc_en) { 4076 switch (wl_dinfo->role[RTW89_PHY_0]) { 4077 case RTW89_WIFI_ROLE_STATION: 4078 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4079 break; 4080 case RTW89_WIFI_ROLE_P2P_GO: 4081 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4082 break; 4083 case RTW89_WIFI_ROLE_P2P_CLIENT: 4084 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4085 break; 4086 case RTW89_WIFI_ROLE_AP: 4087 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4088 break; 4089 default: 4090 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4091 break; 4092 } 4093 } else { 4094 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4095 } 4096 } else if (!b5g && cnt_connect == 2) { 4097 if (wl_rinfo->role_map.role.station && 4098 (wl_rinfo->role_map.role.p2p_go || 4099 wl_rinfo->role_map.role.p2p_gc || 4100 wl_rinfo->role_map.role.ap)) { 4101 if (wl_2g_ch[0] == wl_2g_ch[1]) 4102 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4103 else 4104 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4105 } else { 4106 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4107 } 4108 } else if (!b5g && cnt_connect == 1) { 4109 if (wl_rinfo->role_map.role.station) 4110 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4111 else if (wl_rinfo->role_map.role.ap) 4112 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4113 else if (wl_rinfo->role_map.role.p2p_go) 4114 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4115 else if (wl_rinfo->role_map.role.p2p_gc) 4116 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4117 else 4118 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4119 } 4120 4121 /* if no client_joined, don't care P2P-GO/AP role */ 4122 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4123 if (!client_joined) { 4124 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4125 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4126 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4127 wl_rinfo->connect_cnt = 1; 4128 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4129 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4130 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4131 wl_rinfo->connect_cnt = 0; 4132 } 4133 } 4134 } 4135 4136 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4137 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4138 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4139 4140 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4141 } 4142 4143 static void _update_wl_info_v1(struct rtw89_dev *rtwdev) 4144 { 4145 struct rtw89_btc *btc = &rtwdev->btc; 4146 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4147 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4148 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 4149 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4150 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4151 u8 cnt_2g = 0, cnt_5g = 0, phy; 4152 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 4153 bool b2g = false, b5g = false, client_joined = false; 4154 u8 i; 4155 4156 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4157 4158 for (i = 0; i < RTW89_PORT_NUM; i++) { 4159 if (!wl_linfo[i].active) 4160 continue; 4161 4162 cnt_active++; 4163 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role; 4164 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid; 4165 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy; 4166 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band; 4167 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4168 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0; 4169 4170 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4171 4172 phy = wl_linfo[i].phy; 4173 4174 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4175 wl_dinfo->role[phy] = wl_linfo[i].role; 4176 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4177 _update_dbcc_band(rtwdev, phy); 4178 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4179 } 4180 4181 if (wl_linfo[i].connected == MLME_NO_LINK) { 4182 continue; 4183 } else if (wl_linfo[i].connected == MLME_LINKING) { 4184 cnt_connecting++; 4185 } else { 4186 cnt_connect++; 4187 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4188 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4189 wl_linfo[i].client_cnt > 1) 4190 client_joined = true; 4191 } 4192 4193 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4194 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch; 4195 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw; 4196 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1; 4197 4198 /* only care 2 roles + BT coex */ 4199 if (wl_linfo[i].band != RTW89_BAND_2G) { 4200 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4201 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4202 cnt_5g++; 4203 b5g = true; 4204 } else { 4205 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4206 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4207 cnt_2g++; 4208 b2g = true; 4209 } 4210 } 4211 4212 wl_rinfo->connect_cnt = cnt_connect; 4213 4214 /* Be careful to change the following sequence!! */ 4215 if (cnt_connect == 0) { 4216 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4217 wl_rinfo->role_map.role.none = 1; 4218 } else if (!b2g && b5g) { 4219 wl_rinfo->link_mode = BTC_WLINK_5G; 4220 } else if (wl_rinfo->role_map.role.nan) { 4221 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4222 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4223 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4224 } else if (b2g && b5g && cnt_connect == 2) { 4225 if (rtwdev->dbcc_en) { 4226 switch (wl_dinfo->role[RTW89_PHY_0]) { 4227 case RTW89_WIFI_ROLE_STATION: 4228 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4229 break; 4230 case RTW89_WIFI_ROLE_P2P_GO: 4231 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4232 break; 4233 case RTW89_WIFI_ROLE_P2P_CLIENT: 4234 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4235 break; 4236 case RTW89_WIFI_ROLE_AP: 4237 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4238 break; 4239 default: 4240 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4241 break; 4242 } 4243 } else { 4244 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4245 } 4246 } else if (!b5g && cnt_connect == 2) { 4247 if (wl_rinfo->role_map.role.station && 4248 (wl_rinfo->role_map.role.p2p_go || 4249 wl_rinfo->role_map.role.p2p_gc || 4250 wl_rinfo->role_map.role.ap)) { 4251 if (wl_2g_ch[0] == wl_2g_ch[1]) 4252 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4253 else 4254 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4255 } else { 4256 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4257 } 4258 } else if (!b5g && cnt_connect == 1) { 4259 if (wl_rinfo->role_map.role.station) 4260 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4261 else if (wl_rinfo->role_map.role.ap) 4262 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4263 else if (wl_rinfo->role_map.role.p2p_go) 4264 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4265 else if (wl_rinfo->role_map.role.p2p_gc) 4266 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4267 else 4268 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4269 } 4270 4271 /* if no client_joined, don't care P2P-GO/AP role */ 4272 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4273 if (!client_joined) { 4274 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4275 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4276 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4277 wl_rinfo->connect_cnt = 1; 4278 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4279 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4280 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4281 wl_rinfo->connect_cnt = 0; 4282 } 4283 } 4284 } 4285 4286 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4287 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4288 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4289 4290 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4291 } 4292 4293 #define BTC_CHK_HANG_MAX 3 4294 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 4295 4296 void rtw89_coex_act1_work(struct work_struct *work) 4297 { 4298 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4299 coex_act1_work.work); 4300 struct rtw89_btc *btc = &rtwdev->btc; 4301 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4302 struct rtw89_btc_cx *cx = &btc->cx; 4303 struct rtw89_btc_wl_info *wl = &cx->wl; 4304 4305 mutex_lock(&rtwdev->mutex); 4306 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4307 dm->cnt_notify[BTC_NCNT_TIMER]++; 4308 if (wl->status.map._4way) 4309 wl->status.map._4way = false; 4310 if (wl->status.map.connecting) 4311 wl->status.map.connecting = false; 4312 4313 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 4314 mutex_unlock(&rtwdev->mutex); 4315 } 4316 4317 void rtw89_coex_bt_devinfo_work(struct work_struct *work) 4318 { 4319 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4320 coex_bt_devinfo_work.work); 4321 struct rtw89_btc *btc = &rtwdev->btc; 4322 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4323 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 4324 4325 mutex_lock(&rtwdev->mutex); 4326 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4327 dm->cnt_notify[BTC_NCNT_TIMER]++; 4328 a2dp->play_latency = 0; 4329 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 4330 mutex_unlock(&rtwdev->mutex); 4331 } 4332 4333 void rtw89_coex_rfk_chk_work(struct work_struct *work) 4334 { 4335 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4336 coex_rfk_chk_work.work); 4337 struct rtw89_btc *btc = &rtwdev->btc; 4338 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4339 struct rtw89_btc_cx *cx = &btc->cx; 4340 struct rtw89_btc_wl_info *wl = &cx->wl; 4341 4342 mutex_lock(&rtwdev->mutex); 4343 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4344 dm->cnt_notify[BTC_NCNT_TIMER]++; 4345 if (wl->rfk_info.state != BTC_WRFK_STOP) { 4346 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4347 "[BTC], %s(): RFK timeout\n", __func__); 4348 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++; 4349 dm->error.map.wl_rfk_timeout = true; 4350 wl->rfk_info.state = BTC_WRFK_STOP; 4351 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 4352 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 4353 } 4354 mutex_unlock(&rtwdev->mutex); 4355 } 4356 4357 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) 4358 { 4359 const struct rtw89_chip_info *chip = rtwdev->chip; 4360 struct rtw89_btc *btc = &rtwdev->btc; 4361 struct rtw89_btc_cx *cx = &btc->cx; 4362 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4363 u32 val; 4364 bool status_change = false; 4365 4366 if (!chip->scbd) 4367 return; 4368 4369 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 4370 4371 val = _read_scbd(rtwdev); 4372 if (val == BTC_SCB_INV_VALUE) { 4373 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4374 "[BTC], %s(): return by invalid scbd value\n", 4375 __func__); 4376 return; 4377 } 4378 4379 if (!(val & BTC_BSCB_ON) || 4380 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX) 4381 bt->enable.now = 0; 4382 else 4383 bt->enable.now = 1; 4384 4385 if (bt->enable.now != bt->enable.last) 4386 status_change = true; 4387 4388 /* reset bt info if bt re-enable */ 4389 if (bt->enable.now && !bt->enable.last) { 4390 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 4391 cx->cnt_bt[BTC_BCNT_REENABLE]++; 4392 bt->enable.now = 1; 4393 } 4394 4395 bt->enable.last = bt->enable.now; 4396 bt->scbd = val; 4397 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 4398 4399 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 4400 status_change = true; 4401 4402 bt->whql_test = !!(val & BTC_BSCB_WHQL); 4403 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE; 4404 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT); 4405 4406 /* if rfk run 1->0 */ 4407 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN)) 4408 status_change = true; 4409 4410 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN); 4411 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); 4412 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 4413 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); 4414 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 4415 4416 if (!only_update && status_change) 4417 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 4418 } 4419 4420 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) 4421 { 4422 struct rtw89_btc *btc = &rtwdev->btc; 4423 struct rtw89_btc_cx *cx = &btc->cx; 4424 struct rtw89_btc_bt_info *bt = &cx->bt; 4425 4426 _update_bt_scbd(rtwdev, true); 4427 4428 cx->cnt_wl[BTC_WCNT_RFK_REQ]++; 4429 4430 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) && 4431 !bt->rfk_info.map.timeout) { 4432 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++; 4433 } else { 4434 cx->cnt_wl[BTC_WCNT_RFK_GO]++; 4435 return true; 4436 } 4437 return false; 4438 } 4439 4440 static 4441 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 4442 { 4443 const struct rtw89_chip_info *chip = rtwdev->chip; 4444 struct rtw89_btc *btc = &rtwdev->btc; 4445 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4446 struct rtw89_btc_cx *cx = &btc->cx; 4447 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4448 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4449 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4450 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 4451 u8 mode; 4452 4453 lockdep_assert_held(&rtwdev->mutex); 4454 4455 dm->run_reason = reason; 4456 _update_dm_step(rtwdev, reason); 4457 _update_btc_state_map(rtwdev); 4458 4459 if (chip->chip_id == RTL8852A) 4460 mode = wl_rinfo->link_mode; 4461 else 4462 mode = wl_rinfo_v1->link_mode; 4463 4464 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 4465 __func__, reason, mode); 4466 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 4467 __func__, dm->wl_only, dm->bt_only); 4468 4469 /* Be careful to change the following function sequence!! */ 4470 if (btc->ctrl.manual) { 4471 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4472 "[BTC], %s(): return for Manual CTRL!!\n", 4473 __func__); 4474 return; 4475 } 4476 4477 if (btc->ctrl.igno_bt && 4478 (reason == BTC_RSN_UPDATE_BT_INFO || 4479 reason == BTC_RSN_UPDATE_BT_SCBD)) { 4480 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4481 "[BTC], %s(): return for Stop Coex DM!!\n", 4482 __func__); 4483 return; 4484 } 4485 4486 if (!wl->status.map.init_ok) { 4487 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4488 "[BTC], %s(): return for WL init fail!!\n", 4489 __func__); 4490 return; 4491 } 4492 4493 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 4494 wl->status.map.lps_pre == wl->status.map.lps && 4495 (reason == BTC_RSN_NTFY_POWEROFF || 4496 reason == BTC_RSN_NTFY_RADIO_STATE)) { 4497 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4498 "[BTC], %s(): return for WL rf off state no change!!\n", 4499 __func__); 4500 return; 4501 } 4502 4503 dm->cnt_dm[BTC_DCNT_RUN]++; 4504 4505 if (btc->ctrl.always_freerun) { 4506 _action_freerun(rtwdev); 4507 btc->ctrl.igno_bt = true; 4508 goto exit; 4509 } 4510 4511 if (dm->wl_only) { 4512 _action_wl_only(rtwdev); 4513 btc->ctrl.igno_bt = true; 4514 goto exit; 4515 } 4516 4517 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) { 4518 _action_wl_off(rtwdev); 4519 btc->ctrl.igno_bt = true; 4520 goto exit; 4521 } 4522 4523 btc->ctrl.igno_bt = false; 4524 dm->freerun = false; 4525 bt->scan_rx_low_pri = false; 4526 4527 if (reason == BTC_RSN_NTFY_INIT) { 4528 _action_wl_init(rtwdev); 4529 goto exit; 4530 } 4531 4532 if (!cx->bt.enable.now && !cx->other.type) { 4533 _action_bt_off(rtwdev); 4534 goto exit; 4535 } 4536 4537 if (cx->bt.whql_test) { 4538 _action_bt_whql(rtwdev); 4539 goto exit; 4540 } 4541 4542 if (wl->rfk_info.state != BTC_WRFK_STOP) { 4543 _action_wl_rfk(rtwdev); 4544 goto exit; 4545 } 4546 4547 if (cx->state_map == BTC_WLINKING) { 4548 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || 4549 mode == BTC_WLINK_5G) { 4550 _action_wl_scan(rtwdev); 4551 goto exit; 4552 } 4553 } 4554 4555 if (wl->status.map.scan) { 4556 _action_wl_scan(rtwdev); 4557 goto exit; 4558 } 4559 4560 switch (mode) { 4561 case BTC_WLINK_NOLINK: 4562 _action_wl_nc(rtwdev); 4563 break; 4564 case BTC_WLINK_2G_STA: 4565 _action_wl_2g_sta(rtwdev); 4566 break; 4567 case BTC_WLINK_2G_AP: 4568 bt->scan_rx_low_pri = true; 4569 _action_wl_2g_ap(rtwdev); 4570 break; 4571 case BTC_WLINK_2G_GO: 4572 bt->scan_rx_low_pri = true; 4573 _action_wl_2g_go(rtwdev); 4574 break; 4575 case BTC_WLINK_2G_GC: 4576 bt->scan_rx_low_pri = true; 4577 _action_wl_2g_gc(rtwdev); 4578 break; 4579 case BTC_WLINK_2G_SCC: 4580 bt->scan_rx_low_pri = true; 4581 if (chip->chip_id == RTL8852A) 4582 _action_wl_2g_scc(rtwdev); 4583 else if (chip->chip_id == RTL8852C) 4584 _action_wl_2g_scc_v1(rtwdev); 4585 break; 4586 case BTC_WLINK_2G_MCC: 4587 bt->scan_rx_low_pri = true; 4588 _action_wl_2g_mcc(rtwdev); 4589 break; 4590 case BTC_WLINK_25G_MCC: 4591 bt->scan_rx_low_pri = true; 4592 _action_wl_25g_mcc(rtwdev); 4593 break; 4594 case BTC_WLINK_5G: 4595 _action_wl_5g(rtwdev); 4596 break; 4597 case BTC_WLINK_2G_NAN: 4598 _action_wl_2g_nan(rtwdev); 4599 break; 4600 default: 4601 _action_wl_other(rtwdev); 4602 break; 4603 } 4604 4605 exit: 4606 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 4607 _action_common(rtwdev); 4608 } 4609 4610 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 4611 { 4612 struct rtw89_btc *btc = &rtwdev->btc; 4613 4614 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4615 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 4616 } 4617 4618 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 4619 { 4620 struct rtw89_btc *btc = &rtwdev->btc; 4621 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4622 4623 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4624 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 4625 4626 btc->cx.wl.status.map.rf_off = 1; 4627 btc->cx.wl.status.map.busy = 0; 4628 wl->status.map.lps = BTC_LPS_OFF; 4629 4630 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 4631 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 4632 4633 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 4634 4635 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 4636 } 4637 4638 static void _set_init_info(struct rtw89_dev *rtwdev) 4639 { 4640 const struct rtw89_chip_info *chip = rtwdev->chip; 4641 struct rtw89_btc *btc = &rtwdev->btc; 4642 struct rtw89_btc_dm *dm = &btc->dm; 4643 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4644 4645 dm->init_info.wl_only = (u8)dm->wl_only; 4646 dm->init_info.bt_only = (u8)dm->bt_only; 4647 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok; 4648 dm->init_info.dbcc_en = rtwdev->dbcc_en; 4649 dm->init_info.cx_other = btc->cx.other.type; 4650 dm->init_info.wl_guard_ch = chip->afh_guard_ch; 4651 dm->init_info.module = btc->mdinfo; 4652 } 4653 4654 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 4655 { 4656 struct rtw89_btc *btc = &rtwdev->btc; 4657 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4658 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4659 const struct rtw89_chip_info *chip = rtwdev->chip; 4660 4661 _reset_btc_var(rtwdev, BTC_RESET_ALL); 4662 btc->dm.run_reason = BTC_RSN_NONE; 4663 btc->dm.run_action = BTC_ACT_NONE; 4664 btc->ctrl.igno_bt = true; 4665 4666 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4667 "[BTC], %s(): mode=%d\n", __func__, mode); 4668 4669 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 4670 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 4671 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 4672 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 4673 4674 chip->ops->btc_set_rfe(rtwdev); 4675 chip->ops->btc_init_cfg(rtwdev); 4676 4677 if (!wl->status.map.init_ok) { 4678 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4679 "[BTC], %s(): return for WL init fail!!\n", 4680 __func__); 4681 dm->error.map.init = true; 4682 return; 4683 } 4684 4685 _write_scbd(rtwdev, 4686 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 4687 _update_bt_scbd(rtwdev, true); 4688 if (rtw89_mac_get_ctrl_path(rtwdev) && chip->chip_id == RTL8852A) { 4689 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4690 "[BTC], %s(): PTA owner warning!!\n", 4691 __func__); 4692 dm->error.map.pta_owner = true; 4693 } 4694 4695 _set_init_info(rtwdev); 4696 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR); 4697 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot); 4698 btc_fw_set_monreg(rtwdev); 4699 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 4700 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 4701 4702 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 4703 } 4704 4705 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 4706 { 4707 struct rtw89_btc *btc = &rtwdev->btc; 4708 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4709 4710 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4711 "[BTC], %s(): phy_idx=%d, band=%d\n", 4712 __func__, phy_idx, band); 4713 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 4714 wl->status.map.scan = true; 4715 wl->scan_info.band[phy_idx] = band; 4716 wl->scan_info.phy_map |= BIT(phy_idx); 4717 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 4718 4719 if (rtwdev->dbcc_en) { 4720 wl->dbcc_info.scan_band[phy_idx] = band; 4721 _update_dbcc_band(rtwdev, phy_idx); 4722 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4723 } 4724 4725 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 4726 } 4727 4728 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 4729 { 4730 struct rtw89_btc *btc = &rtwdev->btc; 4731 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4732 4733 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4734 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 4735 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 4736 4737 wl->status.map.scan = false; 4738 wl->scan_info.phy_map &= ~BIT(phy_idx); 4739 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 4740 4741 if (rtwdev->dbcc_en) { 4742 _update_dbcc_band(rtwdev, phy_idx); 4743 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4744 } 4745 4746 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 4747 } 4748 4749 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 4750 { 4751 struct rtw89_btc *btc = &rtwdev->btc; 4752 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4753 4754 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4755 "[BTC], %s(): phy_idx=%d, band=%d\n", 4756 __func__, phy_idx, band); 4757 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 4758 4759 wl->scan_info.band[phy_idx] = band; 4760 wl->scan_info.phy_map |= BIT(phy_idx); 4761 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 4762 4763 if (rtwdev->dbcc_en) { 4764 wl->dbcc_info.scan_band[phy_idx] = band; 4765 _update_dbcc_band(rtwdev, phy_idx); 4766 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4767 } 4768 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 4769 } 4770 4771 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 4772 enum btc_pkt_type pkt_type) 4773 { 4774 struct rtw89_btc *btc = &rtwdev->btc; 4775 struct rtw89_btc_cx *cx = &btc->cx; 4776 struct rtw89_btc_wl_info *wl = &cx->wl; 4777 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info; 4778 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 4779 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 4780 u32 cnt; 4781 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 4782 bool delay_work = false; 4783 4784 switch (pkt_type) { 4785 case PACKET_DHCP: 4786 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP]; 4787 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4788 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 4789 wl->status.map.connecting = true; 4790 delay_work = true; 4791 break; 4792 case PACKET_EAPOL: 4793 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 4794 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4795 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 4796 wl->status.map._4way = true; 4797 delay_work = true; 4798 if (hfp->exist || hid->exist) 4799 delay /= 2; 4800 break; 4801 case PACKET_EAPOL_END: 4802 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 4803 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4804 "[BTC], %s(): EAPOL_End cnt=%d\n", 4805 __func__, cnt); 4806 wl->status.map._4way = false; 4807 cancel_delayed_work(&rtwdev->coex_act1_work); 4808 break; 4809 case PACKET_ARP: 4810 cnt = ++cx->cnt_wl[BTC_WCNT_ARP]; 4811 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4812 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 4813 return; 4814 case PACKET_ICMP: 4815 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4816 "[BTC], %s(): ICMP pkt\n", __func__); 4817 return; 4818 default: 4819 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4820 "[BTC], %s(): unknown packet type %d\n", 4821 __func__, pkt_type); 4822 return; 4823 } 4824 4825 if (delay_work) { 4826 cancel_delayed_work(&rtwdev->coex_act1_work); 4827 ieee80211_queue_delayed_work(rtwdev->hw, 4828 &rtwdev->coex_act1_work, delay); 4829 } 4830 4831 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 4832 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 4833 } 4834 4835 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work) 4836 { 4837 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4838 btc.eapol_notify_work); 4839 4840 mutex_lock(&rtwdev->mutex); 4841 rtw89_leave_ps_mode(rtwdev); 4842 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 4843 mutex_unlock(&rtwdev->mutex); 4844 } 4845 4846 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work) 4847 { 4848 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4849 btc.arp_notify_work); 4850 4851 mutex_lock(&rtwdev->mutex); 4852 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 4853 mutex_unlock(&rtwdev->mutex); 4854 } 4855 4856 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work) 4857 { 4858 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4859 btc.dhcp_notify_work); 4860 4861 mutex_lock(&rtwdev->mutex); 4862 rtw89_leave_ps_mode(rtwdev); 4863 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 4864 mutex_unlock(&rtwdev->mutex); 4865 } 4866 4867 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work) 4868 { 4869 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4870 btc.icmp_notify_work); 4871 4872 mutex_lock(&rtwdev->mutex); 4873 rtw89_leave_ps_mode(rtwdev); 4874 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 4875 mutex_unlock(&rtwdev->mutex); 4876 } 4877 4878 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 4879 { 4880 const struct rtw89_chip_info *chip = rtwdev->chip; 4881 struct rtw89_btc *btc = &rtwdev->btc; 4882 struct rtw89_btc_cx *cx = &btc->cx; 4883 struct rtw89_btc_bt_info *bt = &cx->bt; 4884 struct rtw89_btc_bt_link_info *b = &bt->link_info; 4885 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 4886 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 4887 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 4888 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 4889 union btc_btinfo btinfo; 4890 4891 if (buf[BTC_BTINFO_L1] != 6) 4892 return; 4893 4894 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) { 4895 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4896 "[BTC], %s(): return by bt-info duplicate!!\n", 4897 __func__); 4898 cx->cnt_bt[BTC_BCNT_INFOSAME]++; 4899 return; 4900 } 4901 4902 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX); 4903 4904 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4905 "[BTC], %s(): bt_info[2]=0x%02x\n", 4906 __func__, bt->raw_info[2]); 4907 4908 /* reset to mo-connect before update */ 4909 b->status.val = BTC_BLINK_NOCONNECT; 4910 b->profile_cnt.last = b->profile_cnt.now; 4911 b->relink.last = b->relink.now; 4912 a2dp->exist_last = a2dp->exist; 4913 b->multi_link.last = b->multi_link.now; 4914 bt->inq_pag.last = bt->inq_pag.now; 4915 b->profile_cnt.now = 0; 4916 hid->type = 0; 4917 4918 /* parse raw info low-Byte2 */ 4919 btinfo.val = bt->raw_info[BTC_BTINFO_L2]; 4920 b->status.map.connect = btinfo.lb2.connect; 4921 b->status.map.sco_busy = btinfo.lb2.sco_busy; 4922 b->status.map.acl_busy = btinfo.lb2.acl_busy; 4923 b->status.map.inq_pag = btinfo.lb2.inq_pag; 4924 bt->inq_pag.now = btinfo.lb2.inq_pag; 4925 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 4926 4927 hfp->exist = btinfo.lb2.hfp; 4928 b->profile_cnt.now += (u8)hfp->exist; 4929 hid->exist = btinfo.lb2.hid; 4930 b->profile_cnt.now += (u8)hid->exist; 4931 a2dp->exist = btinfo.lb2.a2dp; 4932 b->profile_cnt.now += (u8)a2dp->exist; 4933 pan->active = btinfo.lb2.pan; 4934 4935 /* parse raw info low-Byte3 */ 4936 btinfo.val = bt->raw_info[BTC_BTINFO_L3]; 4937 if (btinfo.lb3.retry != 0) 4938 cx->cnt_bt[BTC_BCNT_RETRY]++; 4939 b->cqddr = btinfo.lb3.cqddr; 4940 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 4941 bt->inq = btinfo.lb3.inq; 4942 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 4943 bt->pag = btinfo.lb3.pag; 4944 4945 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 4946 /* parse raw info high-Byte0 */ 4947 btinfo.val = bt->raw_info[BTC_BTINFO_H0]; 4948 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 4949 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 4950 4951 /* parse raw info high-Byte1 */ 4952 btinfo.val = bt->raw_info[BTC_BTINFO_H1]; 4953 b->status.map.ble_connect = btinfo.hb1.ble_connect; 4954 if (btinfo.hb1.ble_connect) 4955 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); 4956 4957 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 4958 bt->reinit = btinfo.hb1.reinit; 4959 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 4960 b->relink.now = btinfo.hb1.relink; 4961 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 4962 bt->igno_wl = btinfo.hb1.igno_wl; 4963 4964 if (bt->igno_wl && !cx->wl.status.map.rf_off) 4965 _set_bt_ignore_wlan_act(rtwdev, false); 4966 4967 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); 4968 bt->ble_scan_en = btinfo.hb1.ble_scan; 4969 4970 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 4971 b->role_sw = btinfo.hb1.role_sw; 4972 4973 b->multi_link.now = btinfo.hb1.multi_link; 4974 4975 /* parse raw info high-Byte2 */ 4976 btinfo.val = bt->raw_info[BTC_BTINFO_H2]; 4977 pan->exist = btinfo.hb2.pan_active; 4978 b->profile_cnt.now += (u8)pan->exist; 4979 4980 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 4981 b->afh_update = btinfo.hb2.afh_update; 4982 a2dp->active = btinfo.hb2.a2dp_active; 4983 b->slave_role = btinfo.hb2.slave; 4984 hid->slot_info = btinfo.hb2.hid_slot; 4985 hid->pair_cnt = btinfo.hb2.hid_cnt; 4986 hid->type |= (hid->slot_info == BTC_HID_218 ? 4987 BTC_HID_218 : BTC_HID_418); 4988 /* parse raw info high-Byte3 */ 4989 btinfo.val = bt->raw_info[BTC_BTINFO_H3]; 4990 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 4991 4992 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 4993 cx->cnt_bt[BTC_BCNT_RATECHG]++; 4994 b->tx_3m = (u32)btinfo.hb3.tx_3m; 4995 4996 a2dp->sink = btinfo.hb3.a2dp_sink; 4997 4998 if (b->profile_cnt.now || b->status.map.ble_connect) 4999 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1); 5000 else 5001 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0); 5002 5003 if (!a2dp->exist_last && a2dp->exist) { 5004 a2dp->vendor_id = 0; 5005 a2dp->flush_time = 0; 5006 a2dp->play_latency = 1; 5007 ieee80211_queue_delayed_work(rtwdev->hw, 5008 &rtwdev->coex_bt_devinfo_work, 5009 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 5010 } 5011 5012 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 || 5013 a2dp->play_latency == 1)) 5014 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1); 5015 else 5016 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0); 5017 5018 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 5019 } 5020 5021 enum btc_wl_mode { 5022 BTC_WL_MODE_HT = 0, 5023 BTC_WL_MODE_VHT = 1, 5024 BTC_WL_MODE_HE = 2, 5025 BTC_WL_MODE_NUM, 5026 }; 5027 5028 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 5029 struct rtw89_sta *rtwsta, enum btc_role_state state) 5030 { 5031 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); 5032 const struct rtw89_chip_info *chip = rtwdev->chip; 5033 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 5034 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); 5035 struct rtw89_btc *btc = &rtwdev->btc; 5036 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5037 struct rtw89_btc_wl_link_info r = {0}; 5038 struct rtw89_btc_wl_link_info *wlinfo = NULL; 5039 u8 mode = 0; 5040 5041 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 5042 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5043 "[BTC], role is STA=%d\n", 5044 vif->type == NL80211_IFTYPE_STATION); 5045 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); 5046 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 5047 chan->band_type, chan->channel, chan->band_width); 5048 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 5049 state == BTC_ROLE_MSTS_STA_CONN_END); 5050 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5051 "[BTC], bcn_period=%d dtim_period=%d\n", 5052 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); 5053 5054 if (rtwsta) { 5055 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 5056 rtwsta->mac_id); 5057 5058 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5059 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 5060 sta->deflink.he_cap.has_he, 5061 sta->deflink.vht_cap.vht_supported, 5062 sta->deflink.ht_cap.ht_supported); 5063 if (sta->deflink.he_cap.has_he) 5064 mode |= BIT(BTC_WL_MODE_HE); 5065 if (sta->deflink.vht_cap.vht_supported) 5066 mode |= BIT(BTC_WL_MODE_VHT); 5067 if (sta->deflink.ht_cap.ht_supported) 5068 mode |= BIT(BTC_WL_MODE_HT); 5069 5070 r.mode = mode; 5071 } 5072 5073 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) 5074 return; 5075 5076 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5077 "[BTC], wifi_role=%d\n", rtwvif->wifi_role); 5078 5079 r.role = rtwvif->wifi_role; 5080 r.phy = rtwvif->phy_idx; 5081 r.pid = rtwvif->port; 5082 r.active = true; 5083 r.connected = MLME_LINKED; 5084 r.bcn_period = vif->bss_conf.beacon_int; 5085 r.dtim_period = vif->bss_conf.dtim_period; 5086 r.band = chan->band_type; 5087 r.ch = chan->channel; 5088 r.bw = chan->band_width; 5089 ether_addr_copy(r.mac_addr, rtwvif->mac_addr); 5090 5091 if (rtwsta && vif->type == NL80211_IFTYPE_STATION) 5092 r.mac_id = rtwsta->mac_id; 5093 5094 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 5095 5096 wlinfo = &wl->link_info[r.pid]; 5097 5098 memcpy(wlinfo, &r, sizeof(*wlinfo)); 5099 if (chip->chip_id == RTL8852A) 5100 _update_wl_info(rtwdev); 5101 else 5102 _update_wl_info_v1(rtwdev); 5103 5104 if (wlinfo->role == RTW89_WIFI_ROLE_STATION && 5105 wlinfo->connected == MLME_NO_LINK) 5106 btc->dm.leak_ap = 0; 5107 5108 if (state == BTC_ROLE_MSTS_STA_CONN_START) 5109 wl->status.map.connecting = 1; 5110 else 5111 wl->status.map.connecting = 0; 5112 5113 if (state == BTC_ROLE_MSTS_STA_DIS_CONN) 5114 wl->status.map._4way = false; 5115 5116 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 5117 } 5118 5119 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 5120 { 5121 const struct rtw89_chip_info *chip = rtwdev->chip; 5122 struct rtw89_btc *btc = &rtwdev->btc; 5123 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5124 u32 val; 5125 5126 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 5127 __func__, rf_state); 5128 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 5129 5130 switch (rf_state) { 5131 case BTC_RFCTRL_WL_OFF: 5132 wl->status.map.rf_off = 1; 5133 wl->status.map.lps = BTC_LPS_OFF; 5134 wl->status.map.busy = 0; 5135 break; 5136 case BTC_RFCTRL_FW_CTRL: 5137 wl->status.map.rf_off = 0; 5138 wl->status.map.lps = BTC_LPS_RF_OFF; 5139 wl->status.map.busy = 0; 5140 break; 5141 case BTC_RFCTRL_WL_ON: 5142 default: 5143 wl->status.map.rf_off = 0; 5144 wl->status.map.lps = BTC_LPS_OFF; 5145 break; 5146 } 5147 5148 if (rf_state == BTC_RFCTRL_WL_ON) { 5149 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0; 5150 rtw89_btc_fw_en_rpt(rtwdev, 5151 RPT_EN_MREG | RPT_EN_BT_VER_INFO, true); 5152 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 5153 _write_scbd(rtwdev, val, true); 5154 _update_bt_scbd(rtwdev, true); 5155 chip->ops->btc_init_cfg(rtwdev); 5156 } else { 5157 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false); 5158 if (rf_state == BTC_RFCTRL_WL_OFF) 5159 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 5160 } 5161 5162 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 5163 5164 wl->status.map.rf_off_pre = wl->status.map.rf_off; 5165 wl->status.map.lps_pre = wl->status.map.lps; 5166 } 5167 5168 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 5169 enum btc_wl_rfk_type type, 5170 enum btc_wl_rfk_state state) 5171 { 5172 struct rtw89_btc *btc = &rtwdev->btc; 5173 struct rtw89_btc_cx *cx = &btc->cx; 5174 struct rtw89_btc_wl_info *wl = &cx->wl; 5175 bool result = BTC_WRFK_REJECT; 5176 5177 wl->rfk_info.type = type; 5178 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 5179 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 5180 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 5181 5182 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5183 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 5184 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 5185 type, state); 5186 5187 switch (state) { 5188 case BTC_WRFK_START: 5189 result = _chk_wl_rfk_request(rtwdev); 5190 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP; 5191 5192 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result); 5193 5194 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 5195 break; 5196 case BTC_WRFK_ONESHOT_START: 5197 case BTC_WRFK_ONESHOT_STOP: 5198 if (wl->rfk_info.state == BTC_WRFK_STOP) { 5199 result = BTC_WRFK_REJECT; 5200 } else { 5201 result = BTC_WRFK_ALLOW; 5202 wl->rfk_info.state = state; 5203 } 5204 break; 5205 case BTC_WRFK_STOP: 5206 result = BTC_WRFK_ALLOW; 5207 wl->rfk_info.state = BTC_WRFK_STOP; 5208 5209 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 5210 cancel_delayed_work(&rtwdev->coex_rfk_chk_work); 5211 break; 5212 default: 5213 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5214 "[BTC], %s() warning state=%d\n", __func__, state); 5215 break; 5216 } 5217 5218 if (result == BTC_WRFK_ALLOW) { 5219 if (wl->rfk_info.state == BTC_WRFK_START || 5220 wl->rfk_info.state == BTC_WRFK_STOP) 5221 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 5222 5223 if (wl->rfk_info.state == BTC_WRFK_START) 5224 ieee80211_queue_delayed_work(rtwdev->hw, 5225 &rtwdev->coex_rfk_chk_work, 5226 RTW89_COEX_RFK_CHK_WORK_PERIOD); 5227 } 5228 5229 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5230 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 5231 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 5232 5233 return result == BTC_WRFK_ALLOW; 5234 } 5235 5236 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 5237 enum btc_wl_rfk_type type, 5238 enum btc_wl_rfk_state state) 5239 { 5240 u8 band; 5241 bool allow; 5242 int ret; 5243 5244 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 5245 5246 rtw89_debug(rtwdev, RTW89_DBG_RFK, 5247 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 5248 band == RTW89_BAND_2G ? "2G" : 5249 band == RTW89_BAND_5G ? "5G" : "6G", 5250 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 5251 type, 5252 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 5253 state == BTC_WRFK_STOP ? "RFK_STOP" : 5254 state == BTC_WRFK_START ? "RFK_START" : 5255 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 5256 "ONE-SHOT_STOP"); 5257 5258 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 5259 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 5260 return; 5261 } 5262 5263 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 5264 rtwdev, phy_map, type, state); 5265 if (ret) { 5266 rtw89_warn(rtwdev, "RFK notify timeout\n"); 5267 rtwdev->is_bt_iqk_timeout = true; 5268 } 5269 } 5270 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 5271 5272 struct rtw89_btc_wl_sta_iter_data { 5273 struct rtw89_dev *rtwdev; 5274 u8 busy_all; 5275 u8 dir_all; 5276 u8 rssi_map_all; 5277 bool is_sta_change; 5278 bool is_traffic_change; 5279 }; 5280 5281 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 5282 { 5283 struct rtw89_btc_wl_sta_iter_data *iter_data = 5284 (struct rtw89_btc_wl_sta_iter_data *)data; 5285 struct rtw89_dev *rtwdev = iter_data->rtwdev; 5286 struct rtw89_btc *btc = &rtwdev->btc; 5287 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5288 struct rtw89_btc_wl_link_info *link_info = NULL; 5289 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 5290 struct rtw89_traffic_stats *link_info_t = NULL; 5291 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 5292 struct rtw89_traffic_stats *stats = &rtwvif->stats; 5293 const struct rtw89_chip_info *chip = rtwdev->chip; 5294 u32 last_tx_rate, last_rx_rate; 5295 u16 last_tx_lvl, last_rx_lvl; 5296 u8 port = rtwvif->port; 5297 u8 rssi; 5298 u8 busy = 0; 5299 u8 dir = 0; 5300 u8 rssi_map = 0; 5301 u8 i = 0; 5302 bool is_sta_change = false, is_traffic_change = false; 5303 5304 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; 5305 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 5306 5307 link_info = &wl->link_info[port]; 5308 link_info->stat.traffic = rtwvif->stats; 5309 link_info_t = &link_info->stat.traffic; 5310 5311 if (link_info->connected == MLME_NO_LINK) { 5312 link_info->rx_rate_drop_cnt = 0; 5313 return; 5314 } 5315 5316 link_info->stat.rssi = rssi; 5317 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 5318 link_info->rssi_state[i] = 5319 _update_rssi_state(rtwdev, 5320 link_info->rssi_state[i], 5321 link_info->stat.rssi, 5322 chip->wl_rssi_thres[i]); 5323 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 5324 rssi_map |= BIT(i); 5325 5326 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED && 5327 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 5328 is_sta_change = true; 5329 } 5330 iter_data->rssi_map_all |= rssi_map; 5331 5332 last_tx_rate = link_info_t->tx_rate; 5333 last_rx_rate = link_info_t->rx_rate; 5334 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 5335 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 5336 5337 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 5338 stats->rx_tfc_lv != RTW89_TFC_IDLE) 5339 busy = 1; 5340 5341 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 5342 dir = RTW89_TFC_UL; 5343 else 5344 dir = RTW89_TFC_DL; 5345 5346 link_info = &wl->link_info[port]; 5347 if (link_info->busy != busy || link_info->dir != dir) { 5348 is_sta_change = true; 5349 link_info->busy = busy; 5350 link_info->dir = dir; 5351 } 5352 5353 iter_data->busy_all |= busy; 5354 iter_data->dir_all |= BIT(dir); 5355 5356 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 5357 last_rx_rate > RTW89_HW_RATE_CCK2 && 5358 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 5359 link_info->rx_rate_drop_cnt++; 5360 5361 if (last_tx_rate != rtwsta->ra_report.hw_rate || 5362 last_rx_rate != rtwsta->rx_hw_rate || 5363 last_tx_lvl != link_info_t->tx_tfc_lv || 5364 last_rx_lvl != link_info_t->rx_tfc_lv) 5365 is_traffic_change = true; 5366 5367 link_info_t->tx_rate = rtwsta->ra_report.hw_rate; 5368 link_info_t->rx_rate = rtwsta->rx_hw_rate; 5369 5370 wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv; 5371 wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv; 5372 wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate; 5373 wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate; 5374 5375 if (is_sta_change) 5376 iter_data->is_sta_change = true; 5377 5378 if (is_traffic_change) 5379 iter_data->is_traffic_change = true; 5380 } 5381 5382 #define BTC_NHM_CHK_INTVL 20 5383 5384 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 5385 { 5386 struct rtw89_btc *btc = &rtwdev->btc; 5387 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5388 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 5389 u8 i; 5390 5391 ieee80211_iterate_stations_atomic(rtwdev->hw, 5392 rtw89_btc_ntfy_wl_sta_iter, 5393 &data); 5394 5395 wl->rssi_level = 0; 5396 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 5397 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 5398 /* set RSSI level 4 ~ 0 if rssi bit map match */ 5399 if (data.rssi_map_all & BIT(i - 1)) { 5400 wl->rssi_level = i; 5401 break; 5402 } 5403 } 5404 5405 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 5406 __func__, !!wl->status.map.busy); 5407 5408 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 5409 5410 if (data.is_traffic_change) 5411 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5412 if (data.is_sta_change) { 5413 wl->status.map.busy = data.busy_all; 5414 wl->status.map.traffic_dir = data.dir_all; 5415 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 5416 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 5417 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 5418 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 5419 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 5420 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 5421 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 5422 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 5423 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 5424 } 5425 } 5426 5427 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 5428 u32 len, u8 class, u8 func) 5429 { 5430 struct rtw89_btc *btc = &rtwdev->btc; 5431 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 5432 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 5433 5434 len -= RTW89_C2H_HEADER_LEN; 5435 5436 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5437 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 5438 __func__, len, class, func); 5439 5440 if (class != BTFC_FW_EVENT) 5441 return; 5442 5443 switch (func) { 5444 case BTF_EVNT_RPT: 5445 case BTF_EVNT_BUF_OVERFLOW: 5446 pfwinfo->event[func]++; 5447 /* Don't need rtw89_leave_ps_mode() */ 5448 btc_fw_event(rtwdev, func, buf, len); 5449 break; 5450 case BTF_EVNT_BT_INFO: 5451 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5452 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 5453 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++; 5454 _update_bt_info(rtwdev, buf, len); 5455 break; 5456 case BTF_EVNT_BT_SCBD: 5457 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5458 "[BTC], handle C2H BT SCBD with data %8ph\n", buf); 5459 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++; 5460 _update_bt_scbd(rtwdev, false); 5461 break; 5462 case BTF_EVNT_BT_PSD: 5463 break; 5464 case BTF_EVNT_BT_REG: 5465 btc->dbg.rb_done = true; 5466 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 5467 5468 break; 5469 case BTF_EVNT_C2H_LOOPBACK: 5470 btc->dbg.rb_done = true; 5471 btc->dbg.rb_val = buf[0]; 5472 break; 5473 case BTF_EVNT_CX_RUNINFO: 5474 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 5475 break; 5476 } 5477 } 5478 5479 #define BTC_CX_FW_OFFLOAD 0 5480 5481 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5482 { 5483 const struct rtw89_chip_info *chip = rtwdev->chip; 5484 struct rtw89_hal *hal = &rtwdev->hal; 5485 struct rtw89_btc *btc = &rtwdev->btc; 5486 struct rtw89_btc_dm *dm = &btc->dm; 5487 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5488 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5489 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 5490 5491 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 5492 return; 5493 5494 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 5495 5496 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n", 5497 chip->chip_id); 5498 5499 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 5500 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 5501 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 5502 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 5503 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ", 5504 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch); 5505 5506 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD) 5507 dm->error.map.offload_mismatch = true; 5508 else 5509 dm->error.map.offload_mismatch = false; 5510 5511 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 5512 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 5513 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 5514 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 5515 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)", 5516 ver_main, ver_sub, ver_hotfix, id_branch); 5517 5518 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 5519 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 5520 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 5521 seq_printf(m, "(%s, desired:%d.%d.%d), ", 5522 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 5523 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 5524 5525 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n", 5526 bt->ver_info.fw_coex, 5527 (bt->ver_info.fw_coex >= chip->btcx_desired ? 5528 "Match" : "Mismatch"), chip->btcx_desired); 5529 5530 if (bt->enable.now && bt->ver_info.fw == 0) 5531 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 5532 else 5533 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 5534 5535 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 5536 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 5537 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 5538 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 5539 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n", 5540 "[sub_module]", 5541 ver_main, ver_sub, ver_hotfix, id_branch, 5542 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 5543 5544 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 5545 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type, 5546 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num, 5547 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ? 5548 "1Ant_Pos:S1, " : "1Ant_Pos:S0, "))); 5549 5550 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 5551 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, 5552 hal->rx_nss); 5553 } 5554 5555 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5556 { 5557 struct rtw89_btc *btc = &rtwdev->btc; 5558 struct rtw89_btc_wl_link_info *plink = NULL; 5559 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5560 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5561 struct rtw89_traffic_stats *t; 5562 u8 i; 5563 5564 if (rtwdev->dbcc_en) { 5565 seq_printf(m, 5566 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ", 5567 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0], 5568 wl_dinfo->scan_band[RTW89_PHY_0], 5569 wl_dinfo->real_band[RTW89_PHY_0]); 5570 seq_printf(m, 5571 "PHY1_band(op:%d/scan:%d/real:%d)\n", 5572 wl_dinfo->op_band[RTW89_PHY_1], 5573 wl_dinfo->scan_band[RTW89_PHY_1], 5574 wl_dinfo->real_band[RTW89_PHY_1]); 5575 } 5576 5577 for (i = 0; i < RTW89_PORT_NUM; i++) { 5578 plink = &btc->cx.wl.link_info[i]; 5579 5580 if (!plink->active) 5581 continue; 5582 5583 seq_printf(m, 5584 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 5585 plink->pid, (u32)plink->role, plink->phy, 5586 (u32)plink->connected, plink->client_cnt - 1, 5587 (u32)plink->mode, plink->ch, (u32)plink->bw); 5588 5589 if (plink->connected == MLME_NO_LINK) 5590 continue; 5591 5592 seq_printf(m, 5593 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 5594 plink->mac_id, plink->tx_time, plink->tx_retry); 5595 5596 seq_printf(m, 5597 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 5598 plink->pid, 110 - plink->stat.rssi, 5599 plink->stat.rssi, plink->busy, 5600 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 5601 5602 t = &plink->stat.traffic; 5603 5604 seq_printf(m, 5605 "tx[rate:%d/busy_level:%d], ", 5606 (u32)t->tx_rate, t->tx_tfc_lv); 5607 5608 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n", 5609 (u32)t->rx_rate, 5610 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 5611 } 5612 } 5613 5614 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5615 { 5616 const struct rtw89_chip_info *chip = rtwdev->chip; 5617 struct rtw89_btc *btc = &rtwdev->btc; 5618 struct rtw89_btc_cx *cx = &btc->cx; 5619 struct rtw89_btc_wl_info *wl = &cx->wl; 5620 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5621 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5622 u8 mode; 5623 5624 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 5625 return; 5626 5627 seq_puts(m, "========== [WL Status] ==========\n"); 5628 5629 if (chip->chip_id == RTL8852A) 5630 mode = wl_rinfo->link_mode; 5631 else 5632 mode = wl_rinfo_v1->link_mode; 5633 5634 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode); 5635 5636 seq_printf(m, 5637 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 5638 wl->status.map.rf_off, wl->status.map.lps, 5639 wl->status.map.scan ? "Y" : "N", 5640 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 5641 5642 seq_printf(m, 5643 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n", 5644 wl->status.map.connecting ? "Y" : "N", 5645 wl->status.map.roaming ? "Y" : "N", 5646 wl->status.map._4way ? "Y" : "N", 5647 wl->status.map.init_ok ? "Y" : "N"); 5648 5649 _show_wl_role_info(rtwdev, m); 5650 } 5651 5652 enum btc_bt_a2dp_type { 5653 BTC_A2DP_LEGACY = 0, 5654 BTC_A2DP_TWS_SNIFF = 1, 5655 BTC_A2DP_TWS_RELAY = 2, 5656 }; 5657 5658 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5659 { 5660 struct rtw89_btc *btc = &rtwdev->btc; 5661 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 5662 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 5663 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 5664 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 5665 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 5666 5667 if (hfp.exist) { 5668 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 5669 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 5670 bt_linfo->sut_pwr_level[0], 5671 bt_linfo->golden_rx_shift[0]); 5672 } 5673 5674 if (hid.exist) { 5675 seq_printf(m, 5676 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 5677 "[HID]", 5678 hid.type & BTC_HID_218 ? "2/18," : "", 5679 hid.type & BTC_HID_418 ? "4/18," : "", 5680 hid.type & BTC_HID_BLE ? "BLE," : "", 5681 hid.type & BTC_HID_RCU ? "RCU," : "", 5682 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 5683 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 5684 bt_linfo->golden_rx_shift[1]); 5685 } 5686 5687 if (a2dp.exist) { 5688 seq_printf(m, 5689 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 5690 "[A2DP]", 5691 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 5692 a2dp.bitpool, a2dp.flush_time); 5693 5694 seq_printf(m, 5695 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 5696 a2dp.vendor_id, a2dp.device_name, 5697 bt_linfo->sut_pwr_level[2], 5698 bt_linfo->golden_rx_shift[2]); 5699 } 5700 5701 if (pan.exist) { 5702 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n", 5703 "[PAN]", 5704 bt_linfo->sut_pwr_level[3], 5705 bt_linfo->golden_rx_shift[3]); 5706 } 5707 } 5708 5709 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5710 { 5711 struct rtw89_btc *btc = &rtwdev->btc; 5712 struct rtw89_btc_cx *cx = &btc->cx; 5713 struct rtw89_btc_bt_info *bt = &cx->bt; 5714 struct rtw89_btc_wl_info *wl = &cx->wl; 5715 struct rtw89_btc_module *module = &btc->mdinfo; 5716 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 5717 u8 *afh = bt_linfo->afh_map; 5718 5719 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 5720 return; 5721 5722 seq_puts(m, "========== [BT Status] ==========\n"); 5723 5724 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ", 5725 "[status]", bt->enable.now ? "Y" : "N", 5726 bt->btg_type ? "Y" : "N", 5727 (bt->enable.now && (bt->btg_type != module->bt_pos) ? 5728 "(efuse-mismatch!!)" : ""), 5729 (bt_linfo->status.map.connect ? "Y" : "N")); 5730 5731 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 5732 bt->igno_wl ? "Y" : "N", 5733 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 5734 5735 seq_printf(m, " %-15s : profile:%s%s%s%s%s ", 5736 "[profile]", 5737 (bt_linfo->profile_cnt.now == 0) ? "None," : "", 5738 bt_linfo->hfp_desc.exist ? "HFP," : "", 5739 bt_linfo->hid_desc.exist ? "HID," : "", 5740 bt_linfo->a2dp_desc.exist ? 5741 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 5742 bt_linfo->pan_desc.exist ? "PAN," : ""); 5743 5744 seq_printf(m, 5745 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 5746 bt_linfo->multi_link.now ? "Y" : "N", 5747 bt_linfo->slave_role ? "Slave" : "Master", 5748 bt_linfo->status.map.ble_connect ? "Y" : "N", 5749 bt_linfo->cqddr ? "Y" : "N", 5750 bt_linfo->a2dp_desc.active ? "Y" : "N", 5751 bt_linfo->pan_desc.active ? "Y" : "N"); 5752 5753 seq_printf(m, 5754 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s", 5755 "[link]", bt_linfo->rssi - 100, 5756 bt_linfo->tx_3m ? 3 : 2, 5757 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 5758 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 5759 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 5760 5761 seq_printf(m, 5762 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 5763 bt_linfo->relink.now ? " ReLink!!" : "", 5764 afh[0], afh[1], afh[2], afh[3], afh[4], 5765 afh[5], afh[6], afh[7], afh[8], afh[9]); 5766 5767 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n", 5768 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw); 5769 5770 seq_printf(m, 5771 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 5772 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY], 5773 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG], 5774 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]); 5775 5776 seq_printf(m, 5777 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 5778 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH], 5779 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ], 5780 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]); 5781 5782 _show_bt_profile_info(rtwdev, m); 5783 5784 seq_printf(m, 5785 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 5786 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 5787 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 5788 bt->raw_info[7], 5789 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 5790 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 5791 cx->cnt_bt[BTC_BCNT_INFOSAME]); 5792 5793 seq_printf(m, 5794 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n", 5795 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX], 5796 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX], 5797 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]); 5798 } 5799 5800 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 5801 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 5802 #define CASE_BTC_POLICY_STR(e) \ 5803 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 5804 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 5805 5806 static const char *steps_to_str(u16 step) 5807 { 5808 switch (step) { 5809 CASE_BTC_RSN_STR(NONE); 5810 CASE_BTC_RSN_STR(NTFY_INIT); 5811 CASE_BTC_RSN_STR(NTFY_SWBAND); 5812 CASE_BTC_RSN_STR(NTFY_WL_STA); 5813 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 5814 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 5815 CASE_BTC_RSN_STR(NTFY_WL_RFK); 5816 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 5817 CASE_BTC_RSN_STR(NTFY_SCAN_START); 5818 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 5819 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 5820 CASE_BTC_RSN_STR(NTFY_POWEROFF); 5821 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 5822 CASE_BTC_RSN_STR(CMD_SET_COEX); 5823 CASE_BTC_RSN_STR(ACT1_WORK); 5824 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 5825 CASE_BTC_RSN_STR(RFK_CHK_WORK); 5826 5827 CASE_BTC_ACT_STR(NONE); 5828 CASE_BTC_ACT_STR(WL_ONLY); 5829 CASE_BTC_ACT_STR(WL_5G); 5830 CASE_BTC_ACT_STR(WL_OTHER); 5831 CASE_BTC_ACT_STR(WL_IDLE); 5832 CASE_BTC_ACT_STR(WL_NC); 5833 CASE_BTC_ACT_STR(WL_RFK); 5834 CASE_BTC_ACT_STR(WL_INIT); 5835 CASE_BTC_ACT_STR(WL_OFF); 5836 CASE_BTC_ACT_STR(FREERUN); 5837 CASE_BTC_ACT_STR(BT_WHQL); 5838 CASE_BTC_ACT_STR(BT_RFK); 5839 CASE_BTC_ACT_STR(BT_OFF); 5840 CASE_BTC_ACT_STR(BT_IDLE); 5841 CASE_BTC_ACT_STR(BT_HFP); 5842 CASE_BTC_ACT_STR(BT_HID); 5843 CASE_BTC_ACT_STR(BT_A2DP); 5844 CASE_BTC_ACT_STR(BT_A2DPSINK); 5845 CASE_BTC_ACT_STR(BT_PAN); 5846 CASE_BTC_ACT_STR(BT_A2DP_HID); 5847 CASE_BTC_ACT_STR(BT_A2DP_PAN); 5848 CASE_BTC_ACT_STR(BT_PAN_HID); 5849 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 5850 CASE_BTC_ACT_STR(WL_25G_MCC); 5851 CASE_BTC_ACT_STR(WL_2G_MCC); 5852 CASE_BTC_ACT_STR(WL_2G_SCC); 5853 CASE_BTC_ACT_STR(WL_2G_AP); 5854 CASE_BTC_ACT_STR(WL_2G_GO); 5855 CASE_BTC_ACT_STR(WL_2G_GC); 5856 CASE_BTC_ACT_STR(WL_2G_NAN); 5857 5858 CASE_BTC_POLICY_STR(OFF_BT); 5859 CASE_BTC_POLICY_STR(OFF_WL); 5860 CASE_BTC_POLICY_STR(OFF_EQ0); 5861 CASE_BTC_POLICY_STR(OFF_EQ1); 5862 CASE_BTC_POLICY_STR(OFF_EQ2); 5863 CASE_BTC_POLICY_STR(OFF_EQ3); 5864 CASE_BTC_POLICY_STR(OFF_BWB0); 5865 CASE_BTC_POLICY_STR(OFF_BWB1); 5866 CASE_BTC_POLICY_STR(OFF_BWB2); 5867 CASE_BTC_POLICY_STR(OFF_BWB3); 5868 CASE_BTC_POLICY_STR(OFFB_BWB0); 5869 CASE_BTC_POLICY_STR(OFFE_DEF); 5870 CASE_BTC_POLICY_STR(OFFE_DEF2); 5871 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 5872 CASE_BTC_POLICY_STR(OFFE_2GISOB); 5873 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 5874 CASE_BTC_POLICY_STR(OFFE_WL); 5875 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 5876 CASE_BTC_POLICY_STR(FIX_TD3030); 5877 CASE_BTC_POLICY_STR(FIX_TD5050); 5878 CASE_BTC_POLICY_STR(FIX_TD2030); 5879 CASE_BTC_POLICY_STR(FIX_TD4010); 5880 CASE_BTC_POLICY_STR(FIX_TD7010); 5881 CASE_BTC_POLICY_STR(FIX_TD2060); 5882 CASE_BTC_POLICY_STR(FIX_TD3060); 5883 CASE_BTC_POLICY_STR(FIX_TD2080); 5884 CASE_BTC_POLICY_STR(FIX_TDW1B1); 5885 CASE_BTC_POLICY_STR(FIX_TD4020); 5886 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 5887 CASE_BTC_POLICY_STR(PFIX_TD3030); 5888 CASE_BTC_POLICY_STR(PFIX_TD5050); 5889 CASE_BTC_POLICY_STR(PFIX_TD2030); 5890 CASE_BTC_POLICY_STR(PFIX_TD2060); 5891 CASE_BTC_POLICY_STR(PFIX_TD3070); 5892 CASE_BTC_POLICY_STR(PFIX_TD2080); 5893 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 5894 CASE_BTC_POLICY_STR(AUTO_TD50B1); 5895 CASE_BTC_POLICY_STR(AUTO_TD60B1); 5896 CASE_BTC_POLICY_STR(AUTO_TD20B1); 5897 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 5898 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 5899 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 5900 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 5901 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 5902 CASE_BTC_POLICY_STR(AUTO2_TD3050); 5903 CASE_BTC_POLICY_STR(AUTO2_TD3070); 5904 CASE_BTC_POLICY_STR(AUTO2_TD5050); 5905 CASE_BTC_POLICY_STR(AUTO2_TD6060); 5906 CASE_BTC_POLICY_STR(AUTO2_TD2080); 5907 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 5908 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 5909 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 5910 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 5911 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 5912 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 5913 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 5914 default: 5915 return "unknown step"; 5916 } 5917 } 5918 5919 static const char *id_to_slot(u32 id) 5920 { 5921 switch (id) { 5922 CASE_BTC_SLOT_STR(OFF); 5923 CASE_BTC_SLOT_STR(B2W); 5924 CASE_BTC_SLOT_STR(W1); 5925 CASE_BTC_SLOT_STR(W2); 5926 CASE_BTC_SLOT_STR(W2B); 5927 CASE_BTC_SLOT_STR(B1); 5928 CASE_BTC_SLOT_STR(B2); 5929 CASE_BTC_SLOT_STR(B3); 5930 CASE_BTC_SLOT_STR(B4); 5931 CASE_BTC_SLOT_STR(LK); 5932 CASE_BTC_SLOT_STR(BLK); 5933 CASE_BTC_SLOT_STR(E2G); 5934 CASE_BTC_SLOT_STR(E5G); 5935 CASE_BTC_SLOT_STR(EBT); 5936 CASE_BTC_SLOT_STR(ENULL); 5937 CASE_BTC_SLOT_STR(WLK); 5938 CASE_BTC_SLOT_STR(W1FDD); 5939 CASE_BTC_SLOT_STR(B1FDD); 5940 default: 5941 return "unknown"; 5942 } 5943 } 5944 5945 static 5946 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data, 5947 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 5948 { 5949 u8 i; 5950 u8 cur_index; 5951 5952 for (i = 0; i < len ; i++) { 5953 if ((i % seg_len) == 0) 5954 seq_printf(m, " %-15s : ", prefix); 5955 cur_index = (start_idx + i) % ring_len; 5956 if (i % 3 == 0) 5957 seq_printf(m, "-> %-20s", 5958 steps_to_str(*(data + cur_index))); 5959 else if (i % 3 == 1) 5960 seq_printf(m, "-> %-15s", 5961 steps_to_str(*(data + cur_index))); 5962 else 5963 seq_printf(m, "-> %-13s", 5964 steps_to_str(*(data + cur_index))); 5965 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 5966 seq_puts(m, "\n"); 5967 } 5968 } 5969 5970 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m) 5971 { 5972 struct rtw89_btc *btc = &rtwdev->btc; 5973 struct rtw89_btc_dm *dm = &btc->dm; 5974 u8 start_idx; 5975 u8 len; 5976 5977 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 5978 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 5979 5980 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx, 5981 ARRAY_SIZE(dm->dm_step.step)); 5982 } 5983 5984 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5985 { 5986 struct rtw89_btc *btc = &rtwdev->btc; 5987 struct rtw89_btc_module *module = &btc->mdinfo; 5988 struct rtw89_btc_dm *dm = &btc->dm; 5989 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5990 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5991 5992 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 5993 return; 5994 5995 seq_printf(m, "========== [Mechanism Status %s] ==========\n", 5996 (btc->ctrl.manual ? "(Manual)" : "(Auto)")); 5997 5998 seq_printf(m, 5999 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n", 6000 "[status]", 6001 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated", 6002 steps_to_str(dm->run_reason), 6003 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 6004 FIELD_GET(GENMASK(7, 0), dm->set_ant_path), 6005 dm->cnt_dm[BTC_DCNT_RUN]); 6006 6007 _show_dm_step(rtwdev, m); 6008 6009 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 6010 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt, 6011 dm->freerun, btc->lps, dm->wl_mimo_ps); 6012 6013 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap, 6014 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 6015 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 6016 "" : "(Mismatch!!)")); 6017 6018 if (dm->rf_trx_para.wl_tx_power == 0xff) 6019 seq_printf(m, 6020 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ", 6021 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level); 6022 6023 else 6024 seq_printf(m, 6025 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ", 6026 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level, 6027 dm->rf_trx_para.wl_tx_power); 6028 6029 seq_printf(m, 6030 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n", 6031 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power, 6032 dm->rf_trx_para.bt_rx_gain, 6033 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx); 6034 6035 seq_printf(m, 6036 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 6037 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time, 6038 dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri); 6039 } 6040 6041 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m) 6042 { 6043 const struct rtw89_chip_info *chip = rtwdev->chip; 6044 struct rtw89_btc *btc = &rtwdev->btc; 6045 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6046 struct rtw89_btc_fbtc_cysta *pcysta; 6047 struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1; 6048 u32 except_cnt, exception_map; 6049 6050 if (chip->chip_id == RTL8852A) { 6051 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 6052 except_cnt = le32_to_cpu(pcysta->except_cnt); 6053 exception_map = le32_to_cpu(pcysta->exception); 6054 } else { 6055 pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1; 6056 except_cnt = le32_to_cpu(pcysta_v1->except_cnt); 6057 exception_map = le32_to_cpu(pcysta_v1->except_map); 6058 } 6059 6060 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 6061 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 6062 return; 6063 6064 seq_printf(m, " %-15s : ", "[error]"); 6065 6066 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 6067 seq_printf(m, 6068 "overflow-cnt: %d, ", 6069 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 6070 } 6071 6072 if (pfwinfo->len_mismch) { 6073 seq_printf(m, 6074 "len-mismatch: 0x%x, ", 6075 pfwinfo->len_mismch); 6076 } 6077 6078 if (pfwinfo->fver_mismch) { 6079 seq_printf(m, 6080 "fver-mismatch: 0x%x, ", 6081 pfwinfo->fver_mismch); 6082 } 6083 6084 /* cycle statistics exceptions */ 6085 if (exception_map || except_cnt) { 6086 seq_printf(m, 6087 "exception-type: 0x%x, exception-cnt = %d", 6088 exception_map, except_cnt); 6089 } 6090 seq_puts(m, "\n"); 6091 } 6092 6093 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m) 6094 { 6095 const struct rtw89_chip_info *chip = rtwdev->chip; 6096 struct rtw89_btc *btc = &rtwdev->btc; 6097 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6098 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6099 struct rtw89_btc_fbtc_tdma *t = NULL; 6100 struct rtw89_btc_fbtc_slot *s = NULL; 6101 struct rtw89_btc_dm *dm = &btc->dm; 6102 u8 i, cnt = 0; 6103 6104 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 6105 if (!pcinfo->valid) 6106 return; 6107 6108 if (chip->chip_id == RTL8852A) 6109 t = &pfwinfo->rpt_fbtc_tdma.finfo; 6110 else 6111 t = &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma; 6112 6113 seq_printf(m, 6114 " %-15s : ", "[tdma_policy]"); 6115 seq_printf(m, 6116 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ", 6117 (u32)t->type, 6118 t->rxflctrl, t->txpause); 6119 6120 seq_printf(m, 6121 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ", 6122 t->wtgle_n, t->leak_n, t->ext_ctrl); 6123 6124 seq_printf(m, 6125 "policy_type:%d", 6126 (u32)btc->policy_type); 6127 6128 s = pfwinfo->rpt_fbtc_slots.finfo.slot; 6129 6130 for (i = 0; i < CXST_MAX; i++) { 6131 if (dm->update_slot_map == BIT(CXST_MAX) - 1) 6132 break; 6133 6134 if (!(dm->update_slot_map & BIT(i))) 6135 continue; 6136 6137 if (cnt % 6 == 0) 6138 seq_printf(m, 6139 " %-15s : %d[%d/0x%x/%d]", 6140 "[slot_policy]", 6141 (u32)i, 6142 s[i].dur, s[i].cxtbl, s[i].cxtype); 6143 else 6144 seq_printf(m, 6145 ", %d[%d/0x%x/%d]", 6146 (u32)i, 6147 s[i].dur, s[i].cxtbl, s[i].cxtype); 6148 if (cnt % 6 == 5) 6149 seq_puts(m, "\n"); 6150 cnt++; 6151 } 6152 seq_puts(m, "\n"); 6153 } 6154 6155 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m) 6156 { 6157 struct rtw89_btc *btc = &rtwdev->btc; 6158 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6159 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6160 struct rtw89_btc_fbtc_slots *pslots = NULL; 6161 struct rtw89_btc_fbtc_slot s; 6162 u8 i = 0; 6163 6164 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 6165 if (!pcinfo->valid) 6166 return; 6167 6168 pslots = &pfwinfo->rpt_fbtc_slots.finfo; 6169 6170 for (i = 0; i < CXST_MAX; i++) { 6171 s = pslots->slot[i]; 6172 if (i % 6 == 0) 6173 seq_printf(m, 6174 " %-15s : %02d[%03d/0x%x/%d]", 6175 "[slot_list]", 6176 (u32)i, 6177 s.dur, s.cxtbl, s.cxtype); 6178 else 6179 seq_printf(m, 6180 ", %02d[%03d/0x%x/%d]", 6181 (u32)i, 6182 s.dur, s.cxtbl, s.cxtype); 6183 if (i % 6 == 5) 6184 seq_puts(m, "\n"); 6185 } 6186 } 6187 6188 static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m) 6189 { 6190 struct rtw89_btc *btc = &rtwdev->btc; 6191 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6192 struct rtw89_btc_dm *dm = &btc->dm; 6193 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 6194 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6195 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL; 6196 struct rtw89_btc_fbtc_cysta_cpu pcysta[1]; 6197 union rtw89_btc_fbtc_rxflct r; 6198 u8 i, cnt = 0, slot_pair; 6199 u16 cycle, c_begin, c_end, store_index; 6200 6201 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 6202 if (!pcinfo->valid) 6203 return; 6204 6205 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo; 6206 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta); 6207 seq_printf(m, 6208 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 6209 "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL], 6210 pcysta->bcn_cnt[CXBCN_ALL_OK], 6211 pcysta->bcn_cnt[CXBCN_BT_SLOT], 6212 pcysta->bcn_cnt[CXBCN_BT_OK]); 6213 6214 for (i = 0; i < CXST_MAX; i++) { 6215 if (!pcysta->slot_cnt[i]) 6216 continue; 6217 seq_printf(m, 6218 ", %d:%d", (u32)i, pcysta->slot_cnt[i]); 6219 } 6220 6221 if (dm->tdma_now.rxflctrl) { 6222 seq_printf(m, 6223 ", leak_rx:%d", pcysta->leakrx_cnt); 6224 } 6225 6226 if (pcysta->collision_cnt) { 6227 seq_printf(m, 6228 ", collision:%d", pcysta->collision_cnt); 6229 } 6230 6231 if (pcysta->skip_cnt) { 6232 seq_printf(m, 6233 ", skip:%d", pcysta->skip_cnt); 6234 } 6235 seq_puts(m, "\n"); 6236 6237 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 6238 "[cycle_time]", 6239 pcysta->tavg_cycle[CXT_WL], 6240 pcysta->tavg_cycle[CXT_BT], 6241 pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000); 6242 seq_printf(m, 6243 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 6244 pcysta->tmax_cycle[CXT_WL], 6245 pcysta->tmax_cycle[CXT_BT], 6246 pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000); 6247 seq_printf(m, 6248 ", maxdiff_t[wl:%d/bt:%d]\n", 6249 pcysta->tmaxdiff_cycle[CXT_WL], 6250 pcysta->tmaxdiff_cycle[CXT_BT]); 6251 6252 if (pcysta->cycles == 0) 6253 return; 6254 6255 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 6256 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 6257 6258 if (pcysta->cycles <= slot_pair) 6259 c_begin = 1; 6260 else 6261 c_begin = pcysta->cycles - slot_pair + 1; 6262 6263 c_end = pcysta->cycles; 6264 6265 for (cycle = c_begin; cycle <= c_end; cycle++) { 6266 cnt++; 6267 store_index = ((cycle - 1) % slot_pair) * 2; 6268 6269 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 6270 seq_printf(m, 6271 " %-15s : ->b%02d->w%02d", "[cycle_step]", 6272 pcysta->tslot_cycle[store_index], 6273 pcysta->tslot_cycle[store_index + 1]); 6274 else 6275 seq_printf(m, 6276 "->b%02d->w%02d", 6277 pcysta->tslot_cycle[store_index], 6278 pcysta->tslot_cycle[store_index + 1]); 6279 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 6280 seq_puts(m, "\n"); 6281 } 6282 6283 if (a2dp->exist) { 6284 seq_printf(m, 6285 " %-15s : a2dp_ept:%d, a2dp_late:%d", 6286 "[a2dp_t_sta]", 6287 pcysta->a2dpept, pcysta->a2dpeptto); 6288 6289 seq_printf(m, 6290 ", avg_t:%d, max_t:%d", 6291 pcysta->tavg_a2dpept, pcysta->tmax_a2dpept); 6292 r.val = dm->tdma_now.rxflctrl; 6293 6294 if (r.type && r.tgln_n) { 6295 seq_printf(m, 6296 ", cycle[PSTDMA:%d/TDMA:%d], ", 6297 pcysta->cycles_a2dp[CXT_FLCTRL_ON], 6298 pcysta->cycles_a2dp[CXT_FLCTRL_OFF]); 6299 6300 seq_printf(m, 6301 "avg_t[PSTDMA:%d/TDMA:%d], ", 6302 pcysta->tavg_a2dp[CXT_FLCTRL_ON], 6303 pcysta->tavg_a2dp[CXT_FLCTRL_OFF]); 6304 6305 seq_printf(m, 6306 "max_t[PSTDMA:%d/TDMA:%d]", 6307 pcysta->tmax_a2dp[CXT_FLCTRL_ON], 6308 pcysta->tmax_a2dp[CXT_FLCTRL_OFF]); 6309 } 6310 seq_puts(m, "\n"); 6311 } 6312 } 6313 6314 static void _show_fbtc_cysta_v1(struct rtw89_dev *rtwdev, struct seq_file *m) 6315 { 6316 struct rtw89_btc *btc = &rtwdev->btc; 6317 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 6318 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6319 struct rtw89_btc_dm *dm = &btc->dm; 6320 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 6321 struct rtw89_btc_fbtc_cysta_v1 *pcysta; 6322 struct rtw89_btc_rpt_cmn_info *pcinfo; 6323 u8 i, cnt = 0, slot_pair, divide_cnt; 6324 u16 cycle, c_begin, c_end, store_index; 6325 6326 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 6327 if (!pcinfo->valid) 6328 return; 6329 6330 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo_v1; 6331 seq_printf(m, 6332 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 6333 "[cycle_cnt]", 6334 le16_to_cpu(pcysta->cycles), 6335 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 6336 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 6337 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 6338 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 6339 6340 for (i = 0; i < CXST_MAX; i++) { 6341 if (!le32_to_cpu(pcysta->slot_cnt[i])) 6342 continue; 6343 6344 seq_printf(m, ", %s:%d", id_to_slot(i), 6345 le32_to_cpu(pcysta->slot_cnt[i])); 6346 } 6347 6348 if (dm->tdma_now.rxflctrl) 6349 seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 6350 6351 if (le32_to_cpu(pcysta->collision_cnt)) 6352 seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt)); 6353 6354 if (le32_to_cpu(pcysta->skip_cnt)) 6355 seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt)); 6356 6357 seq_puts(m, "\n"); 6358 6359 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 6360 "[cycle_time]", 6361 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 6362 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 6363 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 6364 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 6365 seq_printf(m, 6366 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 6367 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 6368 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 6369 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 6370 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 6371 seq_printf(m, 6372 ", maxdiff_t[wl:%d/bt:%d]\n", 6373 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 6374 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 6375 6376 cycle = le16_to_cpu(pcysta->cycles); 6377 if (cycle == 0) 6378 return; 6379 6380 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 6381 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 6382 6383 if (cycle <= slot_pair) 6384 c_begin = 1; 6385 else 6386 c_begin = cycle - slot_pair + 1; 6387 6388 c_end = cycle; 6389 6390 if (a2dp->exist) 6391 divide_cnt = 3; 6392 else 6393 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 6394 6395 for (cycle = c_begin; cycle <= c_end; cycle++) { 6396 cnt++; 6397 store_index = ((cycle - 1) % slot_pair) * 2; 6398 6399 if (cnt % divide_cnt == 1) { 6400 seq_printf(m, "\n\r %-15s : ", "[cycle_step]"); 6401 } else { 6402 seq_printf(m, "->b%02d", 6403 le16_to_cpu(pcysta->slot_step_time[store_index])); 6404 if (a2dp->exist) { 6405 a2dp_trx = &pcysta->a2dp_trx[store_index]; 6406 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 6407 a2dp_trx->empty_cnt, 6408 a2dp_trx->retry_cnt, 6409 a2dp_trx->tx_rate ? 3 : 2, 6410 a2dp_trx->tx_cnt, 6411 a2dp_trx->ack_cnt, 6412 a2dp_trx->nack_cnt); 6413 } 6414 seq_printf(m, "->w%02d", 6415 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 6416 if (a2dp->exist) { 6417 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 6418 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)", 6419 a2dp_trx->empty_cnt, 6420 a2dp_trx->retry_cnt, 6421 a2dp_trx->tx_rate ? 3 : 2, 6422 a2dp_trx->tx_cnt, 6423 a2dp_trx->ack_cnt, 6424 a2dp_trx->nack_cnt); 6425 } 6426 } 6427 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 6428 seq_puts(m, "\n"); 6429 } 6430 6431 if (a2dp->exist) { 6432 seq_printf(m, "%-15s : a2dp_ept:%d, a2dp_late:%d", 6433 "[a2dp_t_sta]", 6434 le16_to_cpu(pcysta->a2dp_ept.cnt), 6435 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 6436 6437 seq_printf(m, ", avg_t:%d, max_t:%d", 6438 le16_to_cpu(pcysta->a2dp_ept.tavg), 6439 le16_to_cpu(pcysta->a2dp_ept.tmax)); 6440 6441 seq_puts(m, "\n"); 6442 } 6443 } 6444 6445 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m) 6446 { 6447 const struct rtw89_chip_info *chip = rtwdev->chip; 6448 struct rtw89_btc *btc = &rtwdev->btc; 6449 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6450 struct rtw89_btc_rpt_cmn_info *pcinfo; 6451 struct rtw89_btc_fbtc_cynullsta *ns; 6452 struct rtw89_btc_fbtc_cynullsta_v1 *ns_v1; 6453 u8 i = 0; 6454 6455 if (!btc->dm.tdma_now.rxflctrl) 6456 return; 6457 6458 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 6459 if (!pcinfo->valid) 6460 return; 6461 6462 if (chip->chip_id == RTL8852A) { 6463 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 6464 6465 seq_printf(m, " %-15s : ", "[null_sta]"); 6466 6467 for (i = 0; i < 2; i++) { 6468 if (i != 0) 6469 seq_printf(m, ", null-%d", i); 6470 else 6471 seq_printf(m, "null-%d", i); 6472 seq_printf(m, "[ok:%d/", 6473 le32_to_cpu(ns->result[i][1])); 6474 seq_printf(m, "fail:%d/", 6475 le32_to_cpu(ns->result[i][0])); 6476 seq_printf(m, "on_time:%d/", 6477 le32_to_cpu(ns->result[i][2])); 6478 seq_printf(m, "retry:%d/", 6479 le32_to_cpu(ns->result[i][3])); 6480 seq_printf(m, "avg_t:%d.%03d/", 6481 le32_to_cpu(ns->avg_t[i]) / 1000, 6482 le32_to_cpu(ns->avg_t[i]) % 1000); 6483 seq_printf(m, "max_t:%d.%03d]", 6484 le32_to_cpu(ns->max_t[i]) / 1000, 6485 le32_to_cpu(ns->max_t[i]) % 1000); 6486 } 6487 } else { 6488 ns_v1 = &pfwinfo->rpt_fbtc_nullsta.finfo_v1; 6489 6490 seq_printf(m, " %-15s : ", "[null_sta]"); 6491 6492 for (i = 0; i < 2; i++) { 6493 if (i != 0) 6494 seq_printf(m, ", null-%d", i); 6495 else 6496 seq_printf(m, "null-%d", i); 6497 seq_printf(m, "[Tx:%d/", 6498 le32_to_cpu(ns_v1->result[i][4])); 6499 seq_printf(m, "[ok:%d/", 6500 le32_to_cpu(ns_v1->result[i][1])); 6501 seq_printf(m, "fail:%d/", 6502 le32_to_cpu(ns_v1->result[i][0])); 6503 seq_printf(m, "on_time:%d/", 6504 le32_to_cpu(ns_v1->result[i][2])); 6505 seq_printf(m, "retry:%d/", 6506 le32_to_cpu(ns_v1->result[i][3])); 6507 seq_printf(m, "avg_t:%d.%03d/", 6508 le32_to_cpu(ns_v1->avg_t[i]) / 1000, 6509 le32_to_cpu(ns_v1->avg_t[i]) % 1000); 6510 seq_printf(m, "max_t:%d.%03d]", 6511 le32_to_cpu(ns_v1->max_t[i]) / 1000, 6512 le32_to_cpu(ns_v1->max_t[i]) % 1000); 6513 } 6514 } 6515 seq_puts(m, "\n"); 6516 } 6517 6518 static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m) 6519 { 6520 struct rtw89_btc *btc = &rtwdev->btc; 6521 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6522 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6523 struct rtw89_btc_fbtc_steps *pstep = NULL; 6524 u8 type, val, cnt = 0, state = 0; 6525 bool outloop = false; 6526 u16 i, diff_t, n_start = 0, n_stop = 0; 6527 u16 pos_old, pos_new; 6528 6529 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 6530 if (!pcinfo->valid) 6531 return; 6532 6533 pstep = &pfwinfo->rpt_fbtc_step.finfo; 6534 pos_old = le16_to_cpu(pstep->pos_old); 6535 pos_new = le16_to_cpu(pstep->pos_new); 6536 6537 if (pcinfo->req_fver != pstep->fver) 6538 return; 6539 6540 /* store step info by using ring instead of FIFO*/ 6541 do { 6542 switch (state) { 6543 case 0: 6544 n_start = pos_old; 6545 if (pos_new >= pos_old) 6546 n_stop = pos_new; 6547 else 6548 n_stop = btc->ctrl.trace_step - 1; 6549 6550 state = 1; 6551 break; 6552 case 1: 6553 for (i = n_start; i <= n_stop; i++) { 6554 type = pstep->step[i].type; 6555 val = pstep->step[i].val; 6556 diff_t = le16_to_cpu(pstep->step[i].difft); 6557 6558 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 6559 continue; 6560 6561 if (cnt % 10 == 0) 6562 seq_printf(m, " %-15s : ", "[steps]"); 6563 6564 seq_printf(m, "-> %s(%02d)(%02d)", 6565 (type == CXSTEP_SLOT ? "SLT" : 6566 "EVT"), (u32)val, diff_t); 6567 if (cnt % 10 == 9) 6568 seq_puts(m, "\n"); 6569 cnt++; 6570 } 6571 6572 state = 2; 6573 break; 6574 case 2: 6575 if (pos_new < pos_old && n_start != 0) { 6576 n_start = 0; 6577 n_stop = pos_new; 6578 state = 1; 6579 } else { 6580 outloop = true; 6581 } 6582 break; 6583 } 6584 } while (!outloop); 6585 } 6586 6587 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m) 6588 { 6589 const struct rtw89_chip_info *chip = rtwdev->chip; 6590 struct rtw89_btc *btc = &rtwdev->btc; 6591 6592 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 6593 return; 6594 6595 _show_error(rtwdev, m); 6596 _show_fbtc_tdma(rtwdev, m); 6597 _show_fbtc_slots(rtwdev, m); 6598 6599 if (chip->chip_id == RTL8852A) 6600 _show_fbtc_cysta(rtwdev, m); 6601 else 6602 _show_fbtc_cysta_v1(rtwdev, m); 6603 6604 _show_fbtc_nullsta(rtwdev, m); 6605 _show_fbtc_step(rtwdev, m); 6606 } 6607 6608 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 6609 { 6610 const struct rtw89_chip_info *chip = rtwdev->chip; 6611 struct rtw89_mac_ax_gnt *gnt; 6612 u32 val, status; 6613 6614 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B) { 6615 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 6616 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 6617 6618 gnt = &gnt_cfg->band[0]; 6619 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 6620 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 6621 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 6622 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 6623 6624 gnt = &gnt_cfg->band[1]; 6625 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 6626 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 6627 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 6628 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 6629 } else if (chip->chip_id == RTL8852C) { 6630 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 6631 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 6632 6633 gnt = &gnt_cfg->band[0]; 6634 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 6635 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 6636 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 6637 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 6638 6639 gnt = &gnt_cfg->band[1]; 6640 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 6641 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 6642 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 6643 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 6644 } else { 6645 return; 6646 } 6647 } 6648 6649 static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m) 6650 { 6651 const struct rtw89_chip_info *chip = rtwdev->chip; 6652 struct rtw89_btc *btc = &rtwdev->btc; 6653 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6654 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6655 struct rtw89_btc_fbtc_mreg_val *pmreg = NULL; 6656 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 6657 struct rtw89_btc_cx *cx = &btc->cx; 6658 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6659 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6660 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 6661 struct rtw89_mac_ax_gnt gnt; 6662 u8 i = 0, type = 0, cnt = 0; 6663 u32 val, offset; 6664 6665 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 6666 return; 6667 6668 seq_puts(m, "========== [HW Status] ==========\n"); 6669 6670 seq_printf(m, 6671 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 6672 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 6673 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 6674 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 6675 6676 /* To avoid I/O if WL LPS or power-off */ 6677 if (!wl->status.map.lps && !wl->status.map.rf_off) { 6678 if (chip->chip_id == RTL8852A) 6679 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 6680 else if (chip->chip_id == RTL8852C) 6681 btc->dm.pta_owner = 0; 6682 6683 _get_gnt(rtwdev, &gnt_cfg); 6684 gnt = gnt_cfg.band[0]; 6685 seq_printf(m, 6686 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 6687 "[gnt_status]", 6688 chip->chip_id == RTL8852C ? "HW" : 6689 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 6690 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 6691 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 6692 6693 gnt = gnt_cfg.band[1]; 6694 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 6695 gnt.gnt_wl_sw_en ? "SW" : "HW", 6696 gnt.gnt_wl, 6697 gnt.gnt_bt_sw_en ? "SW" : "HW", 6698 gnt.gnt_bt); 6699 } 6700 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 6701 if (!pcinfo->valid) { 6702 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6703 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 6704 __func__); 6705 return; 6706 } 6707 6708 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo; 6709 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6710 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 6711 __func__, pmreg->reg_num); 6712 6713 for (i = 0; i < pmreg->reg_num; i++) { 6714 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 6715 offset = le32_to_cpu(chip->mon_reg[i].offset); 6716 val = le32_to_cpu(pmreg->mreg_val[i]); 6717 6718 if (cnt % 6 == 0) 6719 seq_printf(m, " %-15s : %d_0x%04x=0x%08x", 6720 "[reg]", (u32)type, offset, val); 6721 else 6722 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type, 6723 offset, val); 6724 if (cnt % 6 == 5) 6725 seq_puts(m, "\n"); 6726 cnt++; 6727 } 6728 6729 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 6730 if (!pcinfo->valid) { 6731 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6732 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 6733 __func__); 6734 return; 6735 } 6736 6737 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 6738 if (!gdbg->en_map) 6739 return; 6740 6741 seq_printf(m, " %-15s : enable_map:0x%08x", 6742 "[gpio_dbg]", gdbg->en_map); 6743 6744 for (i = 0; i < BTC_DBG_MAX1; i++) { 6745 if (!(gdbg->en_map & BIT(i))) 6746 continue; 6747 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]); 6748 } 6749 seq_puts(m, "\n"); 6750 } 6751 6752 static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m) 6753 { 6754 struct rtw89_btc *btc = &rtwdev->btc; 6755 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6756 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6757 struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL; 6758 struct rtw89_btc_cx *cx = &btc->cx; 6759 struct rtw89_btc_dm *dm = &btc->dm; 6760 struct rtw89_btc_wl_info *wl = &cx->wl; 6761 struct rtw89_btc_bt_info *bt = &cx->bt; 6762 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 6763 u8 i; 6764 6765 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 6766 return; 6767 6768 seq_puts(m, "========== [Statistics] ==========\n"); 6769 6770 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 6771 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 6772 prptctrl = &pfwinfo->rpt_ctrl.finfo; 6773 6774 seq_printf(m, 6775 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 6776 "[summary]", pfwinfo->cnt_h2c, 6777 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 6778 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 6779 6780 seq_printf(m, 6781 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 6782 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt, 6783 prptctrl->rpt_enable, dm->error.val); 6784 6785 if (dm->error.map.wl_fw_hang) 6786 seq_puts(m, " (WL FW Hang!!)"); 6787 seq_puts(m, "\n"); 6788 seq_printf(m, 6789 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 6790 "[mailbox]", prptctrl->mb_send_ok_cnt, 6791 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt); 6792 6793 seq_printf(m, 6794 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 6795 prptctrl->mb_a2dp_empty_cnt, 6796 prptctrl->mb_a2dp_flct_cnt, 6797 prptctrl->mb_a2dp_full_cnt); 6798 6799 seq_printf(m, 6800 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 6801 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 6802 cx->cnt_wl[BTC_WCNT_RFK_GO], 6803 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 6804 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 6805 6806 seq_printf(m, 6807 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 6808 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 6809 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 6810 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 6811 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 6812 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 6813 6814 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 6815 bt->rfk_info.map.timeout = 1; 6816 else 6817 bt->rfk_info.map.timeout = 0; 6818 6819 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 6820 } else { 6821 seq_printf(m, 6822 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 6823 "[summary]", pfwinfo->cnt_h2c, 6824 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 6825 pfwinfo->event[BTF_EVNT_RPT], 6826 btc->fwinfo.rpt_en_map); 6827 seq_puts(m, " (WL FW report invalid!!)\n"); 6828 } 6829 6830 for (i = 0; i < BTC_NCNT_NUM; i++) 6831 cnt_sum += dm->cnt_notify[i]; 6832 6833 seq_printf(m, 6834 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 6835 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 6836 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 6837 6838 seq_printf(m, 6839 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 6840 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 6841 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 6842 cnt[BTC_NCNT_WL_STA]); 6843 6844 seq_printf(m, 6845 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 6846 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 6847 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 6848 cnt[BTC_NCNT_SPECIAL_PACKET]); 6849 6850 seq_printf(m, 6851 "timer=%d, control=%d, customerize=%d\n", 6852 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 6853 cnt[BTC_NCNT_CUSTOMERIZE]); 6854 } 6855 6856 static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m) 6857 { 6858 struct rtw89_btc *btc = &rtwdev->btc; 6859 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6860 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl; 6861 struct rtw89_btc_rpt_cmn_info *pcinfo; 6862 struct rtw89_btc_cx *cx = &btc->cx; 6863 struct rtw89_btc_dm *dm = &btc->dm; 6864 struct rtw89_btc_wl_info *wl = &cx->wl; 6865 struct rtw89_btc_bt_info *bt = &cx->bt; 6866 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 6867 u8 i; 6868 6869 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 6870 return; 6871 6872 seq_puts(m, "========== [Statistics] ==========\n"); 6873 6874 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 6875 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 6876 prptctrl = &pfwinfo->rpt_ctrl.finfo_v1; 6877 6878 seq_printf(m, 6879 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 6880 "[summary]", pfwinfo->cnt_h2c, 6881 pfwinfo->cnt_h2c_fail, 6882 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 6883 pfwinfo->cnt_c2h, 6884 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 6885 6886 seq_printf(m, 6887 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 6888 pfwinfo->event[BTF_EVNT_RPT], 6889 le32_to_cpu(prptctrl->rpt_info.cnt), 6890 le32_to_cpu(prptctrl->rpt_info.en), 6891 dm->error.val); 6892 6893 if (dm->error.map.wl_fw_hang) 6894 seq_puts(m, " (WL FW Hang!!)"); 6895 seq_puts(m, "\n"); 6896 seq_printf(m, 6897 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 6898 "[mailbox]", 6899 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 6900 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 6901 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 6902 6903 seq_printf(m, 6904 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 6905 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 6906 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 6907 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 6908 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 6909 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 6910 6911 seq_printf(m, 6912 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 6913 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 6914 cx->cnt_wl[BTC_WCNT_RFK_GO], 6915 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 6916 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 6917 6918 seq_printf(m, 6919 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 6920 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 6921 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 6922 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 6923 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 6924 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 6925 6926 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 6927 bt->rfk_info.map.timeout = 1; 6928 else 6929 bt->rfk_info.map.timeout = 0; 6930 6931 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 6932 } else { 6933 seq_printf(m, 6934 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 6935 "[summary]", pfwinfo->cnt_h2c, 6936 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 6937 pfwinfo->event[BTF_EVNT_RPT], 6938 btc->fwinfo.rpt_en_map); 6939 seq_puts(m, " (WL FW report invalid!!)\n"); 6940 } 6941 6942 for (i = 0; i < BTC_NCNT_NUM; i++) 6943 cnt_sum += dm->cnt_notify[i]; 6944 6945 seq_printf(m, 6946 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 6947 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 6948 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 6949 6950 seq_printf(m, 6951 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 6952 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 6953 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 6954 cnt[BTC_NCNT_WL_STA]); 6955 6956 seq_printf(m, 6957 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 6958 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 6959 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 6960 cnt[BTC_NCNT_SPECIAL_PACKET]); 6961 6962 seq_printf(m, 6963 "timer=%d, control=%d, customerize=%d\n", 6964 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 6965 cnt[BTC_NCNT_CUSTOMERIZE]); 6966 } 6967 6968 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6969 { 6970 const struct rtw89_chip_info *chip = rtwdev->chip; 6971 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal; 6972 struct rtw89_btc *btc = &rtwdev->btc; 6973 struct rtw89_btc_cx *cx = &btc->cx; 6974 struct rtw89_btc_bt_info *bt = &cx->bt; 6975 6976 seq_puts(m, "=========================================\n"); 6977 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n", 6978 fw_suit->major_ver, fw_suit->minor_ver, 6979 fw_suit->sub_ver, fw_suit->sub_idex); 6980 seq_printf(m, "manual %d\n", btc->ctrl.manual); 6981 6982 seq_puts(m, "=========================================\n"); 6983 6984 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)", 6985 "[bt_info]", 6986 bt->raw_info[2], bt->raw_info[3], 6987 bt->raw_info[4], bt->raw_info[5], 6988 bt->raw_info[6], bt->raw_info[7], 6989 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 6990 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 6991 cx->cnt_bt[BTC_BCNT_INFOSAME]); 6992 6993 seq_puts(m, "\n=========================================\n"); 6994 6995 _show_cx_info(rtwdev, m); 6996 _show_wl_info(rtwdev, m); 6997 _show_bt_info(rtwdev, m); 6998 _show_dm_info(rtwdev, m); 6999 _show_fw_dm_msg(rtwdev, m); 7000 _show_mreg(rtwdev, m); 7001 if (chip->chip_id == RTL8852A) 7002 _show_summary(rtwdev, m); 7003 else 7004 _show_summary_v1(rtwdev, m); 7005 } 7006