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