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