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 #if defined(__linux__) 4096 "[BTC], cnt_connect = %d, link_mode = %d\n", 4097 cnt_connect, wl_rinfo->link_mode); 4098 #elif defined(__FreeBSD__) 4099 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4100 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4101 #endif 4102 4103 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4104 } 4105 4106 static void _update_wl_info_v1(struct rtw89_dev *rtwdev) 4107 { 4108 struct rtw89_btc *btc = &rtwdev->btc; 4109 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4110 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 4111 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 4112 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4113 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 4114 u8 cnt_2g = 0, cnt_5g = 0, phy; 4115 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 4116 bool b2g = false, b5g = false, client_joined = false; 4117 u8 i; 4118 4119 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 4120 4121 for (i = 0; i < RTW89_PORT_NUM; i++) { 4122 if (!wl_linfo[i].active) 4123 continue; 4124 4125 cnt_active++; 4126 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role; 4127 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid; 4128 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy; 4129 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band; 4130 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 4131 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0; 4132 4133 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 4134 4135 phy = wl_linfo[i].phy; 4136 4137 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) { 4138 wl_dinfo->role[phy] = wl_linfo[i].role; 4139 wl_dinfo->op_band[phy] = wl_linfo[i].band; 4140 _update_dbcc_band(rtwdev, phy); 4141 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4142 } 4143 4144 if (wl_linfo[i].connected == MLME_NO_LINK) { 4145 continue; 4146 } else if (wl_linfo[i].connected == MLME_LINKING) { 4147 cnt_connecting++; 4148 } else { 4149 cnt_connect++; 4150 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 4151 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 4152 wl_linfo[i].client_cnt > 1) 4153 client_joined = true; 4154 } 4155 4156 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 4157 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch; 4158 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw; 4159 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1; 4160 4161 /* only care 2 roles + BT coex */ 4162 if (wl_linfo[i].band != RTW89_BAND_2G) { 4163 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 4164 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 4165 cnt_5g++; 4166 b5g = true; 4167 } else { 4168 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 4169 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 4170 cnt_2g++; 4171 b2g = true; 4172 } 4173 } 4174 4175 wl_rinfo->connect_cnt = cnt_connect; 4176 4177 /* Be careful to change the following sequence!! */ 4178 if (cnt_connect == 0) { 4179 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4180 wl_rinfo->role_map.role.none = 1; 4181 } else if (!b2g && b5g) { 4182 wl_rinfo->link_mode = BTC_WLINK_5G; 4183 } else if (wl_rinfo->role_map.role.nan) { 4184 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 4185 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 4186 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4187 } else if (b2g && b5g && cnt_connect == 2) { 4188 if (rtwdev->dbcc_en) { 4189 switch (wl_dinfo->role[RTW89_PHY_0]) { 4190 case RTW89_WIFI_ROLE_STATION: 4191 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4192 break; 4193 case RTW89_WIFI_ROLE_P2P_GO: 4194 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4195 break; 4196 case RTW89_WIFI_ROLE_P2P_CLIENT: 4197 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4198 break; 4199 case RTW89_WIFI_ROLE_AP: 4200 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4201 break; 4202 default: 4203 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4204 break; 4205 } 4206 } else { 4207 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 4208 } 4209 } else if (!b5g && cnt_connect == 2) { 4210 if (wl_rinfo->role_map.role.station && 4211 (wl_rinfo->role_map.role.p2p_go || 4212 wl_rinfo->role_map.role.p2p_gc || 4213 wl_rinfo->role_map.role.ap)) { 4214 if (wl_2g_ch[0] == wl_2g_ch[1]) 4215 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 4216 else 4217 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4218 } else { 4219 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 4220 } 4221 } else if (!b5g && cnt_connect == 1) { 4222 if (wl_rinfo->role_map.role.station) 4223 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4224 else if (wl_rinfo->role_map.role.ap) 4225 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 4226 else if (wl_rinfo->role_map.role.p2p_go) 4227 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 4228 else if (wl_rinfo->role_map.role.p2p_gc) 4229 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 4230 else 4231 wl_rinfo->link_mode = BTC_WLINK_OTHER; 4232 } 4233 4234 /* if no client_joined, don't care P2P-GO/AP role */ 4235 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 4236 if (!client_joined) { 4237 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 4238 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 4239 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 4240 wl_rinfo->connect_cnt = 1; 4241 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 4242 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 4243 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 4244 wl_rinfo->connect_cnt = 0; 4245 } 4246 } 4247 } 4248 4249 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4250 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 4251 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 4252 4253 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 4254 } 4255 4256 #define BTC_CHK_HANG_MAX 3 4257 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 4258 4259 void rtw89_coex_act1_work(struct work_struct *work) 4260 { 4261 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4262 coex_act1_work.work); 4263 struct rtw89_btc *btc = &rtwdev->btc; 4264 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4265 struct rtw89_btc_cx *cx = &btc->cx; 4266 struct rtw89_btc_wl_info *wl = &cx->wl; 4267 4268 mutex_lock(&rtwdev->mutex); 4269 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4270 dm->cnt_notify[BTC_NCNT_TIMER]++; 4271 if (wl->status.map._4way) 4272 wl->status.map._4way = false; 4273 if (wl->status.map.connecting) 4274 wl->status.map.connecting = false; 4275 4276 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 4277 mutex_unlock(&rtwdev->mutex); 4278 } 4279 4280 void rtw89_coex_bt_devinfo_work(struct work_struct *work) 4281 { 4282 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4283 coex_bt_devinfo_work.work); 4284 struct rtw89_btc *btc = &rtwdev->btc; 4285 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4286 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 4287 4288 mutex_lock(&rtwdev->mutex); 4289 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4290 dm->cnt_notify[BTC_NCNT_TIMER]++; 4291 a2dp->play_latency = 0; 4292 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 4293 mutex_unlock(&rtwdev->mutex); 4294 } 4295 4296 void rtw89_coex_rfk_chk_work(struct work_struct *work) 4297 { 4298 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4299 coex_rfk_chk_work.work); 4300 struct rtw89_btc *btc = &rtwdev->btc; 4301 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4302 struct rtw89_btc_cx *cx = &btc->cx; 4303 struct rtw89_btc_wl_info *wl = &cx->wl; 4304 4305 mutex_lock(&rtwdev->mutex); 4306 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 4307 dm->cnt_notify[BTC_NCNT_TIMER]++; 4308 if (wl->rfk_info.state != BTC_WRFK_STOP) { 4309 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4310 "[BTC], %s(): RFK timeout\n", __func__); 4311 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++; 4312 dm->error.map.wl_rfk_timeout = true; 4313 wl->rfk_info.state = BTC_WRFK_STOP; 4314 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 4315 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 4316 } 4317 mutex_unlock(&rtwdev->mutex); 4318 } 4319 4320 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) 4321 { 4322 const struct rtw89_chip_info *chip = rtwdev->chip; 4323 struct rtw89_btc *btc = &rtwdev->btc; 4324 struct rtw89_btc_cx *cx = &btc->cx; 4325 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4326 u32 val; 4327 bool status_change = false; 4328 4329 if (!chip->scbd) 4330 return; 4331 4332 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 4333 4334 val = _read_scbd(rtwdev); 4335 if (val == BTC_SCB_INV_VALUE) { 4336 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4337 "[BTC], %s(): return by invalid scbd value\n", 4338 __func__); 4339 return; 4340 } 4341 4342 if (!(val & BTC_BSCB_ON) || 4343 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX) 4344 bt->enable.now = 0; 4345 else 4346 bt->enable.now = 1; 4347 4348 if (bt->enable.now != bt->enable.last) 4349 status_change = true; 4350 4351 /* reset bt info if bt re-enable */ 4352 if (bt->enable.now && !bt->enable.last) { 4353 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 4354 cx->cnt_bt[BTC_BCNT_REENABLE]++; 4355 bt->enable.now = 1; 4356 } 4357 4358 bt->enable.last = bt->enable.now; 4359 bt->scbd = val; 4360 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 4361 4362 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 4363 status_change = true; 4364 4365 bt->whql_test = !!(val & BTC_BSCB_WHQL); 4366 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE; 4367 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT); 4368 4369 /* if rfk run 1->0 */ 4370 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN)) 4371 status_change = true; 4372 4373 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN); 4374 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); 4375 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 4376 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); 4377 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 4378 4379 if (!only_update && status_change) 4380 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 4381 } 4382 4383 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) 4384 { 4385 struct rtw89_btc *btc = &rtwdev->btc; 4386 struct rtw89_btc_cx *cx = &btc->cx; 4387 struct rtw89_btc_bt_info *bt = &cx->bt; 4388 4389 _update_bt_scbd(rtwdev, true); 4390 4391 cx->cnt_wl[BTC_WCNT_RFK_REQ]++; 4392 4393 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) && 4394 !bt->rfk_info.map.timeout) { 4395 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++; 4396 } else { 4397 cx->cnt_wl[BTC_WCNT_RFK_GO]++; 4398 return true; 4399 } 4400 return false; 4401 } 4402 4403 static 4404 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 4405 { 4406 const struct rtw89_chip_info *chip = rtwdev->chip; 4407 struct rtw89_btc *btc = &rtwdev->btc; 4408 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4409 struct rtw89_btc_cx *cx = &btc->cx; 4410 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4411 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 4412 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 4413 u8 mode; 4414 4415 lockdep_assert_held(&rtwdev->mutex); 4416 4417 dm->run_reason = reason; 4418 _update_dm_step(rtwdev, reason); 4419 _update_btc_state_map(rtwdev); 4420 4421 if (chip->chip_id == RTL8852A) 4422 mode = wl_rinfo->link_mode; 4423 else 4424 mode = wl_rinfo_v1->link_mode; 4425 4426 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 4427 __func__, reason, mode); 4428 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 4429 __func__, dm->wl_only, dm->bt_only); 4430 4431 /* Be careful to change the following function sequence!! */ 4432 if (btc->ctrl.manual) { 4433 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4434 "[BTC], %s(): return for Manual CTRL!!\n", 4435 __func__); 4436 return; 4437 } 4438 4439 if (btc->ctrl.igno_bt && 4440 (reason == BTC_RSN_UPDATE_BT_INFO || 4441 reason == BTC_RSN_UPDATE_BT_SCBD)) { 4442 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4443 "[BTC], %s(): return for Stop Coex DM!!\n", 4444 __func__); 4445 return; 4446 } 4447 4448 if (!wl->status.map.init_ok) { 4449 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4450 "[BTC], %s(): return for WL init fail!!\n", 4451 __func__); 4452 return; 4453 } 4454 4455 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 4456 wl->status.map.lps_pre == wl->status.map.lps && 4457 (reason == BTC_RSN_NTFY_POWEROFF || 4458 reason == BTC_RSN_NTFY_RADIO_STATE)) { 4459 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4460 "[BTC], %s(): return for WL rf off state no change!!\n", 4461 __func__); 4462 return; 4463 } 4464 4465 dm->cnt_dm[BTC_DCNT_RUN]++; 4466 4467 if (btc->ctrl.always_freerun) { 4468 _action_freerun(rtwdev); 4469 btc->ctrl.igno_bt = true; 4470 goto exit; 4471 } 4472 4473 if (dm->wl_only) { 4474 _action_wl_only(rtwdev); 4475 btc->ctrl.igno_bt = true; 4476 goto exit; 4477 } 4478 4479 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) { 4480 _action_wl_off(rtwdev); 4481 btc->ctrl.igno_bt = true; 4482 goto exit; 4483 } 4484 4485 btc->ctrl.igno_bt = false; 4486 dm->freerun = false; 4487 4488 if (reason == BTC_RSN_NTFY_INIT) { 4489 _action_wl_init(rtwdev); 4490 goto exit; 4491 } 4492 4493 if (!cx->bt.enable.now && !cx->other.type) { 4494 _action_bt_off(rtwdev); 4495 goto exit; 4496 } 4497 4498 if (cx->bt.whql_test) { 4499 _action_bt_whql(rtwdev); 4500 goto exit; 4501 } 4502 4503 if (wl->rfk_info.state != BTC_WRFK_STOP) { 4504 _action_wl_rfk(rtwdev); 4505 goto exit; 4506 } 4507 4508 if (cx->state_map == BTC_WLINKING) { 4509 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || 4510 mode == BTC_WLINK_5G) { 4511 _action_wl_scan(rtwdev); 4512 goto exit; 4513 } 4514 } 4515 4516 if (wl->status.map.scan) { 4517 _action_wl_scan(rtwdev); 4518 goto exit; 4519 } 4520 4521 switch (mode) { 4522 case BTC_WLINK_NOLINK: 4523 _action_wl_nc(rtwdev); 4524 break; 4525 case BTC_WLINK_2G_STA: 4526 _action_wl_2g_sta(rtwdev); 4527 break; 4528 case BTC_WLINK_2G_AP: 4529 _action_wl_2g_ap(rtwdev); 4530 break; 4531 case BTC_WLINK_2G_GO: 4532 _action_wl_2g_go(rtwdev); 4533 break; 4534 case BTC_WLINK_2G_GC: 4535 _action_wl_2g_gc(rtwdev); 4536 break; 4537 case BTC_WLINK_2G_SCC: 4538 if (chip->chip_id == RTL8852A) 4539 _action_wl_2g_scc(rtwdev); 4540 else if (chip->chip_id == RTL8852C) 4541 _action_wl_2g_scc_v1(rtwdev); 4542 break; 4543 case BTC_WLINK_2G_MCC: 4544 _action_wl_2g_mcc(rtwdev); 4545 break; 4546 case BTC_WLINK_25G_MCC: 4547 _action_wl_25g_mcc(rtwdev); 4548 break; 4549 case BTC_WLINK_5G: 4550 _action_wl_5g(rtwdev); 4551 break; 4552 case BTC_WLINK_2G_NAN: 4553 _action_wl_2g_nan(rtwdev); 4554 break; 4555 default: 4556 _action_wl_other(rtwdev); 4557 break; 4558 } 4559 4560 exit: 4561 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 4562 _action_common(rtwdev); 4563 } 4564 4565 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 4566 { 4567 struct rtw89_btc *btc = &rtwdev->btc; 4568 4569 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4570 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 4571 } 4572 4573 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 4574 { 4575 struct rtw89_btc *btc = &rtwdev->btc; 4576 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4577 4578 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4579 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 4580 4581 btc->cx.wl.status.map.rf_off = 1; 4582 btc->cx.wl.status.map.busy = 0; 4583 wl->status.map.lps = BTC_LPS_OFF; 4584 4585 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 4586 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 4587 4588 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 4589 4590 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 4591 } 4592 4593 static void _set_init_info(struct rtw89_dev *rtwdev) 4594 { 4595 const struct rtw89_chip_info *chip = rtwdev->chip; 4596 struct rtw89_btc *btc = &rtwdev->btc; 4597 struct rtw89_btc_dm *dm = &btc->dm; 4598 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4599 4600 dm->init_info.wl_only = (u8)dm->wl_only; 4601 dm->init_info.bt_only = (u8)dm->bt_only; 4602 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok; 4603 dm->init_info.dbcc_en = rtwdev->dbcc_en; 4604 dm->init_info.cx_other = btc->cx.other.type; 4605 dm->init_info.wl_guard_ch = chip->afh_guard_ch; 4606 dm->init_info.module = btc->mdinfo; 4607 } 4608 4609 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 4610 { 4611 struct rtw89_btc *btc = &rtwdev->btc; 4612 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 4613 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4614 const struct rtw89_chip_info *chip = rtwdev->chip; 4615 4616 _reset_btc_var(rtwdev, BTC_RESET_ALL); 4617 btc->dm.run_reason = BTC_RSN_NONE; 4618 btc->dm.run_action = BTC_ACT_NONE; 4619 btc->ctrl.igno_bt = true; 4620 4621 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4622 "[BTC], %s(): mode=%d\n", __func__, mode); 4623 4624 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 4625 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 4626 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 4627 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 4628 4629 chip->ops->btc_set_rfe(rtwdev); 4630 chip->ops->btc_init_cfg(rtwdev); 4631 4632 if (!wl->status.map.init_ok) { 4633 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4634 "[BTC], %s(): return for WL init fail!!\n", 4635 __func__); 4636 dm->error.map.init = true; 4637 return; 4638 } 4639 4640 _write_scbd(rtwdev, 4641 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 4642 _update_bt_scbd(rtwdev, true); 4643 if (rtw89_mac_get_ctrl_path(rtwdev)) { 4644 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4645 "[BTC], %s(): PTA owner warning!!\n", 4646 __func__); 4647 dm->error.map.pta_owner = true; 4648 } 4649 4650 _set_init_info(rtwdev); 4651 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR); 4652 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot); 4653 btc_fw_set_monreg(rtwdev); 4654 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 4655 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 4656 4657 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 4658 } 4659 4660 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 4661 { 4662 struct rtw89_btc *btc = &rtwdev->btc; 4663 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4664 4665 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4666 "[BTC], %s(): phy_idx=%d, band=%d\n", 4667 __func__, phy_idx, band); 4668 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 4669 wl->status.map.scan = true; 4670 wl->scan_info.band[phy_idx] = band; 4671 wl->scan_info.phy_map |= BIT(phy_idx); 4672 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 4673 4674 if (rtwdev->dbcc_en) { 4675 wl->dbcc_info.scan_band[phy_idx] = band; 4676 _update_dbcc_band(rtwdev, phy_idx); 4677 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4678 } 4679 4680 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 4681 } 4682 4683 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 4684 { 4685 struct rtw89_btc *btc = &rtwdev->btc; 4686 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4687 4688 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4689 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 4690 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 4691 4692 wl->status.map.scan = false; 4693 wl->scan_info.phy_map &= ~BIT(phy_idx); 4694 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 4695 4696 if (rtwdev->dbcc_en) { 4697 _update_dbcc_band(rtwdev, phy_idx); 4698 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4699 } 4700 4701 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 4702 } 4703 4704 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 4705 { 4706 struct rtw89_btc *btc = &rtwdev->btc; 4707 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4708 4709 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4710 "[BTC], %s(): phy_idx=%d, band=%d\n", 4711 __func__, phy_idx, band); 4712 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 4713 4714 wl->scan_info.band[phy_idx] = band; 4715 wl->scan_info.phy_map |= BIT(phy_idx); 4716 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 4717 4718 if (rtwdev->dbcc_en) { 4719 wl->dbcc_info.scan_band[phy_idx] = band; 4720 _update_dbcc_band(rtwdev, phy_idx); 4721 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 4722 } 4723 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 4724 } 4725 4726 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 4727 enum btc_pkt_type pkt_type) 4728 { 4729 struct rtw89_btc *btc = &rtwdev->btc; 4730 struct rtw89_btc_cx *cx = &btc->cx; 4731 struct rtw89_btc_wl_info *wl = &cx->wl; 4732 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info; 4733 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 4734 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 4735 u32 cnt; 4736 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 4737 bool delay_work = false; 4738 4739 switch (pkt_type) { 4740 case PACKET_DHCP: 4741 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP]; 4742 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4743 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 4744 wl->status.map.connecting = true; 4745 delay_work = true; 4746 break; 4747 case PACKET_EAPOL: 4748 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 4749 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4750 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 4751 wl->status.map._4way = true; 4752 delay_work = true; 4753 if (hfp->exist || hid->exist) 4754 delay /= 2; 4755 break; 4756 case PACKET_EAPOL_END: 4757 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 4758 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4759 "[BTC], %s(): EAPOL_End cnt=%d\n", 4760 __func__, cnt); 4761 wl->status.map._4way = false; 4762 cancel_delayed_work(&rtwdev->coex_act1_work); 4763 break; 4764 case PACKET_ARP: 4765 cnt = ++cx->cnt_wl[BTC_WCNT_ARP]; 4766 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4767 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 4768 return; 4769 case PACKET_ICMP: 4770 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4771 "[BTC], %s(): ICMP pkt\n", __func__); 4772 return; 4773 default: 4774 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4775 "[BTC], %s(): unknown packet type %d\n", 4776 __func__, pkt_type); 4777 return; 4778 } 4779 4780 if (delay_work) { 4781 cancel_delayed_work(&rtwdev->coex_act1_work); 4782 ieee80211_queue_delayed_work(rtwdev->hw, 4783 &rtwdev->coex_act1_work, delay); 4784 } 4785 4786 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 4787 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 4788 } 4789 4790 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work) 4791 { 4792 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4793 btc.eapol_notify_work); 4794 4795 mutex_lock(&rtwdev->mutex); 4796 rtw89_leave_ps_mode(rtwdev); 4797 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 4798 mutex_unlock(&rtwdev->mutex); 4799 } 4800 4801 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work) 4802 { 4803 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4804 btc.arp_notify_work); 4805 4806 mutex_lock(&rtwdev->mutex); 4807 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 4808 mutex_unlock(&rtwdev->mutex); 4809 } 4810 4811 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work) 4812 { 4813 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4814 btc.dhcp_notify_work); 4815 4816 mutex_lock(&rtwdev->mutex); 4817 rtw89_leave_ps_mode(rtwdev); 4818 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 4819 mutex_unlock(&rtwdev->mutex); 4820 } 4821 4822 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work) 4823 { 4824 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 4825 btc.icmp_notify_work); 4826 4827 mutex_lock(&rtwdev->mutex); 4828 rtw89_leave_ps_mode(rtwdev); 4829 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 4830 mutex_unlock(&rtwdev->mutex); 4831 } 4832 4833 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 4834 { 4835 const struct rtw89_chip_info *chip = rtwdev->chip; 4836 struct rtw89_btc *btc = &rtwdev->btc; 4837 struct rtw89_btc_cx *cx = &btc->cx; 4838 struct rtw89_btc_bt_info *bt = &cx->bt; 4839 struct rtw89_btc_bt_link_info *b = &bt->link_info; 4840 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 4841 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 4842 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 4843 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 4844 union btc_btinfo btinfo; 4845 4846 if (buf[BTC_BTINFO_L1] != 6) 4847 return; 4848 4849 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) { 4850 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4851 "[BTC], %s(): return by bt-info duplicate!!\n", 4852 __func__); 4853 cx->cnt_bt[BTC_BCNT_INFOSAME]++; 4854 return; 4855 } 4856 4857 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX); 4858 4859 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4860 "[BTC], %s(): bt_info[2]=0x%02x\n", 4861 __func__, bt->raw_info[2]); 4862 4863 /* reset to mo-connect before update */ 4864 b->status.val = BTC_BLINK_NOCONNECT; 4865 b->profile_cnt.last = b->profile_cnt.now; 4866 b->relink.last = b->relink.now; 4867 a2dp->exist_last = a2dp->exist; 4868 b->multi_link.last = b->multi_link.now; 4869 bt->inq_pag.last = bt->inq_pag.now; 4870 b->profile_cnt.now = 0; 4871 hid->type = 0; 4872 4873 /* parse raw info low-Byte2 */ 4874 btinfo.val = bt->raw_info[BTC_BTINFO_L2]; 4875 b->status.map.connect = btinfo.lb2.connect; 4876 b->status.map.sco_busy = btinfo.lb2.sco_busy; 4877 b->status.map.acl_busy = btinfo.lb2.acl_busy; 4878 b->status.map.inq_pag = btinfo.lb2.inq_pag; 4879 bt->inq_pag.now = btinfo.lb2.inq_pag; 4880 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 4881 4882 hfp->exist = btinfo.lb2.hfp; 4883 b->profile_cnt.now += (u8)hfp->exist; 4884 hid->exist = btinfo.lb2.hid; 4885 b->profile_cnt.now += (u8)hid->exist; 4886 a2dp->exist = btinfo.lb2.a2dp; 4887 b->profile_cnt.now += (u8)a2dp->exist; 4888 pan->active = btinfo.lb2.pan; 4889 4890 /* parse raw info low-Byte3 */ 4891 btinfo.val = bt->raw_info[BTC_BTINFO_L3]; 4892 if (btinfo.lb3.retry != 0) 4893 cx->cnt_bt[BTC_BCNT_RETRY]++; 4894 b->cqddr = btinfo.lb3.cqddr; 4895 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 4896 bt->inq = btinfo.lb3.inq; 4897 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 4898 bt->pag = btinfo.lb3.pag; 4899 4900 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 4901 /* parse raw info high-Byte0 */ 4902 btinfo.val = bt->raw_info[BTC_BTINFO_H0]; 4903 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 4904 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 4905 4906 /* parse raw info high-Byte1 */ 4907 btinfo.val = bt->raw_info[BTC_BTINFO_H1]; 4908 b->status.map.ble_connect = btinfo.hb1.ble_connect; 4909 if (btinfo.hb1.ble_connect) 4910 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); 4911 4912 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 4913 bt->reinit = btinfo.hb1.reinit; 4914 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 4915 b->relink.now = btinfo.hb1.relink; 4916 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 4917 bt->igno_wl = btinfo.hb1.igno_wl; 4918 4919 if (bt->igno_wl && !cx->wl.status.map.rf_off) 4920 _set_bt_ignore_wlan_act(rtwdev, false); 4921 4922 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); 4923 bt->ble_scan_en = btinfo.hb1.ble_scan; 4924 4925 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 4926 b->role_sw = btinfo.hb1.role_sw; 4927 4928 b->multi_link.now = btinfo.hb1.multi_link; 4929 4930 /* parse raw info high-Byte2 */ 4931 btinfo.val = bt->raw_info[BTC_BTINFO_H2]; 4932 pan->exist = btinfo.hb2.pan_active; 4933 b->profile_cnt.now += (u8)pan->exist; 4934 4935 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 4936 b->afh_update = btinfo.hb2.afh_update; 4937 a2dp->active = btinfo.hb2.a2dp_active; 4938 b->slave_role = btinfo.hb2.slave; 4939 hid->slot_info = btinfo.hb2.hid_slot; 4940 hid->pair_cnt = btinfo.hb2.hid_cnt; 4941 hid->type |= (hid->slot_info == BTC_HID_218 ? 4942 BTC_HID_218 : BTC_HID_418); 4943 /* parse raw info high-Byte3 */ 4944 btinfo.val = bt->raw_info[BTC_BTINFO_H3]; 4945 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 4946 4947 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 4948 cx->cnt_bt[BTC_BCNT_RATECHG]++; 4949 b->tx_3m = (u32)btinfo.hb3.tx_3m; 4950 4951 a2dp->sink = btinfo.hb3.a2dp_sink; 4952 4953 if (b->profile_cnt.now || b->status.map.ble_connect) 4954 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1); 4955 else 4956 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0); 4957 4958 if (!a2dp->exist_last && a2dp->exist) { 4959 a2dp->vendor_id = 0; 4960 a2dp->flush_time = 0; 4961 a2dp->play_latency = 1; 4962 ieee80211_queue_delayed_work(rtwdev->hw, 4963 &rtwdev->coex_bt_devinfo_work, 4964 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 4965 } 4966 4967 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 || 4968 a2dp->play_latency == 1)) 4969 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1); 4970 else 4971 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0); 4972 4973 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 4974 } 4975 4976 enum btc_wl_mode { 4977 BTC_WL_MODE_HT = 0, 4978 BTC_WL_MODE_VHT = 1, 4979 BTC_WL_MODE_HE = 2, 4980 BTC_WL_MODE_NUM, 4981 }; 4982 4983 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, 4984 struct rtw89_sta *rtwsta, enum btc_role_state state) 4985 { 4986 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); 4987 const struct rtw89_chip_info *chip = rtwdev->chip; 4988 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 4989 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); 4990 struct rtw89_btc *btc = &rtwdev->btc; 4991 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4992 struct rtw89_btc_wl_link_info r = {0}; 4993 struct rtw89_btc_wl_link_info *wlinfo = NULL; 4994 u8 mode = 0; 4995 4996 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 4997 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4998 "[BTC], role is STA=%d\n", 4999 vif->type == NL80211_IFTYPE_STATION); 5000 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); 5001 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 5002 chan->band_type, chan->channel, chan->band_width); 5003 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 5004 state == BTC_ROLE_MSTS_STA_CONN_END); 5005 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5006 "[BTC], bcn_period=%d dtim_period=%d\n", 5007 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); 5008 5009 if (rtwsta) { 5010 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 5011 rtwsta->mac_id); 5012 5013 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5014 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 5015 sta->deflink.he_cap.has_he, 5016 sta->deflink.vht_cap.vht_supported, 5017 sta->deflink.ht_cap.ht_supported); 5018 if (sta->deflink.he_cap.has_he) 5019 mode |= BIT(BTC_WL_MODE_HE); 5020 if (sta->deflink.vht_cap.vht_supported) 5021 mode |= BIT(BTC_WL_MODE_VHT); 5022 if (sta->deflink.ht_cap.ht_supported) 5023 mode |= BIT(BTC_WL_MODE_HT); 5024 5025 r.mode = mode; 5026 } 5027 5028 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) 5029 return; 5030 5031 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5032 "[BTC], wifi_role=%d\n", rtwvif->wifi_role); 5033 5034 r.role = rtwvif->wifi_role; 5035 r.phy = rtwvif->phy_idx; 5036 r.pid = rtwvif->port; 5037 r.active = true; 5038 r.connected = MLME_LINKED; 5039 r.bcn_period = vif->bss_conf.beacon_int; 5040 r.dtim_period = vif->bss_conf.dtim_period; 5041 r.band = chan->band_type; 5042 r.ch = chan->channel; 5043 r.bw = chan->band_width; 5044 ether_addr_copy(r.mac_addr, rtwvif->mac_addr); 5045 5046 if (rtwsta && vif->type == NL80211_IFTYPE_STATION) 5047 r.mac_id = rtwsta->mac_id; 5048 5049 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 5050 5051 wlinfo = &wl->link_info[r.pid]; 5052 5053 memcpy(wlinfo, &r, sizeof(*wlinfo)); 5054 if (chip->chip_id == RTL8852A) 5055 _update_wl_info(rtwdev); 5056 else 5057 _update_wl_info_v1(rtwdev); 5058 5059 if (wlinfo->role == RTW89_WIFI_ROLE_STATION && 5060 wlinfo->connected == MLME_NO_LINK) 5061 btc->dm.leak_ap = 0; 5062 5063 if (state == BTC_ROLE_MSTS_STA_CONN_START) 5064 wl->status.map.connecting = 1; 5065 else 5066 wl->status.map.connecting = 0; 5067 5068 if (state == BTC_ROLE_MSTS_STA_DIS_CONN) 5069 wl->status.map._4way = false; 5070 5071 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 5072 } 5073 5074 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 5075 { 5076 const struct rtw89_chip_info *chip = rtwdev->chip; 5077 struct rtw89_btc *btc = &rtwdev->btc; 5078 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5079 u32 val; 5080 5081 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 5082 __func__, rf_state); 5083 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 5084 5085 switch (rf_state) { 5086 case BTC_RFCTRL_WL_OFF: 5087 wl->status.map.rf_off = 1; 5088 wl->status.map.lps = BTC_LPS_OFF; 5089 wl->status.map.busy = 0; 5090 break; 5091 case BTC_RFCTRL_FW_CTRL: 5092 wl->status.map.rf_off = 0; 5093 wl->status.map.lps = BTC_LPS_RF_OFF; 5094 wl->status.map.busy = 0; 5095 break; 5096 case BTC_RFCTRL_WL_ON: 5097 default: 5098 wl->status.map.rf_off = 0; 5099 wl->status.map.lps = BTC_LPS_OFF; 5100 break; 5101 } 5102 5103 if (rf_state == BTC_RFCTRL_WL_ON) { 5104 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0; 5105 rtw89_btc_fw_en_rpt(rtwdev, 5106 RPT_EN_MREG | RPT_EN_BT_VER_INFO, true); 5107 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 5108 _write_scbd(rtwdev, val, true); 5109 _update_bt_scbd(rtwdev, true); 5110 chip->ops->btc_init_cfg(rtwdev); 5111 } else { 5112 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false); 5113 if (rf_state == BTC_RFCTRL_WL_OFF) 5114 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 5115 } 5116 5117 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 5118 5119 wl->status.map.rf_off_pre = wl->status.map.rf_off; 5120 wl->status.map.lps_pre = wl->status.map.lps; 5121 } 5122 5123 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 5124 enum btc_wl_rfk_type type, 5125 enum btc_wl_rfk_state state) 5126 { 5127 struct rtw89_btc *btc = &rtwdev->btc; 5128 struct rtw89_btc_cx *cx = &btc->cx; 5129 struct rtw89_btc_wl_info *wl = &cx->wl; 5130 bool result = BTC_WRFK_REJECT; 5131 5132 wl->rfk_info.type = type; 5133 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 5134 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 5135 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 5136 5137 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5138 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 5139 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 5140 type, state); 5141 5142 switch (state) { 5143 case BTC_WRFK_START: 5144 result = _chk_wl_rfk_request(rtwdev); 5145 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP; 5146 5147 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result); 5148 5149 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 5150 break; 5151 case BTC_WRFK_ONESHOT_START: 5152 case BTC_WRFK_ONESHOT_STOP: 5153 if (wl->rfk_info.state == BTC_WRFK_STOP) { 5154 result = BTC_WRFK_REJECT; 5155 } else { 5156 result = BTC_WRFK_ALLOW; 5157 wl->rfk_info.state = state; 5158 } 5159 break; 5160 case BTC_WRFK_STOP: 5161 result = BTC_WRFK_ALLOW; 5162 wl->rfk_info.state = BTC_WRFK_STOP; 5163 5164 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 5165 cancel_delayed_work(&rtwdev->coex_rfk_chk_work); 5166 break; 5167 default: 5168 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5169 "[BTC], %s() warning state=%d\n", __func__, state); 5170 break; 5171 } 5172 5173 if (result == BTC_WRFK_ALLOW) { 5174 if (wl->rfk_info.state == BTC_WRFK_START || 5175 wl->rfk_info.state == BTC_WRFK_STOP) 5176 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 5177 5178 if (wl->rfk_info.state == BTC_WRFK_START) 5179 ieee80211_queue_delayed_work(rtwdev->hw, 5180 &rtwdev->coex_rfk_chk_work, 5181 RTW89_COEX_RFK_CHK_WORK_PERIOD); 5182 } 5183 5184 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5185 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 5186 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 5187 5188 return result == BTC_WRFK_ALLOW; 5189 } 5190 5191 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 5192 enum btc_wl_rfk_type type, 5193 enum btc_wl_rfk_state state) 5194 { 5195 u8 band; 5196 bool allow; 5197 int ret; 5198 5199 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 5200 5201 rtw89_debug(rtwdev, RTW89_DBG_RFK, 5202 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 5203 band == RTW89_BAND_2G ? "2G" : 5204 band == RTW89_BAND_5G ? "5G" : "6G", 5205 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 5206 type, 5207 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 5208 state == BTC_WRFK_STOP ? "RFK_STOP" : 5209 state == BTC_WRFK_START ? "RFK_START" : 5210 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 5211 "ONE-SHOT_STOP"); 5212 5213 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 5214 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 5215 return; 5216 } 5217 5218 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 5219 rtwdev, phy_map, type, state); 5220 if (ret) { 5221 rtw89_warn(rtwdev, "RFK notify timeout\n"); 5222 rtwdev->is_bt_iqk_timeout = true; 5223 } 5224 } 5225 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 5226 5227 struct rtw89_btc_wl_sta_iter_data { 5228 struct rtw89_dev *rtwdev; 5229 u8 busy_all; 5230 u8 dir_all; 5231 u8 rssi_map_all; 5232 bool is_sta_change; 5233 bool is_traffic_change; 5234 }; 5235 5236 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 5237 { 5238 struct rtw89_btc_wl_sta_iter_data *iter_data = 5239 (struct rtw89_btc_wl_sta_iter_data *)data; 5240 struct rtw89_dev *rtwdev = iter_data->rtwdev; 5241 struct rtw89_btc *btc = &rtwdev->btc; 5242 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5243 struct rtw89_btc_wl_link_info *link_info = NULL; 5244 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; 5245 struct rtw89_traffic_stats *link_info_t = NULL; 5246 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 5247 struct rtw89_traffic_stats *stats = &rtwvif->stats; 5248 const struct rtw89_chip_info *chip = rtwdev->chip; 5249 u32 last_tx_rate, last_rx_rate; 5250 u16 last_tx_lvl, last_rx_lvl; 5251 u8 port = rtwvif->port; 5252 u8 rssi; 5253 u8 busy = 0; 5254 u8 dir = 0; 5255 u8 rssi_map = 0; 5256 u8 i = 0; 5257 bool is_sta_change = false, is_traffic_change = false; 5258 5259 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; 5260 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 5261 5262 link_info = &wl->link_info[port]; 5263 link_info->stat.traffic = rtwvif->stats; 5264 link_info_t = &link_info->stat.traffic; 5265 5266 if (link_info->connected == MLME_NO_LINK) { 5267 link_info->rx_rate_drop_cnt = 0; 5268 return; 5269 } 5270 5271 link_info->stat.rssi = rssi; 5272 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 5273 link_info->rssi_state[i] = 5274 _update_rssi_state(rtwdev, 5275 link_info->rssi_state[i], 5276 link_info->stat.rssi, 5277 chip->wl_rssi_thres[i]); 5278 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 5279 rssi_map |= BIT(i); 5280 5281 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED && 5282 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 5283 is_sta_change = true; 5284 } 5285 iter_data->rssi_map_all |= rssi_map; 5286 5287 last_tx_rate = link_info_t->tx_rate; 5288 last_rx_rate = link_info_t->rx_rate; 5289 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 5290 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 5291 5292 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 5293 stats->rx_tfc_lv != RTW89_TFC_IDLE) 5294 busy = 1; 5295 5296 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 5297 dir = RTW89_TFC_UL; 5298 else 5299 dir = RTW89_TFC_DL; 5300 5301 link_info = &wl->link_info[port]; 5302 if (link_info->busy != busy || link_info->dir != dir) { 5303 is_sta_change = true; 5304 link_info->busy = busy; 5305 link_info->dir = dir; 5306 } 5307 5308 iter_data->busy_all |= busy; 5309 iter_data->dir_all |= BIT(dir); 5310 5311 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 5312 last_rx_rate > RTW89_HW_RATE_CCK2 && 5313 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 5314 link_info->rx_rate_drop_cnt++; 5315 5316 if (last_tx_rate != rtwsta->ra_report.hw_rate || 5317 last_rx_rate != rtwsta->rx_hw_rate || 5318 last_tx_lvl != link_info_t->tx_tfc_lv || 5319 last_rx_lvl != link_info_t->rx_tfc_lv) 5320 is_traffic_change = true; 5321 5322 link_info_t->tx_rate = rtwsta->ra_report.hw_rate; 5323 link_info_t->rx_rate = rtwsta->rx_hw_rate; 5324 5325 wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv; 5326 wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv; 5327 wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate; 5328 wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate; 5329 5330 if (is_sta_change) 5331 iter_data->is_sta_change = true; 5332 5333 if (is_traffic_change) 5334 iter_data->is_traffic_change = true; 5335 } 5336 5337 #define BTC_NHM_CHK_INTVL 20 5338 5339 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 5340 { 5341 struct rtw89_btc *btc = &rtwdev->btc; 5342 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5343 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 5344 u8 i; 5345 5346 ieee80211_iterate_stations_atomic(rtwdev->hw, 5347 rtw89_btc_ntfy_wl_sta_iter, 5348 &data); 5349 5350 wl->rssi_level = 0; 5351 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 5352 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 5353 /* set RSSI level 4 ~ 0 if rssi bit map match */ 5354 if (data.rssi_map_all & BIT(i - 1)) { 5355 wl->rssi_level = i; 5356 break; 5357 } 5358 } 5359 5360 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 5361 __func__, !!wl->status.map.busy); 5362 5363 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 5364 5365 if (data.is_traffic_change) 5366 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5367 if (data.is_sta_change) { 5368 wl->status.map.busy = data.busy_all; 5369 wl->status.map.traffic_dir = data.dir_all; 5370 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 5371 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 5372 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 5373 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 5374 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 5375 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 5376 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 5377 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 5378 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 5379 } 5380 } 5381 5382 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 5383 u32 len, u8 class, u8 func) 5384 { 5385 struct rtw89_btc *btc = &rtwdev->btc; 5386 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 5387 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 5388 5389 len -= RTW89_C2H_HEADER_LEN; 5390 5391 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5392 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 5393 __func__, len, class, func); 5394 5395 if (class != BTFC_FW_EVENT) 5396 return; 5397 5398 switch (func) { 5399 case BTF_EVNT_RPT: 5400 case BTF_EVNT_BUF_OVERFLOW: 5401 pfwinfo->event[func]++; 5402 /* Don't need rtw89_leave_ps_mode() */ 5403 btc_fw_event(rtwdev, func, buf, len); 5404 break; 5405 case BTF_EVNT_BT_INFO: 5406 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5407 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 5408 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++; 5409 _update_bt_info(rtwdev, buf, len); 5410 break; 5411 case BTF_EVNT_BT_SCBD: 5412 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5413 "[BTC], handle C2H BT SCBD with data %8ph\n", buf); 5414 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++; 5415 _update_bt_scbd(rtwdev, false); 5416 break; 5417 case BTF_EVNT_BT_PSD: 5418 break; 5419 case BTF_EVNT_BT_REG: 5420 btc->dbg.rb_done = true; 5421 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 5422 5423 break; 5424 case BTF_EVNT_C2H_LOOPBACK: 5425 btc->dbg.rb_done = true; 5426 btc->dbg.rb_val = buf[0]; 5427 break; 5428 case BTF_EVNT_CX_RUNINFO: 5429 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 5430 break; 5431 } 5432 } 5433 5434 #define BTC_CX_FW_OFFLOAD 0 5435 5436 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5437 { 5438 const struct rtw89_chip_info *chip = rtwdev->chip; 5439 struct rtw89_hal *hal = &rtwdev->hal; 5440 struct rtw89_btc *btc = &rtwdev->btc; 5441 struct rtw89_btc_dm *dm = &btc->dm; 5442 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5443 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5444 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 5445 5446 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 5447 return; 5448 5449 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 5450 5451 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n", 5452 chip->chip_id); 5453 5454 ver_main = FIELD_GET(GENMASK(31, 24), chip->para_ver); 5455 ver_sub = FIELD_GET(GENMASK(23, 16), chip->para_ver); 5456 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->para_ver); 5457 id_branch = FIELD_GET(GENMASK(7, 0), chip->para_ver); 5458 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ", 5459 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch); 5460 5461 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD) 5462 dm->error.map.offload_mismatch = true; 5463 else 5464 dm->error.map.offload_mismatch = false; 5465 5466 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 5467 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 5468 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 5469 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 5470 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)", 5471 ver_main, ver_sub, ver_hotfix, id_branch); 5472 5473 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 5474 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 5475 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 5476 seq_printf(m, "(%s, desired:%d.%d.%d), ", 5477 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 5478 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 5479 5480 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n", 5481 bt->ver_info.fw_coex, 5482 (bt->ver_info.fw_coex >= chip->btcx_desired ? 5483 "Match" : "Mismatch"), chip->btcx_desired); 5484 5485 if (bt->enable.now && bt->ver_info.fw == 0) 5486 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 5487 else 5488 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 5489 5490 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 5491 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 5492 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 5493 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 5494 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n", 5495 "[sub_module]", 5496 ver_main, ver_sub, ver_hotfix, id_branch, 5497 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 5498 5499 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 5500 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type, 5501 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num, 5502 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ? 5503 "1Ant_Pos:S1, " : "1Ant_Pos:S0, "))); 5504 5505 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 5506 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, 5507 hal->rx_nss); 5508 } 5509 5510 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5511 { 5512 struct rtw89_btc *btc = &rtwdev->btc; 5513 struct rtw89_btc_wl_link_info *plink = NULL; 5514 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5515 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5516 struct rtw89_traffic_stats *t; 5517 u8 i; 5518 5519 if (rtwdev->dbcc_en) { 5520 seq_printf(m, 5521 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ", 5522 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0], 5523 wl_dinfo->scan_band[RTW89_PHY_0], 5524 wl_dinfo->real_band[RTW89_PHY_0]); 5525 seq_printf(m, 5526 "PHY1_band(op:%d/scan:%d/real:%d)\n", 5527 wl_dinfo->op_band[RTW89_PHY_1], 5528 wl_dinfo->scan_band[RTW89_PHY_1], 5529 wl_dinfo->real_band[RTW89_PHY_1]); 5530 } 5531 5532 for (i = 0; i < RTW89_PORT_NUM; i++) { 5533 plink = &btc->cx.wl.link_info[i]; 5534 5535 if (!plink->active) 5536 continue; 5537 5538 seq_printf(m, 5539 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 5540 plink->pid, (u32)plink->role, plink->phy, 5541 (u32)plink->connected, plink->client_cnt - 1, 5542 (u32)plink->mode, plink->ch, (u32)plink->bw); 5543 5544 if (plink->connected == MLME_NO_LINK) 5545 continue; 5546 5547 seq_printf(m, 5548 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 5549 plink->mac_id, plink->tx_time, plink->tx_retry); 5550 5551 seq_printf(m, 5552 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 5553 plink->pid, 110 - plink->stat.rssi, 5554 plink->stat.rssi, plink->busy, 5555 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 5556 5557 t = &plink->stat.traffic; 5558 5559 seq_printf(m, 5560 "tx[rate:%d/busy_level:%d], ", 5561 (u32)t->tx_rate, t->tx_tfc_lv); 5562 5563 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n", 5564 (u32)t->rx_rate, 5565 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 5566 } 5567 } 5568 5569 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5570 { 5571 const struct rtw89_chip_info *chip = rtwdev->chip; 5572 struct rtw89_btc *btc = &rtwdev->btc; 5573 struct rtw89_btc_cx *cx = &btc->cx; 5574 struct rtw89_btc_wl_info *wl = &cx->wl; 5575 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5576 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5577 u8 mode; 5578 5579 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 5580 return; 5581 5582 seq_puts(m, "========== [WL Status] ==========\n"); 5583 5584 if (chip->chip_id == RTL8852A) 5585 mode = wl_rinfo->link_mode; 5586 else 5587 mode = wl_rinfo_v1->link_mode; 5588 5589 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode); 5590 5591 seq_printf(m, 5592 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 5593 wl->status.map.rf_off, wl->status.map.lps, 5594 wl->status.map.scan ? "Y" : "N", 5595 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 5596 5597 seq_printf(m, 5598 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n", 5599 wl->status.map.connecting ? "Y" : "N", 5600 wl->status.map.roaming ? "Y" : "N", 5601 wl->status.map._4way ? "Y" : "N", 5602 wl->status.map.init_ok ? "Y" : "N"); 5603 5604 _show_wl_role_info(rtwdev, m); 5605 } 5606 5607 enum btc_bt_a2dp_type { 5608 BTC_A2DP_LEGACY = 0, 5609 BTC_A2DP_TWS_SNIFF = 1, 5610 BTC_A2DP_TWS_RELAY = 2, 5611 }; 5612 5613 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5614 { 5615 struct rtw89_btc *btc = &rtwdev->btc; 5616 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 5617 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 5618 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 5619 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 5620 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 5621 5622 if (hfp.exist) { 5623 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 5624 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 5625 bt_linfo->sut_pwr_level[0], 5626 bt_linfo->golden_rx_shift[0]); 5627 } 5628 5629 if (hid.exist) { 5630 seq_printf(m, 5631 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 5632 "[HID]", 5633 hid.type & BTC_HID_218 ? "2/18," : "", 5634 hid.type & BTC_HID_418 ? "4/18," : "", 5635 hid.type & BTC_HID_BLE ? "BLE," : "", 5636 hid.type & BTC_HID_RCU ? "RCU," : "", 5637 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 5638 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 5639 bt_linfo->golden_rx_shift[1]); 5640 } 5641 5642 if (a2dp.exist) { 5643 seq_printf(m, 5644 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 5645 "[A2DP]", 5646 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 5647 a2dp.bitpool, a2dp.flush_time); 5648 5649 seq_printf(m, 5650 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 5651 a2dp.vendor_id, a2dp.device_name, 5652 bt_linfo->sut_pwr_level[2], 5653 bt_linfo->golden_rx_shift[2]); 5654 } 5655 5656 if (pan.exist) { 5657 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n", 5658 "[PAN]", 5659 bt_linfo->sut_pwr_level[3], 5660 bt_linfo->golden_rx_shift[3]); 5661 } 5662 } 5663 5664 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5665 { 5666 struct rtw89_btc *btc = &rtwdev->btc; 5667 struct rtw89_btc_cx *cx = &btc->cx; 5668 struct rtw89_btc_bt_info *bt = &cx->bt; 5669 struct rtw89_btc_wl_info *wl = &cx->wl; 5670 struct rtw89_btc_module *module = &btc->mdinfo; 5671 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 5672 u8 *afh = bt_linfo->afh_map; 5673 5674 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 5675 return; 5676 5677 seq_puts(m, "========== [BT Status] ==========\n"); 5678 5679 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ", 5680 "[status]", bt->enable.now ? "Y" : "N", 5681 bt->btg_type ? "Y" : "N", 5682 (bt->enable.now && (bt->btg_type != module->bt_pos) ? 5683 "(efuse-mismatch!!)" : ""), 5684 (bt_linfo->status.map.connect ? "Y" : "N")); 5685 5686 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 5687 bt->igno_wl ? "Y" : "N", 5688 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 5689 5690 seq_printf(m, " %-15s : profile:%s%s%s%s%s ", 5691 "[profile]", 5692 (bt_linfo->profile_cnt.now == 0) ? "None," : "", 5693 bt_linfo->hfp_desc.exist ? "HFP," : "", 5694 bt_linfo->hid_desc.exist ? "HID," : "", 5695 bt_linfo->a2dp_desc.exist ? 5696 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 5697 bt_linfo->pan_desc.exist ? "PAN," : ""); 5698 5699 seq_printf(m, 5700 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 5701 bt_linfo->multi_link.now ? "Y" : "N", 5702 bt_linfo->slave_role ? "Slave" : "Master", 5703 bt_linfo->status.map.ble_connect ? "Y" : "N", 5704 bt_linfo->cqddr ? "Y" : "N", 5705 bt_linfo->a2dp_desc.active ? "Y" : "N", 5706 bt_linfo->pan_desc.active ? "Y" : "N"); 5707 5708 seq_printf(m, 5709 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s", 5710 "[link]", bt_linfo->rssi - 100, 5711 bt_linfo->tx_3m ? 3 : 2, 5712 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 5713 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 5714 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 5715 5716 seq_printf(m, 5717 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 5718 bt_linfo->relink.now ? " ReLink!!" : "", 5719 afh[0], afh[1], afh[2], afh[3], afh[4], 5720 afh[5], afh[6], afh[7], afh[8], afh[9]); 5721 5722 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n", 5723 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw); 5724 5725 seq_printf(m, 5726 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 5727 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY], 5728 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG], 5729 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]); 5730 5731 seq_printf(m, 5732 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 5733 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH], 5734 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ], 5735 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]); 5736 5737 _show_bt_profile_info(rtwdev, m); 5738 5739 seq_printf(m, 5740 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 5741 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 5742 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 5743 bt->raw_info[7], 5744 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 5745 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 5746 cx->cnt_bt[BTC_BCNT_INFOSAME]); 5747 5748 seq_printf(m, 5749 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n", 5750 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX], 5751 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX], 5752 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]); 5753 } 5754 5755 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 5756 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 5757 #define CASE_BTC_POLICY_STR(e) \ 5758 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 5759 5760 static const char *steps_to_str(u16 step) 5761 { 5762 switch (step) { 5763 CASE_BTC_RSN_STR(NONE); 5764 CASE_BTC_RSN_STR(NTFY_INIT); 5765 CASE_BTC_RSN_STR(NTFY_SWBAND); 5766 CASE_BTC_RSN_STR(NTFY_WL_STA); 5767 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 5768 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 5769 CASE_BTC_RSN_STR(NTFY_WL_RFK); 5770 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 5771 CASE_BTC_RSN_STR(NTFY_SCAN_START); 5772 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 5773 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 5774 CASE_BTC_RSN_STR(NTFY_POWEROFF); 5775 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 5776 CASE_BTC_RSN_STR(CMD_SET_COEX); 5777 CASE_BTC_RSN_STR(ACT1_WORK); 5778 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 5779 CASE_BTC_RSN_STR(RFK_CHK_WORK); 5780 5781 CASE_BTC_ACT_STR(NONE); 5782 CASE_BTC_ACT_STR(WL_ONLY); 5783 CASE_BTC_ACT_STR(WL_5G); 5784 CASE_BTC_ACT_STR(WL_OTHER); 5785 CASE_BTC_ACT_STR(WL_IDLE); 5786 CASE_BTC_ACT_STR(WL_NC); 5787 CASE_BTC_ACT_STR(WL_RFK); 5788 CASE_BTC_ACT_STR(WL_INIT); 5789 CASE_BTC_ACT_STR(WL_OFF); 5790 CASE_BTC_ACT_STR(FREERUN); 5791 CASE_BTC_ACT_STR(BT_WHQL); 5792 CASE_BTC_ACT_STR(BT_RFK); 5793 CASE_BTC_ACT_STR(BT_OFF); 5794 CASE_BTC_ACT_STR(BT_IDLE); 5795 CASE_BTC_ACT_STR(BT_HFP); 5796 CASE_BTC_ACT_STR(BT_HID); 5797 CASE_BTC_ACT_STR(BT_A2DP); 5798 CASE_BTC_ACT_STR(BT_A2DPSINK); 5799 CASE_BTC_ACT_STR(BT_PAN); 5800 CASE_BTC_ACT_STR(BT_A2DP_HID); 5801 CASE_BTC_ACT_STR(BT_A2DP_PAN); 5802 CASE_BTC_ACT_STR(BT_PAN_HID); 5803 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 5804 CASE_BTC_ACT_STR(WL_25G_MCC); 5805 CASE_BTC_ACT_STR(WL_2G_MCC); 5806 CASE_BTC_ACT_STR(WL_2G_SCC); 5807 CASE_BTC_ACT_STR(WL_2G_AP); 5808 CASE_BTC_ACT_STR(WL_2G_GO); 5809 CASE_BTC_ACT_STR(WL_2G_GC); 5810 CASE_BTC_ACT_STR(WL_2G_NAN); 5811 5812 CASE_BTC_POLICY_STR(OFF_BT); 5813 CASE_BTC_POLICY_STR(OFF_WL); 5814 CASE_BTC_POLICY_STR(OFF_EQ0); 5815 CASE_BTC_POLICY_STR(OFF_EQ1); 5816 CASE_BTC_POLICY_STR(OFF_EQ2); 5817 CASE_BTC_POLICY_STR(OFF_EQ3); 5818 CASE_BTC_POLICY_STR(OFF_BWB0); 5819 CASE_BTC_POLICY_STR(OFF_BWB1); 5820 CASE_BTC_POLICY_STR(OFF_BWB2); 5821 CASE_BTC_POLICY_STR(OFFB_BWB0); 5822 CASE_BTC_POLICY_STR(OFFE_DEF); 5823 CASE_BTC_POLICY_STR(OFFE_DEF2); 5824 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 5825 CASE_BTC_POLICY_STR(OFFE_2GISOB); 5826 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 5827 CASE_BTC_POLICY_STR(OFFE_WL); 5828 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 5829 CASE_BTC_POLICY_STR(FIX_TD3030); 5830 CASE_BTC_POLICY_STR(FIX_TD5050); 5831 CASE_BTC_POLICY_STR(FIX_TD2030); 5832 CASE_BTC_POLICY_STR(FIX_TD4010); 5833 CASE_BTC_POLICY_STR(FIX_TD7010); 5834 CASE_BTC_POLICY_STR(FIX_TD2060); 5835 CASE_BTC_POLICY_STR(FIX_TD3060); 5836 CASE_BTC_POLICY_STR(FIX_TD2080); 5837 CASE_BTC_POLICY_STR(FIX_TDW1B1); 5838 CASE_BTC_POLICY_STR(FIX_TD4020); 5839 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 5840 CASE_BTC_POLICY_STR(PFIX_TD3030); 5841 CASE_BTC_POLICY_STR(PFIX_TD5050); 5842 CASE_BTC_POLICY_STR(PFIX_TD2030); 5843 CASE_BTC_POLICY_STR(PFIX_TD2060); 5844 CASE_BTC_POLICY_STR(PFIX_TD3070); 5845 CASE_BTC_POLICY_STR(PFIX_TD2080); 5846 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 5847 CASE_BTC_POLICY_STR(AUTO_TD50B1); 5848 CASE_BTC_POLICY_STR(AUTO_TD60B1); 5849 CASE_BTC_POLICY_STR(AUTO_TD20B1); 5850 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 5851 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 5852 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 5853 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 5854 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 5855 CASE_BTC_POLICY_STR(AUTO2_TD3050); 5856 CASE_BTC_POLICY_STR(AUTO2_TD3070); 5857 CASE_BTC_POLICY_STR(AUTO2_TD5050); 5858 CASE_BTC_POLICY_STR(AUTO2_TD6060); 5859 CASE_BTC_POLICY_STR(AUTO2_TD2080); 5860 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 5861 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 5862 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 5863 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 5864 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 5865 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 5866 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 5867 default: 5868 return "unknown step"; 5869 } 5870 } 5871 5872 static 5873 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data, 5874 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 5875 { 5876 u8 i; 5877 u8 cur_index; 5878 5879 for (i = 0; i < len ; i++) { 5880 if ((i % seg_len) == 0) 5881 seq_printf(m, " %-15s : ", prefix); 5882 cur_index = (start_idx + i) % ring_len; 5883 if (i % 3 == 0) 5884 seq_printf(m, "-> %-20s", 5885 steps_to_str(*(data + cur_index))); 5886 else if (i % 3 == 1) 5887 seq_printf(m, "-> %-15s", 5888 steps_to_str(*(data + cur_index))); 5889 else 5890 seq_printf(m, "-> %-13s", 5891 steps_to_str(*(data + cur_index))); 5892 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 5893 seq_puts(m, "\n"); 5894 } 5895 } 5896 5897 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m) 5898 { 5899 struct rtw89_btc *btc = &rtwdev->btc; 5900 struct rtw89_btc_dm *dm = &btc->dm; 5901 u8 start_idx; 5902 u8 len; 5903 5904 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 5905 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 5906 5907 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx, 5908 ARRAY_SIZE(dm->dm_step.step)); 5909 } 5910 5911 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m) 5912 { 5913 struct rtw89_btc *btc = &rtwdev->btc; 5914 struct rtw89_btc_module *module = &btc->mdinfo; 5915 struct rtw89_btc_dm *dm = &btc->dm; 5916 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5917 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5918 5919 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 5920 return; 5921 5922 seq_printf(m, "========== [Mechanism Status %s] ==========\n", 5923 (btc->ctrl.manual ? "(Manual)" : "(Auto)")); 5924 5925 seq_printf(m, 5926 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n", 5927 "[status]", 5928 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated", 5929 steps_to_str(dm->run_reason), 5930 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 5931 FIELD_GET(GENMASK(7, 0), dm->set_ant_path), 5932 dm->cnt_dm[BTC_DCNT_RUN]); 5933 5934 _show_dm_step(rtwdev, m); 5935 5936 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 5937 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt, 5938 dm->freerun, btc->lps, dm->wl_mimo_ps); 5939 5940 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap, 5941 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 5942 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 5943 "" : "(Mismatch!!)")); 5944 5945 if (dm->rf_trx_para.wl_tx_power == 0xff) 5946 seq_printf(m, 5947 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ", 5948 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level); 5949 5950 else 5951 seq_printf(m, 5952 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ", 5953 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level, 5954 dm->rf_trx_para.wl_tx_power); 5955 5956 seq_printf(m, 5957 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n", 5958 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power, 5959 dm->rf_trx_para.bt_rx_gain, 5960 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx); 5961 5962 seq_printf(m, 5963 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU\n", 5964 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time, 5965 dm->wl_tx_limit.tx_retry, btc->bt_req_len); 5966 } 5967 5968 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m) 5969 { 5970 struct rtw89_btc *btc = &rtwdev->btc; 5971 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 5972 struct rtw89_btc_fbtc_cysta *pcysta = NULL; 5973 5974 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 5975 5976 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && 5977 pcysta->except_cnt == 0 && 5978 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 5979 return; 5980 5981 seq_printf(m, " %-15s : ", "[error]"); 5982 5983 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 5984 seq_printf(m, 5985 "overflow-cnt: %d, ", 5986 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 5987 } 5988 5989 if (pfwinfo->len_mismch) { 5990 seq_printf(m, 5991 "len-mismatch: 0x%x, ", 5992 pfwinfo->len_mismch); 5993 } 5994 5995 if (pfwinfo->fver_mismch) { 5996 seq_printf(m, 5997 "fver-mismatch: 0x%x, ", 5998 pfwinfo->fver_mismch); 5999 } 6000 6001 /* cycle statistics exceptions */ 6002 if (pcysta->exception || pcysta->except_cnt) { 6003 seq_printf(m, 6004 "exception-type: 0x%x, exception-cnt = %d", 6005 pcysta->exception, pcysta->except_cnt); 6006 } 6007 seq_puts(m, "\n"); 6008 } 6009 6010 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m) 6011 { 6012 struct rtw89_btc *btc = &rtwdev->btc; 6013 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6014 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6015 struct rtw89_btc_fbtc_tdma *t = NULL; 6016 struct rtw89_btc_fbtc_slot *s = NULL; 6017 struct rtw89_btc_dm *dm = &btc->dm; 6018 u8 i, cnt = 0; 6019 6020 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 6021 if (!pcinfo->valid) 6022 return; 6023 6024 t = &pfwinfo->rpt_fbtc_tdma.finfo; 6025 6026 seq_printf(m, 6027 " %-15s : ", "[tdma_policy]"); 6028 seq_printf(m, 6029 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ", 6030 (u32)t->type, 6031 t->rxflctrl, t->txpause); 6032 6033 seq_printf(m, 6034 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ", 6035 t->wtgle_n, t->leak_n, t->ext_ctrl); 6036 6037 seq_printf(m, 6038 "policy_type:%d", 6039 (u32)btc->policy_type); 6040 6041 s = pfwinfo->rpt_fbtc_slots.finfo.slot; 6042 6043 for (i = 0; i < CXST_MAX; i++) { 6044 if (dm->update_slot_map == BIT(CXST_MAX) - 1) 6045 break; 6046 6047 if (!(dm->update_slot_map & BIT(i))) 6048 continue; 6049 6050 if (cnt % 6 == 0) 6051 seq_printf(m, 6052 " %-15s : %d[%d/0x%x/%d]", 6053 "[slot_policy]", 6054 (u32)i, 6055 s[i].dur, s[i].cxtbl, s[i].cxtype); 6056 else 6057 seq_printf(m, 6058 ", %d[%d/0x%x/%d]", 6059 (u32)i, 6060 s[i].dur, s[i].cxtbl, s[i].cxtype); 6061 if (cnt % 6 == 5) 6062 seq_puts(m, "\n"); 6063 cnt++; 6064 } 6065 seq_puts(m, "\n"); 6066 } 6067 6068 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m) 6069 { 6070 struct rtw89_btc *btc = &rtwdev->btc; 6071 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6072 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6073 struct rtw89_btc_fbtc_slots *pslots = NULL; 6074 struct rtw89_btc_fbtc_slot s; 6075 u8 i = 0; 6076 6077 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 6078 if (!pcinfo->valid) 6079 return; 6080 6081 pslots = &pfwinfo->rpt_fbtc_slots.finfo; 6082 6083 for (i = 0; i < CXST_MAX; i++) { 6084 s = pslots->slot[i]; 6085 if (i % 6 == 0) 6086 seq_printf(m, 6087 " %-15s : %02d[%03d/0x%x/%d]", 6088 "[slot_list]", 6089 (u32)i, 6090 s.dur, s.cxtbl, s.cxtype); 6091 else 6092 seq_printf(m, 6093 ", %02d[%03d/0x%x/%d]", 6094 (u32)i, 6095 s.dur, s.cxtbl, s.cxtype); 6096 if (i % 6 == 5) 6097 seq_puts(m, "\n"); 6098 } 6099 } 6100 6101 static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m) 6102 { 6103 struct rtw89_btc *btc = &rtwdev->btc; 6104 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6105 struct rtw89_btc_dm *dm = &btc->dm; 6106 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 6107 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6108 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL; 6109 struct rtw89_btc_fbtc_cysta_cpu pcysta[1]; 6110 union rtw89_btc_fbtc_rxflct r; 6111 u8 i, cnt = 0, slot_pair; 6112 u16 cycle, c_begin, c_end, store_index; 6113 6114 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 6115 if (!pcinfo->valid) 6116 return; 6117 6118 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo; 6119 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta); 6120 seq_printf(m, 6121 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 6122 "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL], 6123 pcysta->bcn_cnt[CXBCN_ALL_OK], 6124 pcysta->bcn_cnt[CXBCN_BT_SLOT], 6125 pcysta->bcn_cnt[CXBCN_BT_OK]); 6126 6127 for (i = 0; i < CXST_MAX; i++) { 6128 if (!pcysta->slot_cnt[i]) 6129 continue; 6130 seq_printf(m, 6131 ", %d:%d", (u32)i, pcysta->slot_cnt[i]); 6132 } 6133 6134 if (dm->tdma_now.rxflctrl) { 6135 seq_printf(m, 6136 ", leak_rx:%d", pcysta->leakrx_cnt); 6137 } 6138 6139 if (pcysta->collision_cnt) { 6140 seq_printf(m, 6141 ", collision:%d", pcysta->collision_cnt); 6142 } 6143 6144 if (pcysta->skip_cnt) { 6145 seq_printf(m, 6146 ", skip:%d", pcysta->skip_cnt); 6147 } 6148 seq_puts(m, "\n"); 6149 6150 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 6151 "[cycle_time]", 6152 pcysta->tavg_cycle[CXT_WL], 6153 pcysta->tavg_cycle[CXT_BT], 6154 pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000); 6155 seq_printf(m, 6156 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 6157 pcysta->tmax_cycle[CXT_WL], 6158 pcysta->tmax_cycle[CXT_BT], 6159 pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000); 6160 seq_printf(m, 6161 ", maxdiff_t[wl:%d/bt:%d]\n", 6162 pcysta->tmaxdiff_cycle[CXT_WL], 6163 pcysta->tmaxdiff_cycle[CXT_BT]); 6164 6165 if (pcysta->cycles == 0) 6166 return; 6167 6168 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 6169 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 6170 6171 if (pcysta->cycles <= slot_pair) 6172 c_begin = 1; 6173 else 6174 c_begin = pcysta->cycles - slot_pair + 1; 6175 6176 c_end = pcysta->cycles; 6177 6178 for (cycle = c_begin; cycle <= c_end; cycle++) { 6179 cnt++; 6180 store_index = ((cycle - 1) % slot_pair) * 2; 6181 6182 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 6183 seq_printf(m, 6184 " %-15s : ->b%02d->w%02d", "[cycle_step]", 6185 pcysta->tslot_cycle[store_index], 6186 pcysta->tslot_cycle[store_index + 1]); 6187 else 6188 seq_printf(m, 6189 "->b%02d->w%02d", 6190 pcysta->tslot_cycle[store_index], 6191 pcysta->tslot_cycle[store_index + 1]); 6192 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 6193 seq_puts(m, "\n"); 6194 } 6195 6196 if (a2dp->exist) { 6197 seq_printf(m, 6198 " %-15s : a2dp_ept:%d, a2dp_late:%d", 6199 "[a2dp_t_sta]", 6200 pcysta->a2dpept, pcysta->a2dpeptto); 6201 6202 seq_printf(m, 6203 ", avg_t:%d, max_t:%d", 6204 pcysta->tavg_a2dpept, pcysta->tmax_a2dpept); 6205 r.val = dm->tdma_now.rxflctrl; 6206 6207 if (r.type && r.tgln_n) { 6208 seq_printf(m, 6209 ", cycle[PSTDMA:%d/TDMA:%d], ", 6210 pcysta->cycles_a2dp[CXT_FLCTRL_ON], 6211 pcysta->cycles_a2dp[CXT_FLCTRL_OFF]); 6212 6213 seq_printf(m, 6214 "avg_t[PSTDMA:%d/TDMA:%d], ", 6215 pcysta->tavg_a2dp[CXT_FLCTRL_ON], 6216 pcysta->tavg_a2dp[CXT_FLCTRL_OFF]); 6217 6218 seq_printf(m, 6219 "max_t[PSTDMA:%d/TDMA:%d]", 6220 pcysta->tmax_a2dp[CXT_FLCTRL_ON], 6221 pcysta->tmax_a2dp[CXT_FLCTRL_OFF]); 6222 } 6223 seq_puts(m, "\n"); 6224 } 6225 } 6226 6227 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m) 6228 { 6229 struct rtw89_btc *btc = &rtwdev->btc; 6230 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6231 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6232 struct rtw89_btc_fbtc_cynullsta *ns = NULL; 6233 u8 i = 0; 6234 6235 if (!btc->dm.tdma_now.rxflctrl) 6236 return; 6237 6238 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 6239 if (!pcinfo->valid) 6240 return; 6241 6242 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 6243 6244 seq_printf(m, " %-15s : ", "[null_sta]"); 6245 6246 for (i = 0; i < 2; i++) { 6247 if (i != 0) 6248 seq_printf(m, ", null-%d", i); 6249 else 6250 seq_printf(m, "null-%d", i); 6251 seq_printf(m, "[ok:%d/", le32_to_cpu(ns->result[i][1])); 6252 seq_printf(m, "fail:%d/", le32_to_cpu(ns->result[i][0])); 6253 seq_printf(m, "on_time:%d/", le32_to_cpu(ns->result[i][2])); 6254 seq_printf(m, "retry:%d/", le32_to_cpu(ns->result[i][3])); 6255 seq_printf(m, "avg_t:%d.%03d/", 6256 le32_to_cpu(ns->avg_t[i]) / 1000, 6257 le32_to_cpu(ns->avg_t[i]) % 1000); 6258 seq_printf(m, "max_t:%d.%03d]", 6259 le32_to_cpu(ns->max_t[i]) / 1000, 6260 le32_to_cpu(ns->max_t[i]) % 1000); 6261 } 6262 seq_puts(m, "\n"); 6263 } 6264 6265 static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m) 6266 { 6267 struct rtw89_btc *btc = &rtwdev->btc; 6268 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6269 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6270 struct rtw89_btc_fbtc_steps *pstep = NULL; 6271 u8 type, val, cnt = 0, state = 0; 6272 bool outloop = false; 6273 u16 i, diff_t, n_start = 0, n_stop = 0; 6274 u16 pos_old, pos_new; 6275 6276 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 6277 if (!pcinfo->valid) 6278 return; 6279 6280 pstep = &pfwinfo->rpt_fbtc_step.finfo; 6281 pos_old = le16_to_cpu(pstep->pos_old); 6282 pos_new = le16_to_cpu(pstep->pos_new); 6283 6284 if (pcinfo->req_fver != pstep->fver) 6285 return; 6286 6287 /* store step info by using ring instead of FIFO*/ 6288 do { 6289 switch (state) { 6290 case 0: 6291 n_start = pos_old; 6292 if (pos_new >= pos_old) 6293 n_stop = pos_new; 6294 else 6295 n_stop = btc->ctrl.trace_step - 1; 6296 6297 state = 1; 6298 break; 6299 case 1: 6300 for (i = n_start; i <= n_stop; i++) { 6301 type = pstep->step[i].type; 6302 val = pstep->step[i].val; 6303 diff_t = le16_to_cpu(pstep->step[i].difft); 6304 6305 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 6306 continue; 6307 6308 if (cnt % 10 == 0) 6309 seq_printf(m, " %-15s : ", "[steps]"); 6310 6311 seq_printf(m, "-> %s(%02d)(%02d)", 6312 (type == CXSTEP_SLOT ? "SLT" : 6313 "EVT"), (u32)val, diff_t); 6314 if (cnt % 10 == 9) 6315 seq_puts(m, "\n"); 6316 cnt++; 6317 } 6318 6319 state = 2; 6320 break; 6321 case 2: 6322 if (pos_new < pos_old && n_start != 0) { 6323 n_start = 0; 6324 n_stop = pos_new; 6325 state = 1; 6326 } else { 6327 outloop = true; 6328 } 6329 break; 6330 } 6331 } while (!outloop); 6332 } 6333 6334 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m) 6335 { 6336 struct rtw89_btc *btc = &rtwdev->btc; 6337 6338 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 6339 return; 6340 6341 _show_error(rtwdev, m); 6342 _show_fbtc_tdma(rtwdev, m); 6343 _show_fbtc_slots(rtwdev, m); 6344 _show_fbtc_cysta(rtwdev, m); 6345 _show_fbtc_nullsta(rtwdev, m); 6346 _show_fbtc_step(rtwdev, m); 6347 } 6348 6349 static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m) 6350 { 6351 const struct rtw89_chip_info *chip = rtwdev->chip; 6352 struct rtw89_btc *btc = &rtwdev->btc; 6353 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6354 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6355 struct rtw89_btc_fbtc_mreg_val *pmreg = NULL; 6356 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 6357 struct rtw89_btc_cx *cx = &btc->cx; 6358 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6359 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 6360 struct rtw89_mac_ax_gnt gnt[2] = {0}; 6361 u8 i = 0, type = 0, cnt = 0; 6362 u32 val, offset; 6363 6364 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 6365 return; 6366 6367 seq_puts(m, "========== [HW Status] ==========\n"); 6368 6369 seq_printf(m, 6370 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 6371 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 6372 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 6373 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 6374 6375 /* To avoid I/O if WL LPS or power-off */ 6376 if (!wl->status.map.lps && !wl->status.map.rf_off) { 6377 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 6378 if (val & (B_AX_GNT_BT_RFC_S0_SW_VAL | 6379 B_AX_GNT_BT_BB_S0_SW_VAL)) 6380 gnt[0].gnt_bt = true; 6381 if (val & (B_AX_GNT_BT_RFC_S0_SW_CTRL | 6382 B_AX_GNT_BT_BB_S0_SW_CTRL)) 6383 gnt[0].gnt_bt_sw_en = true; 6384 if (val & (B_AX_GNT_WL_RFC_S0_SW_VAL | 6385 B_AX_GNT_WL_BB_S0_SW_VAL)) 6386 gnt[0].gnt_wl = true; 6387 if (val & (B_AX_GNT_WL_RFC_S0_SW_CTRL | 6388 B_AX_GNT_WL_BB_S0_SW_CTRL)) 6389 gnt[0].gnt_wl_sw_en = true; 6390 6391 if (val & (B_AX_GNT_BT_RFC_S1_SW_VAL | 6392 B_AX_GNT_BT_BB_S1_SW_VAL)) 6393 gnt[1].gnt_bt = true; 6394 if (val & (B_AX_GNT_BT_RFC_S1_SW_CTRL | 6395 B_AX_GNT_BT_BB_S1_SW_CTRL)) 6396 gnt[1].gnt_bt_sw_en = true; 6397 if (val & (B_AX_GNT_WL_RFC_S1_SW_VAL | 6398 B_AX_GNT_WL_BB_S1_SW_VAL)) 6399 gnt[1].gnt_wl = true; 6400 if (val & (B_AX_GNT_WL_RFC_S1_SW_CTRL | 6401 B_AX_GNT_WL_BB_S1_SW_CTRL)) 6402 gnt[1].gnt_wl_sw_en = true; 6403 6404 seq_printf(m, 6405 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 6406 "[gnt_status]", 6407 (rtw89_mac_get_ctrl_path(rtwdev) ? "WL" : "BT"), 6408 (gnt[0].gnt_wl_sw_en ? "SW" : "HW"), gnt[0].gnt_wl, 6409 (gnt[0].gnt_bt_sw_en ? "SW" : "HW"), gnt[0].gnt_bt); 6410 6411 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 6412 (gnt[1].gnt_wl_sw_en ? "SW" : "HW"), gnt[1].gnt_wl, 6413 (gnt[1].gnt_bt_sw_en ? "SW" : "HW"), gnt[1].gnt_bt); 6414 } 6415 6416 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 6417 if (!pcinfo->valid) { 6418 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6419 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 6420 __func__); 6421 return; 6422 } 6423 6424 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo; 6425 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6426 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 6427 __func__, pmreg->reg_num); 6428 6429 for (i = 0; i < pmreg->reg_num; i++) { 6430 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 6431 offset = le32_to_cpu(chip->mon_reg[i].offset); 6432 val = le32_to_cpu(pmreg->mreg_val[i]); 6433 6434 if (cnt % 6 == 0) 6435 seq_printf(m, " %-15s : %d_0x%04x=0x%08x", 6436 "[reg]", (u32)type, offset, val); 6437 else 6438 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type, 6439 offset, val); 6440 if (cnt % 6 == 5) 6441 seq_puts(m, "\n"); 6442 cnt++; 6443 } 6444 6445 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 6446 if (!pcinfo->valid) { 6447 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6448 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 6449 __func__); 6450 return; 6451 } 6452 6453 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo; 6454 if (!gdbg->en_map) 6455 return; 6456 6457 seq_printf(m, " %-15s : enable_map:0x%08x", 6458 "[gpio_dbg]", gdbg->en_map); 6459 6460 for (i = 0; i < BTC_DBG_MAX1; i++) { 6461 if (!(gdbg->en_map & BIT(i))) 6462 continue; 6463 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]); 6464 } 6465 seq_puts(m, "\n"); 6466 } 6467 6468 static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m) 6469 { 6470 struct rtw89_btc *btc = &rtwdev->btc; 6471 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 6472 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 6473 struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL; 6474 struct rtw89_btc_cx *cx = &btc->cx; 6475 struct rtw89_btc_dm *dm = &btc->dm; 6476 struct rtw89_btc_wl_info *wl = &cx->wl; 6477 struct rtw89_btc_bt_info *bt = &cx->bt; 6478 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 6479 u8 i; 6480 6481 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 6482 return; 6483 6484 seq_puts(m, "========== [Statistics] ==========\n"); 6485 6486 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 6487 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 6488 prptctrl = &pfwinfo->rpt_ctrl.finfo; 6489 6490 seq_printf(m, 6491 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 6492 "[summary]", pfwinfo->cnt_h2c, 6493 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 6494 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 6495 6496 seq_printf(m, 6497 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 6498 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt, 6499 prptctrl->rpt_enable, dm->error.val); 6500 6501 if (dm->error.map.wl_fw_hang) 6502 seq_puts(m, " (WL FW Hang!!)"); 6503 seq_puts(m, "\n"); 6504 seq_printf(m, 6505 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 6506 "[mailbox]", prptctrl->mb_send_ok_cnt, 6507 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt); 6508 6509 seq_printf(m, 6510 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 6511 prptctrl->mb_a2dp_empty_cnt, 6512 prptctrl->mb_a2dp_flct_cnt, 6513 prptctrl->mb_a2dp_full_cnt); 6514 6515 seq_printf(m, 6516 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 6517 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 6518 cx->cnt_wl[BTC_WCNT_RFK_GO], 6519 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 6520 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 6521 6522 seq_printf(m, 6523 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 6524 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 6525 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 6526 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 6527 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 6528 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 6529 6530 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 6531 bt->rfk_info.map.timeout = 1; 6532 else 6533 bt->rfk_info.map.timeout = 0; 6534 6535 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 6536 } else { 6537 seq_printf(m, 6538 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 6539 "[summary]", pfwinfo->cnt_h2c, 6540 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 6541 pfwinfo->event[BTF_EVNT_RPT], 6542 btc->fwinfo.rpt_en_map); 6543 seq_puts(m, " (WL FW report invalid!!)\n"); 6544 } 6545 6546 for (i = 0; i < BTC_NCNT_NUM; i++) 6547 cnt_sum += dm->cnt_notify[i]; 6548 6549 seq_printf(m, 6550 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 6551 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 6552 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 6553 6554 seq_printf(m, 6555 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 6556 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 6557 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 6558 cnt[BTC_NCNT_WL_STA]); 6559 6560 seq_printf(m, 6561 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 6562 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 6563 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 6564 cnt[BTC_NCNT_SPECIAL_PACKET]); 6565 6566 seq_printf(m, 6567 "timer=%d, control=%d, customerize=%d\n", 6568 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 6569 cnt[BTC_NCNT_CUSTOMERIZE]); 6570 } 6571 6572 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m) 6573 { 6574 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal; 6575 struct rtw89_btc *btc = &rtwdev->btc; 6576 struct rtw89_btc_cx *cx = &btc->cx; 6577 struct rtw89_btc_bt_info *bt = &cx->bt; 6578 6579 seq_puts(m, "=========================================\n"); 6580 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n", 6581 fw_suit->major_ver, fw_suit->minor_ver, 6582 fw_suit->sub_ver, fw_suit->sub_idex); 6583 seq_printf(m, "manual %d\n", btc->ctrl.manual); 6584 6585 seq_puts(m, "=========================================\n"); 6586 6587 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)", 6588 "[bt_info]", 6589 bt->raw_info[2], bt->raw_info[3], 6590 bt->raw_info[4], bt->raw_info[5], 6591 bt->raw_info[6], bt->raw_info[7], 6592 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 6593 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 6594 cx->cnt_bt[BTC_BCNT_INFOSAME]); 6595 6596 seq_puts(m, "\n=========================================\n"); 6597 6598 _show_cx_info(rtwdev, m); 6599 _show_wl_info(rtwdev, m); 6600 _show_bt_info(rtwdev, m); 6601 _show_dm_info(rtwdev, m); 6602 _show_fw_dm_msg(rtwdev, m); 6603 _show_mreg(rtwdev, m); 6604 _show_summary(rtwdev, m); 6605 } 6606