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