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