0001
0002
0003
0004
0005 #include "coex.h"
0006 #include "debug.h"
0007 #include "fw.h"
0008 #include "mac.h"
0009 #include "ps.h"
0010 #include "reg.h"
0011
0012 #define FCXDEF_STEP 50
0013
0014 enum btc_fbtc_tdma_template {
0015 CXTD_OFF = 0x0,
0016 CXTD_OFF_B2,
0017 CXTD_OFF_EXT,
0018 CXTD_FIX,
0019 CXTD_PFIX,
0020 CXTD_AUTO,
0021 CXTD_PAUTO,
0022 CXTD_AUTO2,
0023 CXTD_PAUTO2,
0024 CXTD_MAX,
0025 };
0026
0027 enum btc_fbtc_tdma_type {
0028 CXTDMA_OFF = 0x0,
0029 CXTDMA_FIX = 0x1,
0030 CXTDMA_AUTO = 0x2,
0031 CXTDMA_AUTO2 = 0x3,
0032 CXTDMA_MAX
0033 };
0034
0035 enum btc_fbtc_tdma_rx_flow_ctrl {
0036 CXFLC_OFF = 0x0,
0037 CXFLC_NULLP = 0x1,
0038 CXFLC_QOSNULL = 0x2,
0039 CXFLC_CTS = 0x3,
0040 CXFLC_MAX
0041 };
0042
0043 enum btc_fbtc_tdma_wlan_tx_pause {
0044 CXTPS_OFF = 0x0,
0045 CXTPS_ON = 0x1,
0046 CXTPS_MAX
0047 };
0048
0049 enum btc_mlme_state {
0050 MLME_NO_LINK,
0051 MLME_LINKING,
0052 MLME_LINKED,
0053 };
0054
0055 #define FCXONESLOT_VER 1
0056 struct btc_fbtc_1slot {
0057 u8 fver;
0058 u8 sid;
0059 struct rtw89_btc_fbtc_slot slot;
0060 } __packed;
0061
0062 static const struct rtw89_btc_fbtc_tdma t_def[] = {
0063 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
0064 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
0065 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 3, 0, 0},
0066 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
0067 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
0068 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
0069 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
0070 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
0071 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
0072 };
0073
0074 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
0075 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
0076 .cxtype = cpu_to_le16(__cxtype),}
0077
0078 static const struct rtw89_btc_fbtc_slot s_def[] = {
0079 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
0080 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0x5a5a5a5a, SLOT_ISO),
0081 [CXST_W1] = __DEF_FBTC_SLOT(70, 0x5a5a5a5a, SLOT_ISO),
0082 [CXST_W2] = __DEF_FBTC_SLOT(70, 0x5a5a5aaa, SLOT_ISO),
0083 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0x5a5a5a5a, SLOT_ISO),
0084 [CXST_B1] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
0085 [CXST_B2] = __DEF_FBTC_SLOT(7, 0x6a5a5a5a, SLOT_MIX),
0086 [CXST_B3] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX),
0087 [CXST_B4] = __DEF_FBTC_SLOT(50, 0x55555555, SLOT_MIX),
0088 [CXST_LK] = __DEF_FBTC_SLOT(20, 0x5a5a5a5a, SLOT_ISO),
0089 [CXST_BLK] = __DEF_FBTC_SLOT(250, 0x55555555, SLOT_MIX),
0090 [CXST_E2G] = __DEF_FBTC_SLOT(20, 0x6a5a5a5a, SLOT_MIX),
0091 [CXST_E5G] = __DEF_FBTC_SLOT(20, 0xffffffff, SLOT_MIX),
0092 [CXST_EBT] = __DEF_FBTC_SLOT(20, 0x55555555, SLOT_MIX),
0093 [CXST_ENULL] = __DEF_FBTC_SLOT(7, 0xaaaaaaaa, SLOT_ISO),
0094 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0x6a5a6a5a, SLOT_MIX),
0095 [CXST_W1FDD] = __DEF_FBTC_SLOT(35, 0xfafafafa, SLOT_ISO),
0096 [CXST_B1FDD] = __DEF_FBTC_SLOT(100, 0xffffffff, SLOT_MIX),
0097 };
0098
0099 static const u32 cxtbl[] = {
0100 0xffffffff,
0101 0xaaaaaaaa,
0102 0x55555555,
0103 0x66555555,
0104 0x66556655,
0105 0x5a5a5a5a,
0106 0x5a5a5aaa,
0107 0xaa5a5a5a,
0108 0x6a5a5a5a,
0109 0x6a5a5aaa,
0110 0x6a5a6a5a,
0111 0x6a5a6aaa,
0112 0x6afa5afa,
0113 0xaaaa5aaa,
0114 0xaaffffaa,
0115 0xaa5555aa,
0116 0xfafafafa,
0117 0xffffddff,
0118 0xdaffdaff,
0119 0xfafadafa
0120 };
0121
0122 struct rtw89_btc_btf_tlv {
0123 u8 type;
0124 u8 len;
0125 u8 val[1];
0126 } __packed;
0127
0128 enum btc_btf_set_report_en {
0129 RPT_EN_TDMA = BIT(0),
0130 RPT_EN_CYCLE = BIT(1),
0131 RPT_EN_MREG = BIT(2),
0132 RPT_EN_BT_VER_INFO = BIT(3),
0133 RPT_EN_BT_SCAN_INFO = BIT(4),
0134 RPT_EN_BT_AFH_MAP = BIT(5),
0135 RPT_EN_BT_DEVICE_INFO = BIT(6),
0136 RPT_EN_WL_ALL = GENMASK(2, 0),
0137 RPT_EN_BT_ALL = GENMASK(6, 3),
0138 RPT_EN_ALL = GENMASK(6, 0),
0139 };
0140
0141 #define BTF_SET_REPORT_VER 1
0142 struct rtw89_btc_btf_set_report {
0143 u8 fver;
0144 __le32 enable;
0145 __le32 para;
0146 } __packed;
0147
0148 #define BTF_SET_SLOT_TABLE_VER 1
0149 struct rtw89_btc_btf_set_slot_table {
0150 u8 fver;
0151 u8 tbl_num;
0152 u8 buf[];
0153 } __packed;
0154
0155 #define BTF_SET_MON_REG_VER 1
0156 struct rtw89_btc_btf_set_mon_reg {
0157 u8 fver;
0158 u8 reg_num;
0159 u8 buf[];
0160 } __packed;
0161
0162 enum btc_btf_set_cx_policy {
0163 CXPOLICY_TDMA = 0x0,
0164 CXPOLICY_SLOT = 0x1,
0165 CXPOLICY_TYPE = 0x2,
0166 CXPOLICY_MAX,
0167 };
0168
0169 enum btc_b2w_scoreboard {
0170 BTC_BSCB_ACT = BIT(0),
0171 BTC_BSCB_ON = BIT(1),
0172 BTC_BSCB_WHQL = BIT(2),
0173 BTC_BSCB_BT_S1 = BIT(3),
0174 BTC_BSCB_A2DP_ACT = BIT(4),
0175 BTC_BSCB_RFK_RUN = BIT(5),
0176 BTC_BSCB_RFK_REQ = BIT(6),
0177 BTC_BSCB_LPS = BIT(7),
0178 BTC_BSCB_WLRFK = BIT(11),
0179 BTC_BSCB_BT_HILNA = BIT(13),
0180 BTC_BSCB_BT_CONNECT = BIT(16),
0181 BTC_BSCB_PATCH_CODE = BIT(30),
0182 BTC_BSCB_ALL = GENMASK(30, 0),
0183 };
0184
0185 enum btc_phymap {
0186 BTC_PHY_0 = BIT(0),
0187 BTC_PHY_1 = BIT(1),
0188 BTC_PHY_ALL = BIT(0) | BIT(1),
0189 };
0190
0191 enum btc_cx_state_map {
0192 BTC_WIDLE = 0,
0193 BTC_WBUSY_BNOSCAN,
0194 BTC_WBUSY_BSCAN,
0195 BTC_WSCAN_BNOSCAN,
0196 BTC_WSCAN_BSCAN,
0197 BTC_WLINKING
0198 };
0199
0200 enum btc_ant_phase {
0201 BTC_ANT_WPOWERON = 0,
0202 BTC_ANT_WINIT,
0203 BTC_ANT_WONLY,
0204 BTC_ANT_WOFF,
0205 BTC_ANT_W2G,
0206 BTC_ANT_W5G,
0207 BTC_ANT_W25G,
0208 BTC_ANT_FREERUN,
0209 BTC_ANT_WRFK,
0210 BTC_ANT_BRFK,
0211 BTC_ANT_MAX
0212 };
0213
0214 enum btc_plt {
0215 BTC_PLT_NONE = 0,
0216 BTC_PLT_LTE_RX = BIT(0),
0217 BTC_PLT_GNT_BT_TX = BIT(1),
0218 BTC_PLT_GNT_BT_RX = BIT(2),
0219 BTC_PLT_GNT_WL = BIT(3),
0220 BTC_PLT_BT = BIT(1) | BIT(2),
0221 BTC_PLT_ALL = 0xf
0222 };
0223
0224 enum btc_cx_poicy_main_type {
0225 BTC_CXP_OFF = 0,
0226 BTC_CXP_OFFB,
0227 BTC_CXP_OFFE,
0228 BTC_CXP_FIX,
0229 BTC_CXP_PFIX,
0230 BTC_CXP_AUTO,
0231 BTC_CXP_PAUTO,
0232 BTC_CXP_AUTO2,
0233 BTC_CXP_PAUTO2,
0234 BTC_CXP_MANUAL,
0235 BTC_CXP_USERDEF0,
0236 BTC_CXP_MAIN_MAX
0237 };
0238
0239 enum btc_cx_poicy_type {
0240
0241 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
0242
0243
0244 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
0245
0246
0247 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
0248
0249
0250 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
0251
0252
0253 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
0254
0255
0256 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
0257
0258
0259 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 6,
0260
0261
0262 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 7,
0263
0264
0265 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
0266
0267
0268 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
0269
0270
0271 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
0272
0273
0274 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
0275
0276
0277 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
0278
0279
0280 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
0281
0282
0283 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
0284
0285
0286 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
0287
0288
0289 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
0290
0291
0292 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
0293
0294
0295 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
0296
0297
0298 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
0299
0300
0301 BTC_CXP_FIX_TD4020 = (BTC_CXP_FIX << 8) | 9,
0302
0303
0304 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
0305
0306
0307 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
0308
0309
0310 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
0311
0312
0313 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
0314
0315
0316 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
0317
0318
0319 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
0320
0321
0322 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
0323
0324
0325 BTC_CXP_AUTO_TD50200 = (BTC_CXP_AUTO << 8) | 0,
0326
0327
0328 BTC_CXP_AUTO_TD60200 = (BTC_CXP_AUTO << 8) | 1,
0329
0330
0331 BTC_CXP_AUTO_TD20200 = (BTC_CXP_AUTO << 8) | 2,
0332
0333
0334 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
0335
0336
0337 BTC_CXP_PAUTO_TD50200 = (BTC_CXP_PAUTO << 8) | 0,
0338
0339
0340 BTC_CXP_PAUTO_TD60200 = (BTC_CXP_PAUTO << 8) | 1,
0341
0342
0343 BTC_CXP_PAUTO_TD20200 = (BTC_CXP_PAUTO << 8) | 2,
0344
0345
0346 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
0347
0348
0349 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
0350
0351
0352 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
0353
0354
0355 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
0356
0357
0358 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
0359
0360
0361 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
0362
0363
0364 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
0365
0366
0367 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
0368
0369
0370 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
0371
0372
0373 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
0374
0375
0376 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
0377
0378
0379 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
0380
0381
0382 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
0383
0384 BTC_CXP_MAX = 0xffff
0385 };
0386
0387 enum btc_wl_rfk_result {
0388 BTC_WRFK_REJECT = 0,
0389 BTC_WRFK_ALLOW = 1,
0390 };
0391
0392 enum btc_coex_info_map_en {
0393 BTC_COEX_INFO_CX = BIT(0),
0394 BTC_COEX_INFO_WL = BIT(1),
0395 BTC_COEX_INFO_BT = BIT(2),
0396 BTC_COEX_INFO_DM = BIT(3),
0397 BTC_COEX_INFO_MREG = BIT(4),
0398 BTC_COEX_INFO_SUMMARY = BIT(5),
0399 BTC_COEX_INFO_ALL = GENMASK(7, 0),
0400 };
0401
0402 #define BTC_CXP_MASK GENMASK(15, 8)
0403
0404 enum btc_w2b_scoreboard {
0405 BTC_WSCB_ACTIVE = BIT(0),
0406 BTC_WSCB_ON = BIT(1),
0407 BTC_WSCB_SCAN = BIT(2),
0408 BTC_WSCB_UNDERTEST = BIT(3),
0409 BTC_WSCB_RXGAIN = BIT(4),
0410 BTC_WSCB_WLBUSY = BIT(7),
0411 BTC_WSCB_EXTFEM = BIT(8),
0412 BTC_WSCB_TDMA = BIT(9),
0413 BTC_WSCB_FIX2M = BIT(10),
0414 BTC_WSCB_WLRFK = BIT(11),
0415 BTC_WSCB_BTRFK_GNT = BIT(12),
0416 BTC_WSCB_BT_HILNA = BIT(13),
0417 BTC_WSCB_BTLOG = BIT(14),
0418 BTC_WSCB_ALL = GENMASK(23, 0),
0419 };
0420
0421 enum btc_wl_link_mode {
0422 BTC_WLINK_NOLINK = 0x0,
0423 BTC_WLINK_2G_STA,
0424 BTC_WLINK_2G_AP,
0425 BTC_WLINK_2G_GO,
0426 BTC_WLINK_2G_GC,
0427 BTC_WLINK_2G_SCC,
0428 BTC_WLINK_2G_MCC,
0429 BTC_WLINK_25G_MCC,
0430 BTC_WLINK_25G_DBCC,
0431 BTC_WLINK_5G,
0432 BTC_WLINK_2G_NAN,
0433 BTC_WLINK_OTHER,
0434 BTC_WLINK_MAX
0435 };
0436
0437 enum btc_bt_hid_type {
0438 BTC_HID_218 = BIT(0),
0439 BTC_HID_418 = BIT(1),
0440 BTC_HID_BLE = BIT(2),
0441 BTC_HID_RCU = BIT(3),
0442 BTC_HID_RCU_VOICE = BIT(4),
0443 BTC_HID_OTHER_LEGACY = BIT(5)
0444 };
0445
0446 enum btc_reset_module {
0447 BTC_RESET_CX = BIT(0),
0448 BTC_RESET_DM = BIT(1),
0449 BTC_RESET_CTRL = BIT(2),
0450 BTC_RESET_CXDM = BIT(0) | BIT(1),
0451 BTC_RESET_BTINFO = BIT(3),
0452 BTC_RESET_MDINFO = BIT(4),
0453 BTC_RESET_ALL = GENMASK(7, 0),
0454 };
0455
0456 enum btc_gnt_state {
0457 BTC_GNT_HW = 0,
0458 BTC_GNT_SW_LO,
0459 BTC_GNT_SW_HI,
0460 BTC_GNT_MAX
0461 };
0462
0463 enum btc_wl_max_tx_time {
0464 BTC_MAX_TX_TIME_L1 = 500,
0465 BTC_MAX_TX_TIME_L2 = 1000,
0466 BTC_MAX_TX_TIME_L3 = 2000,
0467 BTC_MAX_TX_TIME_DEF = 5280
0468 };
0469
0470 enum btc_wl_max_tx_retry {
0471 BTC_MAX_TX_RETRY_L1 = 7,
0472 BTC_MAX_TX_RETRY_L2 = 15,
0473 BTC_MAX_TX_RETRY_DEF = 31,
0474 };
0475
0476 enum btc_reason_and_action {
0477 BTC_RSN_NONE,
0478 BTC_RSN_NTFY_INIT,
0479 BTC_RSN_NTFY_SWBAND,
0480 BTC_RSN_NTFY_WL_STA,
0481 BTC_RSN_NTFY_RADIO_STATE,
0482 BTC_RSN_UPDATE_BT_SCBD,
0483 BTC_RSN_NTFY_WL_RFK,
0484 BTC_RSN_UPDATE_BT_INFO,
0485 BTC_RSN_NTFY_SCAN_START,
0486 BTC_RSN_NTFY_SCAN_FINISH,
0487 BTC_RSN_NTFY_SPECIFIC_PACKET,
0488 BTC_RSN_NTFY_POWEROFF,
0489 BTC_RSN_NTFY_ROLE_INFO,
0490 BTC_RSN_CMD_SET_COEX,
0491 BTC_RSN_ACT1_WORK,
0492 BTC_RSN_BT_DEVINFO_WORK,
0493 BTC_RSN_RFK_CHK_WORK,
0494 BTC_RSN_NUM,
0495 BTC_ACT_NONE = 100,
0496 BTC_ACT_WL_ONLY,
0497 BTC_ACT_WL_5G,
0498 BTC_ACT_WL_OTHER,
0499 BTC_ACT_WL_IDLE,
0500 BTC_ACT_WL_NC,
0501 BTC_ACT_WL_RFK,
0502 BTC_ACT_WL_INIT,
0503 BTC_ACT_WL_OFF,
0504 BTC_ACT_FREERUN,
0505 BTC_ACT_BT_WHQL,
0506 BTC_ACT_BT_RFK,
0507 BTC_ACT_BT_OFF,
0508 BTC_ACT_BT_IDLE,
0509 BTC_ACT_BT_HFP,
0510 BTC_ACT_BT_HID,
0511 BTC_ACT_BT_A2DP,
0512 BTC_ACT_BT_A2DPSINK,
0513 BTC_ACT_BT_PAN,
0514 BTC_ACT_BT_A2DP_HID,
0515 BTC_ACT_BT_A2DP_PAN,
0516 BTC_ACT_BT_PAN_HID,
0517 BTC_ACT_BT_A2DP_PAN_HID,
0518 BTC_ACT_WL_25G_MCC,
0519 BTC_ACT_WL_2G_MCC,
0520 BTC_ACT_WL_2G_SCC,
0521 BTC_ACT_WL_2G_AP,
0522 BTC_ACT_WL_2G_GO,
0523 BTC_ACT_WL_2G_GC,
0524 BTC_ACT_WL_2G_NAN,
0525 BTC_ACT_LAST,
0526 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
0527 BTC_ACT_EXT_BIT = BIT(14),
0528 BTC_POLICY_EXT_BIT = BIT(15),
0529 };
0530
0531 #define BTC_FREERUN_ANTISO_MIN 30
0532 #define BTC_TDMA_BTHID_MAX 2
0533 #define BTC_BLINK_NOCONNECT 0
0534
0535 static void _run_coex(struct rtw89_dev *rtwdev,
0536 enum btc_reason_and_action reason);
0537 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
0538 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
0539
0540 static void _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
0541 void *param, u16 len)
0542 {
0543 struct rtw89_btc *btc = &rtwdev->btc;
0544 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
0545 struct rtw89_btc_cx *cx = &btc->cx;
0546 struct rtw89_btc_wl_info *wl = &cx->wl;
0547 int ret;
0548
0549 if (!wl->status.map.init_ok) {
0550 rtw89_debug(rtwdev, RTW89_DBG_BTC,
0551 "[BTC], %s(): return by btc not init!!\n", __func__);
0552 pfwinfo->cnt_h2c_fail++;
0553 return;
0554 } else if ((wl->status.map.rf_off_pre == 1 && wl->status.map.rf_off == 1) ||
0555 (wl->status.map.lps_pre == 1 && wl->status.map.lps == 1)) {
0556 rtw89_debug(rtwdev, RTW89_DBG_BTC,
0557 "[BTC], %s(): return by wl off!!\n", __func__);
0558 pfwinfo->cnt_h2c_fail++;
0559 return;
0560 }
0561
0562 pfwinfo->cnt_h2c++;
0563
0564 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
0565 false, true);
0566 if (ret != 0)
0567 pfwinfo->cnt_h2c_fail++;
0568 }
0569
0570 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
0571 {
0572 struct rtw89_btc *btc = &rtwdev->btc;
0573 struct rtw89_btc_cx *cx = &btc->cx;
0574 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
0575 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
0576 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
0577 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
0578 u8 i;
0579
0580 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
0581
0582 if (type & BTC_RESET_CX)
0583 memset(cx, 0, sizeof(*cx));
0584 else if (type & BTC_RESET_BTINFO)
0585 memset(bt, 0, sizeof(*bt));
0586
0587 if (type & BTC_RESET_CTRL) {
0588 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
0589 btc->ctrl.trace_step = FCXDEF_STEP;
0590 }
0591
0592
0593 if (type & BTC_RESET_DM) {
0594 memset(&btc->dm, 0, sizeof(btc->dm));
0595 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
0596
0597 for (i = 0; i < RTW89_PORT_NUM; i++)
0598 memset(wl_linfo[i].rssi_state, 0,
0599 sizeof(wl_linfo[i].rssi_state));
0600
0601
0602 btc->dm.tdma_now = t_def[CXTD_OFF];
0603 btc->dm.tdma = t_def[CXTD_OFF];
0604 memcpy(&btc->dm.slot_now, s_def, sizeof(btc->dm.slot_now));
0605 memcpy(&btc->dm.slot, s_def, sizeof(btc->dm.slot));
0606
0607 btc->policy_len = 0;
0608 btc->bt_req_len = 0;
0609
0610 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
0611 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
0612 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
0613 }
0614
0615 if (type & BTC_RESET_MDINFO)
0616 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
0617 }
0618
0619 #define BTC_FWINFO_BUF 1024
0620
0621 #define BTC_RPT_HDR_SIZE 3
0622 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
0623 #define BTC_CHK_HANG_MAX 3
0624
0625 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
0626 {
0627 struct rtw89_btc *btc = &rtwdev->btc;
0628 struct rtw89_btc_cx *cx = &btc->cx;
0629 struct rtw89_btc_dm *dm = &btc->dm;
0630 struct rtw89_btc_bt_info *bt = &cx->bt;
0631
0632 rtw89_debug(rtwdev, RTW89_DBG_BTC,
0633 "[BTC], %s(): type:%d cnt:%d\n",
0634 __func__, type, cnt);
0635
0636 switch (type) {
0637 case BTC_DCNT_RPT_FREEZE:
0638 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
0639 dm->cnt_dm[BTC_DCNT_RPT_FREEZE]++;
0640 else
0641 dm->cnt_dm[BTC_DCNT_RPT_FREEZE] = 0;
0642
0643 if (dm->cnt_dm[BTC_DCNT_RPT_FREEZE] >= BTC_CHK_HANG_MAX)
0644 dm->error.map.wl_fw_hang = true;
0645 else
0646 dm->error.map.wl_fw_hang = false;
0647
0648 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
0649 break;
0650 case BTC_DCNT_CYCLE_FREEZE:
0651 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
0652 (dm->tdma_now.type != CXTDMA_OFF ||
0653 dm->tdma_now.ext_ctrl == CXECTL_EXT))
0654 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE]++;
0655 else
0656 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] = 0;
0657
0658 if (dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] >= BTC_CHK_HANG_MAX)
0659 dm->error.map.cycle_hang = true;
0660 else
0661 dm->error.map.cycle_hang = false;
0662
0663 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
0664 break;
0665 case BTC_DCNT_W1_FREEZE:
0666 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
0667 dm->tdma_now.type != CXTDMA_OFF)
0668 dm->cnt_dm[BTC_DCNT_W1_FREEZE]++;
0669 else
0670 dm->cnt_dm[BTC_DCNT_W1_FREEZE] = 0;
0671
0672 if (dm->cnt_dm[BTC_DCNT_W1_FREEZE] >= BTC_CHK_HANG_MAX)
0673 dm->error.map.w1_hang = true;
0674 else
0675 dm->error.map.w1_hang = false;
0676
0677 dm->cnt_dm[BTC_DCNT_W1] = cnt;
0678 break;
0679 case BTC_DCNT_B1_FREEZE:
0680 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
0681 dm->tdma_now.type != CXTDMA_OFF)
0682 dm->cnt_dm[BTC_DCNT_B1_FREEZE]++;
0683 else
0684 dm->cnt_dm[BTC_DCNT_B1_FREEZE] = 0;
0685
0686 if (dm->cnt_dm[BTC_DCNT_B1_FREEZE] >= BTC_CHK_HANG_MAX)
0687 dm->error.map.b1_hang = true;
0688 else
0689 dm->error.map.b1_hang = false;
0690
0691 dm->cnt_dm[BTC_DCNT_B1] = cnt;
0692 break;
0693 case BTC_DCNT_TDMA_NONSYNC:
0694 if (cnt != 0)
0695 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
0696 else
0697 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
0698
0699 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
0700 dm->error.map.tdma_no_sync = true;
0701 else
0702 dm->error.map.tdma_no_sync = false;
0703 break;
0704 case BTC_DCNT_SLOT_NONSYNC:
0705 if (cnt != 0)
0706 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
0707 else
0708 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
0709
0710 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
0711 dm->error.map.tdma_no_sync = true;
0712 else
0713 dm->error.map.tdma_no_sync = false;
0714 break;
0715 case BTC_DCNT_BTCNT_FREEZE:
0716 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
0717 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
0718 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
0719 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
0720
0721 if (cnt == 0)
0722 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE]++;
0723 else
0724 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
0725
0726 if ((dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX &&
0727 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] &&
0728 !bt->enable.now))
0729 _update_bt_scbd(rtwdev, false);
0730 break;
0731 case BTC_DCNT_WL_SLOT_DRIFT:
0732 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
0733 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
0734 else
0735 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
0736
0737 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
0738 dm->error.map.wl_slot_drift = true;
0739 else
0740 dm->error.map.wl_slot_drift = false;
0741 break;
0742 }
0743 }
0744
0745 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
0746 {
0747 struct rtw89_btc *btc = &rtwdev->btc;
0748 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
0749 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
0750 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
0751 struct rtw89_btc_fbtc_btver *pver = NULL;
0752 struct rtw89_btc_fbtc_btscan *pscan = NULL;
0753 struct rtw89_btc_fbtc_btafh *pafh = NULL;
0754 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
0755
0756 pver = (struct rtw89_btc_fbtc_btver *)pfinfo;
0757 pscan = (struct rtw89_btc_fbtc_btscan *)pfinfo;
0758 pafh = (struct rtw89_btc_fbtc_btafh *)pfinfo;
0759 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
0760
0761 rtw89_debug(rtwdev, RTW89_DBG_BTC,
0762 "[BTC], %s(): rpt_type:%d\n",
0763 __func__, rpt_type);
0764
0765 switch (rpt_type) {
0766 case BTC_RPT_TYPE_BT_VER:
0767 bt->ver_info.fw = le32_to_cpu(pver->fw_ver);
0768 bt->ver_info.fw_coex = le32_get_bits(pver->coex_ver, GENMASK(7, 0));
0769 bt->feature = le32_to_cpu(pver->feature);
0770 break;
0771 case BTC_RPT_TYPE_BT_SCAN:
0772 memcpy(bt->scan_info, pscan->scan, BTC_SCAN_MAX1);
0773 break;
0774 case BTC_RPT_TYPE_BT_AFH:
0775 memcpy(&bt_linfo->afh_map[0], pafh->afh_l, 4);
0776 memcpy(&bt_linfo->afh_map[4], pafh->afh_m, 4);
0777 memcpy(&bt_linfo->afh_map[8], pafh->afh_h, 2);
0778 break;
0779 case BTC_RPT_TYPE_BT_DEVICE:
0780 a2dp->device_name = le32_to_cpu(pdev->dev_name);
0781 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
0782 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
0783 break;
0784 default:
0785 break;
0786 }
0787 }
0788
0789 struct rtw89_btc_fbtc_cysta_cpu {
0790 u8 fver;
0791 u8 rsvd;
0792 u16 cycles;
0793 u16 cycles_a2dp[CXT_FLCTRL_MAX];
0794 u16 a2dpept;
0795 u16 a2dpeptto;
0796 u16 tavg_cycle[CXT_MAX];
0797 u16 tmax_cycle[CXT_MAX];
0798 u16 tmaxdiff_cycle[CXT_MAX];
0799 u16 tavg_a2dp[CXT_FLCTRL_MAX];
0800 u16 tmax_a2dp[CXT_FLCTRL_MAX];
0801 u16 tavg_a2dpept;
0802 u16 tmax_a2dpept;
0803 u16 tavg_lk;
0804 u16 tmax_lk;
0805 u32 slot_cnt[CXST_MAX];
0806 u32 bcn_cnt[CXBCN_MAX];
0807 u32 leakrx_cnt;
0808 u32 collision_cnt;
0809 u32 skip_cnt;
0810 u32 exception;
0811 u32 except_cnt;
0812 u16 tslot_cycle[BTC_CYCLE_SLOT_MAX];
0813 };
0814
0815 static void rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta *src,
0816 struct rtw89_btc_fbtc_cysta_cpu *dst)
0817 {
0818 static_assert(sizeof(*src) == sizeof(*dst));
0819
0820 #define __CPY_U8(_x) ({dst->_x = src->_x; })
0821 #define __CPY_LE16(_x) ({dst->_x = le16_to_cpu(src->_x); })
0822 #define __CPY_LE16S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
0823 dst->_x[_i] = le16_to_cpu(src->_x[_i]); })
0824 #define __CPY_LE32(_x) ({dst->_x = le32_to_cpu(src->_x); })
0825 #define __CPY_LE32S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
0826 dst->_x[_i] = le32_to_cpu(src->_x[_i]); })
0827
0828 __CPY_U8(fver);
0829 __CPY_U8(rsvd);
0830 __CPY_LE16(cycles);
0831 __CPY_LE16S(cycles_a2dp);
0832 __CPY_LE16(a2dpept);
0833 __CPY_LE16(a2dpeptto);
0834 __CPY_LE16S(tavg_cycle);
0835 __CPY_LE16S(tmax_cycle);
0836 __CPY_LE16S(tmaxdiff_cycle);
0837 __CPY_LE16S(tavg_a2dp);
0838 __CPY_LE16S(tmax_a2dp);
0839 __CPY_LE16(tavg_a2dpept);
0840 __CPY_LE16(tmax_a2dpept);
0841 __CPY_LE16(tavg_lk);
0842 __CPY_LE16(tmax_lk);
0843 __CPY_LE32S(slot_cnt);
0844 __CPY_LE32S(bcn_cnt);
0845 __CPY_LE32(leakrx_cnt);
0846 __CPY_LE32(collision_cnt);
0847 __CPY_LE32(skip_cnt);
0848 __CPY_LE32(exception);
0849 __CPY_LE32(except_cnt);
0850 __CPY_LE16S(tslot_cycle);
0851
0852 #undef __CPY_U8
0853 #undef __CPY_LE16
0854 #undef __CPY_LE16S
0855 #undef __CPY_LE32
0856 #undef __CPY_LE32S
0857 }
0858
0859 #define BTC_LEAK_AP_TH 10
0860 #define BTC_CYSTA_CHK_PERIOD 100
0861
0862 struct rtw89_btc_prpt {
0863 u8 type;
0864 __le16 len;
0865 u8 content[];
0866 } __packed;
0867
0868 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
0869 struct rtw89_btc_btf_fwinfo *pfwinfo,
0870 u8 *prptbuf, u32 index)
0871 {
0872 struct rtw89_btc *btc = &rtwdev->btc;
0873 struct rtw89_btc_dm *dm = &btc->dm;
0874 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
0875 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
0876 struct rtw89_btc_fbtc_rpt_ctrl *prpt = NULL;
0877 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
0878 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
0879 struct rtw89_btc_prpt *btc_prpt = NULL;
0880 struct rtw89_btc_fbtc_slot *rtp_slot = NULL;
0881 u8 rpt_type = 0, *rpt_content = NULL, *pfinfo = NULL;
0882 u16 wl_slot_set = 0;
0883 u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t;
0884 u8 i;
0885
0886 rtw89_debug(rtwdev, RTW89_DBG_BTC,
0887 "[BTC], %s(): index:%d\n",
0888 __func__, index);
0889
0890 if (!prptbuf) {
0891 pfwinfo->err[BTFRE_INVALID_INPUT]++;
0892 return 0;
0893 }
0894
0895 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
0896 rpt_type = btc_prpt->type;
0897 rpt_len = le16_to_cpu(btc_prpt->len);
0898 rpt_content = btc_prpt->content;
0899
0900 rtw89_debug(rtwdev, RTW89_DBG_BTC,
0901 "[BTC], %s(): rpt_type:%d\n",
0902 __func__, rpt_type);
0903
0904 switch (rpt_type) {
0905 case BTC_RPT_TYPE_CTRL:
0906 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
0907 pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
0908 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
0909 pcinfo->req_fver = BTCRPT_VER;
0910 pcinfo->rx_len = rpt_len;
0911 pcinfo->rx_cnt++;
0912 break;
0913 case BTC_RPT_TYPE_TDMA:
0914 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
0915 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_tdma.finfo);
0916 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
0917 pcinfo->req_fver = FCXTDMA_VER;
0918 pcinfo->rx_len = rpt_len;
0919 pcinfo->rx_cnt++;
0920 break;
0921 case BTC_RPT_TYPE_SLOT:
0922 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
0923 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_slots.finfo);
0924 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
0925 pcinfo->req_fver = FCXSLOTS_VER;
0926 pcinfo->rx_len = rpt_len;
0927 pcinfo->rx_cnt++;
0928 break;
0929 case BTC_RPT_TYPE_CYSTA:
0930 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
0931 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
0932 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
0933 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
0934 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
0935 pcinfo->req_fver = FCXCYSTA_VER;
0936 pcinfo->rx_len = rpt_len;
0937 pcinfo->rx_cnt++;
0938 break;
0939 case BTC_RPT_TYPE_STEP:
0940 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
0941 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_step.finfo);
0942 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
0943 trace_step + 8;
0944 pcinfo->req_fver = FCXSTEP_VER;
0945 pcinfo->rx_len = rpt_len;
0946 pcinfo->rx_cnt++;
0947 break;
0948 case BTC_RPT_TYPE_NULLSTA:
0949 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
0950 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_nullsta.finfo);
0951 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
0952 pcinfo->req_fver = FCXNULLSTA_VER;
0953 pcinfo->rx_len = rpt_len;
0954 pcinfo->rx_cnt++;
0955 break;
0956 case BTC_RPT_TYPE_MREG:
0957 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
0958 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_mregval.finfo);
0959 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo);
0960 pcinfo->req_fver = FCXMREG_VER;
0961 pcinfo->rx_len = rpt_len;
0962 pcinfo->rx_cnt++;
0963 break;
0964 case BTC_RPT_TYPE_GPIO_DBG:
0965 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
0966 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_gpio_dbg.finfo);
0967 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo);
0968 pcinfo->req_fver = FCXGPIODBG_VER;
0969 pcinfo->rx_len = rpt_len;
0970 pcinfo->rx_cnt++;
0971 break;
0972 case BTC_RPT_TYPE_BT_VER:
0973 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
0974 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btver.finfo);
0975 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo);
0976 pcinfo->req_fver = FCX_BTVER_VER;
0977 pcinfo->rx_len = rpt_len;
0978 pcinfo->rx_cnt++;
0979 break;
0980 case BTC_RPT_TYPE_BT_SCAN:
0981 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
0982 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btscan.finfo);
0983 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo);
0984 pcinfo->req_fver = FCX_BTSCAN_VER;
0985 pcinfo->rx_len = rpt_len;
0986 pcinfo->rx_cnt++;
0987 break;
0988 case BTC_RPT_TYPE_BT_AFH:
0989 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
0990 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btafh.finfo);
0991 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo);
0992 pcinfo->req_fver = FCX_BTAFH_VER;
0993 pcinfo->rx_len = rpt_len;
0994 pcinfo->rx_cnt++;
0995 break;
0996 case BTC_RPT_TYPE_BT_DEVICE:
0997 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
0998 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btdev.finfo);
0999 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
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
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
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
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
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_chip_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 {
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) {
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) {
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 {
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
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
1701 for (i = 0; i < RTW89_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
1714 for (i = 0; i < RTW89_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;
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
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
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) {
1802 btc->dm.trx_para_level = 5;
1803 return true;
1804 } else if (wl->rssi_level > 1) {
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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_chip_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_chip_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_chip_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_chip_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_chip_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_chip_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
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_chip_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_chip_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_chip_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_chip_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_chip_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) {
2453 switch (btc->cx.state_map) {
2454 case BTC_WBUSY_BNOSCAN:
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:
2463 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
2464 BTC_ACT_BT_IDLE);
2465 break;
2466 case BTC_WSCAN_BNOSCAN:
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:
2475 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
2476 BTC_ACT_BT_IDLE);
2477 break;
2478 case BTC_WLINKING:
2479 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
2480 BTC_ACT_BT_IDLE);
2481 break;
2482 case BTC_WIDLE:
2483 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
2484 break;
2485 }
2486 } else {
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)
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
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:
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:
2544 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
2545 break;
2546 case BTC_WSCAN_BSCAN:
2547 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
2548 break;
2549 case BTC_WSCAN_BNOSCAN:
2550 case BTC_WLINKING:
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:
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:
2575 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
2576 break;
2577 case BTC_WBUSY_BSCAN:
2578 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
2579 break;
2580 case BTC_WSCAN_BNOSCAN:
2581 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
2582 break;
2583 case BTC_WSCAN_BSCAN:
2584 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
2585 break;
2586 case BTC_WLINKING:
2587 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
2588 break;
2589 case BTC_WIDLE:
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:
2603 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
2604 break;
2605 case BTC_WBUSY_BSCAN:
2606 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
2607 break;
2608 case BTC_WSCAN_BNOSCAN:
2609 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
2610 break;
2611 case BTC_WSCAN_BSCAN:
2612 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
2613 break;
2614 case BTC_WLINKING:
2615 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, BTC_ACT_BT_PAN);
2616 break;
2617 case BTC_WIDLE:
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:
2634 case BTC_WIDLE:
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:
2646 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
2647 break;
2648
2649 case BTC_WSCAN_BSCAN:
2650 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
2651 break;
2652 case BTC_WSCAN_BNOSCAN:
2653 case BTC_WLINKING:
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:
2675 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
2676 break;
2677 case BTC_WBUSY_BSCAN:
2678 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
2679 break;
2680 case BTC_WSCAN_BNOSCAN:
2681 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
2682 break;
2683 case BTC_WSCAN_BSCAN:
2684 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
2685 break;
2686 case BTC_WLINKING:
2687 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
2688 break;
2689 case BTC_WIDLE:
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:
2703 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
2704 break;
2705 case BTC_WBUSY_BSCAN:
2706 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
2707 break;
2708 case BTC_WSCAN_BNOSCAN:
2709 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
2710 break;
2711 case BTC_WSCAN_BSCAN:
2712 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
2713 break;
2714 case BTC_WLINKING:
2715 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
2716 break;
2717 case BTC_WIDLE:
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:
2731 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
2732 BTC_ACT_BT_A2DP_PAN_HID);
2733 break;
2734 case BTC_WBUSY_BSCAN:
2735 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
2736 BTC_ACT_BT_A2DP_PAN_HID);
2737 break;
2738 case BTC_WSCAN_BSCAN:
2739 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
2740 BTC_ACT_BT_A2DP_PAN_HID);
2741 break;
2742 case BTC_WSCAN_BNOSCAN:
2743 case BTC_WLINKING:
2744 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
2745 BTC_ACT_BT_A2DP_PAN_HID);
2746 break;
2747 case BTC_WIDLE:
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
2805 if (wl_rinfo->link_mode == BTC_WLINK_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
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
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
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 (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
3072 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
3073 if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
3074 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3075 BTC_RSN_NTFY_SCAN_START);
3076 else
3077 _set_policy(rtwdev, BTC_CXP_OFF_EQ0,
3078 BTC_RSN_NTFY_SCAN_START);
3079
3080 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
3081 } else if (rtwdev->dbcc_en) {
3082 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
3083 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
3084 _action_wl_5g(rtwdev);
3085 else
3086 _action_by_bt(rtwdev);
3087 } else {
3088 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
3089 _action_wl_5g(rtwdev);
3090 else
3091 _action_by_bt(rtwdev);
3092 }
3093 }
3094
3095 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
3096 {
3097 struct rtw89_btc *btc = &rtwdev->btc;
3098
3099 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
3100
3101 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3102 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3103 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3104 BTC_ACT_WL_25G_MCC);
3105 else
3106 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3107 BTC_ACT_WL_25G_MCC);
3108 } else {
3109 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC);
3110 }
3111 }
3112
3113 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
3114 { struct rtw89_btc *btc = &rtwdev->btc;
3115
3116 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3117
3118 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3119 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3120 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3121 BTC_ACT_WL_2G_MCC);
3122 else
3123 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3124 BTC_ACT_WL_2G_MCC);
3125 } else {
3126 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
3127 }
3128 }
3129
3130 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
3131 {
3132 struct rtw89_btc *btc = &rtwdev->btc;
3133
3134 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3135
3136 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3137 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3138 _set_policy(rtwdev,
3139 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
3140 else
3141 _set_policy(rtwdev,
3142 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
3143 } else {
3144 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
3145 }
3146 }
3147
3148 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
3149 {
3150 struct rtw89_btc *btc = &rtwdev->btc;
3151
3152 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3153
3154 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3155 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3156 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3157 BTC_ACT_WL_2G_AP);
3158 else
3159 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
3160 } else {
3161 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
3162 }
3163 }
3164
3165 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
3166 {
3167 struct rtw89_btc *btc = &rtwdev->btc;
3168
3169 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3170
3171 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3172 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3173 _set_policy(rtwdev,
3174 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
3175 else
3176 _set_policy(rtwdev,
3177 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
3178 } else {
3179 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
3180 }
3181 }
3182
3183 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
3184 {
3185 struct rtw89_btc *btc = &rtwdev->btc;
3186
3187 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3188
3189 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3190 _action_by_bt(rtwdev);
3191 } else {
3192 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
3193 }
3194 }
3195
3196 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
3197 {
3198 struct rtw89_btc *btc = &rtwdev->btc;
3199
3200 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3201
3202 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3203 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3204 _set_policy(rtwdev,
3205 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
3206 else
3207 _set_policy(rtwdev,
3208 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
3209 } else {
3210 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
3211 }
3212 }
3213
3214 static u32 _read_scbd(struct rtw89_dev *rtwdev)
3215 {
3216 const struct rtw89_chip_info *chip = rtwdev->chip;
3217 struct rtw89_btc *btc = &rtwdev->btc;
3218 u32 scbd_val = 0;
3219
3220 if (!chip->scbd)
3221 return 0;
3222
3223 scbd_val = rtw89_mac_get_sb(rtwdev);
3224 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
3225 scbd_val);
3226
3227 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
3228 return scbd_val;
3229 }
3230
3231 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
3232 {
3233 const struct rtw89_chip_info *chip = rtwdev->chip;
3234 struct rtw89_btc *btc = &rtwdev->btc;
3235 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3236 u32 scbd_val = 0;
3237
3238 if (!chip->scbd)
3239 return;
3240
3241 scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
3242
3243 if (scbd_val == wl->scbd)
3244 return;
3245 rtw89_mac_cfg_sb(rtwdev, scbd_val);
3246 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
3247 scbd_val);
3248 wl->scbd = scbd_val;
3249
3250 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
3251 }
3252
3253 static u8
3254 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
3255 {
3256 const struct rtw89_chip_info *chip = rtwdev->chip;
3257 u8 next_state, tol = chip->rssi_tol;
3258
3259 if (pre_state == BTC_RSSI_ST_LOW ||
3260 pre_state == BTC_RSSI_ST_STAY_LOW) {
3261 if (rssi >= (thresh + tol))
3262 next_state = BTC_RSSI_ST_HIGH;
3263 else
3264 next_state = BTC_RSSI_ST_STAY_LOW;
3265 } else {
3266 if (rssi < thresh)
3267 next_state = BTC_RSSI_ST_LOW;
3268 else
3269 next_state = BTC_RSSI_ST_STAY_HIGH;
3270 }
3271
3272 return next_state;
3273 }
3274
3275 static
3276 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
3277 {
3278 struct rtw89_btc *btc = &rtwdev->btc;
3279
3280 btc->cx.wl.dbcc_info.real_band[phy_idx] =
3281 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
3282 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
3283 btc->cx.wl.dbcc_info.op_band[phy_idx];
3284 }
3285
3286 static void _update_wl_info(struct rtw89_dev *rtwdev)
3287 {
3288 struct rtw89_btc *btc = &rtwdev->btc;
3289 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3290 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
3291 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3292 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
3293 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
3294 u8 cnt_2g = 0, cnt_5g = 0, phy;
3295 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
3296 bool b2g = false, b5g = false, client_joined = false;
3297
3298 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
3299
3300 for (i = 0; i < RTW89_PORT_NUM; i++) {
3301
3302 if (!wl_linfo[i].active)
3303 continue;
3304
3305 cnt_active++;
3306 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
3307 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
3308 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
3309 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
3310 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
3311 wl_rinfo->active_role[cnt_active - 1].connected = 0;
3312
3313 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
3314
3315 phy = wl_linfo[i].phy;
3316
3317
3318 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
3319 wl_dinfo->role[phy] = wl_linfo[i].role;
3320 wl_dinfo->op_band[phy] = wl_linfo[i].band;
3321 _update_dbcc_band(rtwdev, phy);
3322 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
3323 }
3324
3325 if (wl_linfo[i].connected == MLME_NO_LINK) {
3326 continue;
3327 } else if (wl_linfo[i].connected == MLME_LINKING) {
3328 cnt_connecting++;
3329 } else {
3330 cnt_connect++;
3331 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
3332 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
3333 wl_linfo[i].client_cnt > 1)
3334 client_joined = true;
3335 }
3336
3337 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
3338 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
3339 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
3340 wl_rinfo->active_role[cnt_active - 1].connected = 1;
3341
3342
3343 if (wl_linfo[i].band != RTW89_BAND_2G) {
3344 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
3345 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
3346 cnt_5g++;
3347 b5g = true;
3348 } else {
3349 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
3350 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
3351 cnt_2g++;
3352 b2g = true;
3353 }
3354 }
3355
3356 wl_rinfo->connect_cnt = cnt_connect;
3357
3358
3359 if (cnt_connect == 0) {
3360 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
3361 wl_rinfo->role_map.role.none = 1;
3362 } else if (!b2g && b5g) {
3363 wl_rinfo->link_mode = BTC_WLINK_5G;
3364 } else if (wl_rinfo->role_map.role.nan) {
3365 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
3366 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
3367 wl_rinfo->link_mode = BTC_WLINK_OTHER;
3368 } else if (b2g && b5g && cnt_connect == 2) {
3369 if (rtwdev->dbcc_en) {
3370 switch (wl_dinfo->role[RTW89_PHY_0]) {
3371 case RTW89_WIFI_ROLE_STATION:
3372 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
3373 break;
3374 case RTW89_WIFI_ROLE_P2P_GO:
3375 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
3376 break;
3377 case RTW89_WIFI_ROLE_P2P_CLIENT:
3378 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
3379 break;
3380 case RTW89_WIFI_ROLE_AP:
3381 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
3382 break;
3383 default:
3384 wl_rinfo->link_mode = BTC_WLINK_OTHER;
3385 break;
3386 }
3387 } else {
3388 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
3389 }
3390 } else if (!b5g && cnt_connect == 2) {
3391 if (wl_rinfo->role_map.role.station &&
3392 (wl_rinfo->role_map.role.p2p_go ||
3393 wl_rinfo->role_map.role.p2p_gc ||
3394 wl_rinfo->role_map.role.ap)) {
3395 if (wl_2g_ch[0] == wl_2g_ch[1])
3396 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
3397 else
3398 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
3399 } else {
3400 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
3401 }
3402 } else if (!b5g && cnt_connect == 1) {
3403 if (wl_rinfo->role_map.role.station)
3404 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
3405 else if (wl_rinfo->role_map.role.ap)
3406 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
3407 else if (wl_rinfo->role_map.role.p2p_go)
3408 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
3409 else if (wl_rinfo->role_map.role.p2p_gc)
3410 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
3411 else
3412 wl_rinfo->link_mode = BTC_WLINK_OTHER;
3413 }
3414
3415
3416 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
3417 if (!client_joined) {
3418 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
3419 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
3420 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
3421 wl_rinfo->connect_cnt = 1;
3422 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
3423 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
3424 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
3425 wl_rinfo->connect_cnt = 0;
3426 }
3427 }
3428 }
3429
3430 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3431 "[BTC], cnt_connect = %d, link_mode = %d\n",
3432 cnt_connect, wl_rinfo->link_mode);
3433
3434 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
3435 }
3436
3437 #define BTC_CHK_HANG_MAX 3
3438 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
3439
3440 void rtw89_coex_act1_work(struct work_struct *work)
3441 {
3442 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3443 coex_act1_work.work);
3444 struct rtw89_btc *btc = &rtwdev->btc;
3445 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
3446 struct rtw89_btc_cx *cx = &btc->cx;
3447 struct rtw89_btc_wl_info *wl = &cx->wl;
3448
3449 mutex_lock(&rtwdev->mutex);
3450 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
3451 dm->cnt_notify[BTC_NCNT_TIMER]++;
3452 if (wl->status.map._4way)
3453 wl->status.map._4way = false;
3454 if (wl->status.map.connecting)
3455 wl->status.map.connecting = false;
3456
3457 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
3458 mutex_unlock(&rtwdev->mutex);
3459 }
3460
3461 void rtw89_coex_bt_devinfo_work(struct work_struct *work)
3462 {
3463 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3464 coex_bt_devinfo_work.work);
3465 struct rtw89_btc *btc = &rtwdev->btc;
3466 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
3467 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
3468
3469 mutex_lock(&rtwdev->mutex);
3470 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
3471 dm->cnt_notify[BTC_NCNT_TIMER]++;
3472 a2dp->play_latency = 0;
3473 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
3474 mutex_unlock(&rtwdev->mutex);
3475 }
3476
3477 void rtw89_coex_rfk_chk_work(struct work_struct *work)
3478 {
3479 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3480 coex_rfk_chk_work.work);
3481 struct rtw89_btc *btc = &rtwdev->btc;
3482 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
3483 struct rtw89_btc_cx *cx = &btc->cx;
3484 struct rtw89_btc_wl_info *wl = &cx->wl;
3485
3486 mutex_lock(&rtwdev->mutex);
3487 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
3488 dm->cnt_notify[BTC_NCNT_TIMER]++;
3489 if (wl->rfk_info.state != BTC_WRFK_STOP) {
3490 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3491 "[BTC], %s(): RFK timeout\n", __func__);
3492 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
3493 dm->error.map.wl_rfk_timeout = true;
3494 wl->rfk_info.state = BTC_WRFK_STOP;
3495 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
3496 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
3497 }
3498 mutex_unlock(&rtwdev->mutex);
3499 }
3500
3501 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
3502 {
3503 const struct rtw89_chip_info *chip = rtwdev->chip;
3504 struct rtw89_btc *btc = &rtwdev->btc;
3505 struct rtw89_btc_cx *cx = &btc->cx;
3506 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3507 u32 val;
3508 bool status_change = false;
3509
3510 if (!chip->scbd)
3511 return;
3512
3513 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
3514
3515 val = _read_scbd(rtwdev);
3516 if (val == BTC_SCB_INV_VALUE) {
3517 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3518 "[BTC], %s(): return by invalid scbd value\n",
3519 __func__);
3520 return;
3521 }
3522
3523 if (!(val & BTC_BSCB_ON) ||
3524 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX)
3525 bt->enable.now = 0;
3526 else
3527 bt->enable.now = 1;
3528
3529 if (bt->enable.now != bt->enable.last)
3530 status_change = true;
3531
3532
3533 if (bt->enable.now && !bt->enable.last) {
3534 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
3535 cx->cnt_bt[BTC_BCNT_REENABLE]++;
3536 bt->enable.now = 1;
3537 }
3538
3539 bt->enable.last = bt->enable.now;
3540 bt->scbd = val;
3541 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
3542
3543 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
3544 status_change = true;
3545
3546 bt->whql_test = !!(val & BTC_BSCB_WHQL);
3547 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
3548 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT);
3549
3550
3551 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
3552 status_change = true;
3553
3554 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
3555 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
3556 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
3557 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
3558 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
3559
3560 if (!only_update && status_change)
3561 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
3562 }
3563
3564 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
3565 {
3566 struct rtw89_btc *btc = &rtwdev->btc;
3567 struct rtw89_btc_cx *cx = &btc->cx;
3568 struct rtw89_btc_bt_info *bt = &cx->bt;
3569
3570 _update_bt_scbd(rtwdev, true);
3571
3572 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
3573
3574 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
3575 !bt->rfk_info.map.timeout) {
3576 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
3577 } else {
3578 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
3579 return true;
3580 }
3581 return false;
3582 }
3583
3584 static
3585 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
3586 {
3587 struct rtw89_btc *btc = &rtwdev->btc;
3588 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
3589 struct rtw89_btc_cx *cx = &btc->cx;
3590 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3591 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3592 u8 mode = wl_rinfo->link_mode;
3593
3594 lockdep_assert_held(&rtwdev->mutex);
3595 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
3596 __func__, reason, mode);
3597 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
3598 __func__, dm->wl_only, dm->bt_only);
3599
3600 dm->run_reason = reason;
3601 _update_dm_step(rtwdev, reason);
3602 _update_btc_state_map(rtwdev);
3603
3604
3605 if (btc->ctrl.manual) {
3606 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3607 "[BTC], %s(): return for Manual CTRL!!\n",
3608 __func__);
3609 return;
3610 }
3611
3612 if (btc->ctrl.igno_bt &&
3613 (reason == BTC_RSN_UPDATE_BT_INFO ||
3614 reason == BTC_RSN_UPDATE_BT_SCBD)) {
3615 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3616 "[BTC], %s(): return for Stop Coex DM!!\n",
3617 __func__);
3618 return;
3619 }
3620
3621 if (!wl->status.map.init_ok) {
3622 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3623 "[BTC], %s(): return for WL init fail!!\n",
3624 __func__);
3625 return;
3626 }
3627
3628 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
3629 wl->status.map.lps_pre == wl->status.map.lps &&
3630 (reason == BTC_RSN_NTFY_POWEROFF ||
3631 reason == BTC_RSN_NTFY_RADIO_STATE)) {
3632 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3633 "[BTC], %s(): return for WL rf off state no change!!\n",
3634 __func__);
3635 return;
3636 }
3637
3638 dm->cnt_dm[BTC_DCNT_RUN]++;
3639
3640 if (btc->ctrl.always_freerun) {
3641 _action_freerun(rtwdev);
3642 btc->ctrl.igno_bt = true;
3643 goto exit;
3644 }
3645
3646 if (dm->wl_only) {
3647 _action_wl_only(rtwdev);
3648 btc->ctrl.igno_bt = true;
3649 goto exit;
3650 }
3651
3652 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
3653 _action_wl_off(rtwdev);
3654 btc->ctrl.igno_bt = true;
3655 goto exit;
3656 }
3657
3658 btc->ctrl.igno_bt = false;
3659 dm->freerun = false;
3660
3661 if (reason == BTC_RSN_NTFY_INIT) {
3662 _action_wl_init(rtwdev);
3663 goto exit;
3664 }
3665
3666 if (!cx->bt.enable.now && !cx->other.type) {
3667 _action_bt_off(rtwdev);
3668 goto exit;
3669 }
3670
3671 if (cx->bt.whql_test) {
3672 _action_bt_whql(rtwdev);
3673 goto exit;
3674 }
3675
3676 if (wl->rfk_info.state != BTC_WRFK_STOP) {
3677 _action_wl_rfk(rtwdev);
3678 goto exit;
3679 }
3680
3681 if (cx->state_map == BTC_WLINKING) {
3682 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
3683 mode == BTC_WLINK_5G) {
3684 _action_wl_scan(rtwdev);
3685 goto exit;
3686 }
3687 }
3688
3689 if (wl->status.map.scan) {
3690 _action_wl_scan(rtwdev);
3691 goto exit;
3692 }
3693
3694 switch (mode) {
3695 case BTC_WLINK_NOLINK:
3696 _action_wl_nc(rtwdev);
3697 break;
3698 case BTC_WLINK_2G_STA:
3699 _action_wl_2g_sta(rtwdev);
3700 break;
3701 case BTC_WLINK_2G_AP:
3702 _action_wl_2g_ap(rtwdev);
3703 break;
3704 case BTC_WLINK_2G_GO:
3705 _action_wl_2g_go(rtwdev);
3706 break;
3707 case BTC_WLINK_2G_GC:
3708 _action_wl_2g_gc(rtwdev);
3709 break;
3710 case BTC_WLINK_2G_SCC:
3711 _action_wl_2g_scc(rtwdev);
3712 break;
3713 case BTC_WLINK_2G_MCC:
3714 _action_wl_2g_mcc(rtwdev);
3715 break;
3716 case BTC_WLINK_25G_MCC:
3717 _action_wl_25g_mcc(rtwdev);
3718 break;
3719 case BTC_WLINK_5G:
3720 _action_wl_5g(rtwdev);
3721 break;
3722 case BTC_WLINK_2G_NAN:
3723 _action_wl_2g_nan(rtwdev);
3724 break;
3725 default:
3726 _action_wl_other(rtwdev);
3727 break;
3728 }
3729
3730 exit:
3731 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
3732 _action_common(rtwdev);
3733 }
3734
3735 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
3736 {
3737 struct rtw89_btc *btc = &rtwdev->btc;
3738
3739 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3740 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
3741 }
3742
3743 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
3744 {
3745 struct rtw89_btc *btc = &rtwdev->btc;
3746
3747 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3748 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
3749
3750 btc->cx.wl.status.map.rf_off = 1;
3751
3752 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
3753 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
3754
3755 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
3756
3757 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
3758 }
3759
3760 static void _set_init_info(struct rtw89_dev *rtwdev)
3761 {
3762 const struct rtw89_chip_info *chip = rtwdev->chip;
3763 struct rtw89_btc *btc = &rtwdev->btc;
3764 struct rtw89_btc_dm *dm = &btc->dm;
3765 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3766
3767 dm->init_info.wl_only = (u8)dm->wl_only;
3768 dm->init_info.bt_only = (u8)dm->bt_only;
3769 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok;
3770 dm->init_info.dbcc_en = rtwdev->dbcc_en;
3771 dm->init_info.cx_other = btc->cx.other.type;
3772 dm->init_info.wl_guard_ch = chip->afh_guard_ch;
3773 dm->init_info.module = btc->mdinfo;
3774 }
3775
3776 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
3777 {
3778 struct rtw89_btc *btc = &rtwdev->btc;
3779 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
3780 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3781 const struct rtw89_chip_info *chip = rtwdev->chip;
3782
3783 _reset_btc_var(rtwdev, BTC_RESET_ALL);
3784 btc->dm.run_reason = BTC_RSN_NONE;
3785 btc->dm.run_action = BTC_ACT_NONE;
3786 btc->ctrl.igno_bt = true;
3787
3788 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3789 "[BTC], %s(): mode=%d\n", __func__, mode);
3790
3791 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
3792 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
3793 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
3794 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
3795
3796 chip->ops->btc_set_rfe(rtwdev);
3797 chip->ops->btc_init_cfg(rtwdev);
3798
3799 if (!wl->status.map.init_ok) {
3800 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3801 "[BTC], %s(): return for WL init fail!!\n",
3802 __func__);
3803 dm->error.map.init = true;
3804 return;
3805 }
3806
3807 _write_scbd(rtwdev,
3808 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
3809 _update_bt_scbd(rtwdev, true);
3810 if (rtw89_mac_get_ctrl_path(rtwdev)) {
3811 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3812 "[BTC], %s(): PTA owner warning!!\n",
3813 __func__);
3814 dm->error.map.pta_owner = true;
3815 }
3816
3817 _set_init_info(rtwdev);
3818 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
3819 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
3820 btc_fw_set_monreg(rtwdev);
3821 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
3822 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
3823
3824 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
3825 }
3826
3827 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
3828 {
3829 struct rtw89_btc *btc = &rtwdev->btc;
3830 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3831
3832 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3833 "[BTC], %s(): phy_idx=%d, band=%d\n",
3834 __func__, phy_idx, band);
3835 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
3836 wl->status.map.scan = true;
3837 wl->scan_info.band[phy_idx] = band;
3838 wl->scan_info.phy_map |= BIT(phy_idx);
3839 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
3840
3841 if (rtwdev->dbcc_en) {
3842 wl->dbcc_info.scan_band[phy_idx] = band;
3843 _update_dbcc_band(rtwdev, phy_idx);
3844 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
3845 }
3846
3847 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
3848 }
3849
3850 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
3851 {
3852 struct rtw89_btc *btc = &rtwdev->btc;
3853 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3854
3855 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3856 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
3857 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
3858
3859 wl->status.map.scan = false;
3860 wl->scan_info.phy_map &= ~BIT(phy_idx);
3861 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
3862
3863 if (rtwdev->dbcc_en) {
3864 _update_dbcc_band(rtwdev, phy_idx);
3865 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
3866 }
3867
3868 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
3869 }
3870
3871 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
3872 {
3873 struct rtw89_btc *btc = &rtwdev->btc;
3874 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3875
3876 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3877 "[BTC], %s(): phy_idx=%d, band=%d\n",
3878 __func__, phy_idx, band);
3879 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
3880
3881 wl->scan_info.band[phy_idx] = band;
3882 wl->scan_info.phy_map |= BIT(phy_idx);
3883 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
3884
3885 if (rtwdev->dbcc_en) {
3886 wl->dbcc_info.scan_band[phy_idx] = band;
3887 _update_dbcc_band(rtwdev, phy_idx);
3888 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
3889 }
3890 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
3891 }
3892
3893 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
3894 enum btc_pkt_type pkt_type)
3895 {
3896 struct rtw89_btc *btc = &rtwdev->btc;
3897 struct rtw89_btc_cx *cx = &btc->cx;
3898 struct rtw89_btc_wl_info *wl = &cx->wl;
3899 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
3900 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
3901 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
3902 u32 cnt;
3903 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
3904 bool delay_work = false;
3905
3906 switch (pkt_type) {
3907 case PACKET_DHCP:
3908 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
3909 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3910 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
3911 wl->status.map.connecting = true;
3912 delay_work = true;
3913 break;
3914 case PACKET_EAPOL:
3915 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
3916 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3917 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
3918 wl->status.map._4way = true;
3919 delay_work = true;
3920 if (hfp->exist || hid->exist)
3921 delay /= 2;
3922 break;
3923 case PACKET_EAPOL_END:
3924 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
3925 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3926 "[BTC], %s(): EAPOL_End cnt=%d\n",
3927 __func__, cnt);
3928 wl->status.map._4way = false;
3929 cancel_delayed_work(&rtwdev->coex_act1_work);
3930 break;
3931 case PACKET_ARP:
3932 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
3933 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3934 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
3935 return;
3936 case PACKET_ICMP:
3937 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3938 "[BTC], %s(): ICMP pkt\n", __func__);
3939 return;
3940 default:
3941 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3942 "[BTC], %s(): unknown packet type %d\n",
3943 __func__, pkt_type);
3944 return;
3945 }
3946
3947 if (delay_work) {
3948 cancel_delayed_work(&rtwdev->coex_act1_work);
3949 ieee80211_queue_delayed_work(rtwdev->hw,
3950 &rtwdev->coex_act1_work, delay);
3951 }
3952
3953 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
3954 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
3955 }
3956
3957 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
3958 {
3959 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3960 btc.eapol_notify_work);
3961
3962 mutex_lock(&rtwdev->mutex);
3963 rtw89_leave_ps_mode(rtwdev);
3964 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
3965 mutex_unlock(&rtwdev->mutex);
3966 }
3967
3968 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
3969 {
3970 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3971 btc.arp_notify_work);
3972
3973 mutex_lock(&rtwdev->mutex);
3974 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
3975 mutex_unlock(&rtwdev->mutex);
3976 }
3977
3978 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
3979 {
3980 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3981 btc.dhcp_notify_work);
3982
3983 mutex_lock(&rtwdev->mutex);
3984 rtw89_leave_ps_mode(rtwdev);
3985 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
3986 mutex_unlock(&rtwdev->mutex);
3987 }
3988
3989 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
3990 {
3991 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
3992 btc.icmp_notify_work);
3993
3994 mutex_lock(&rtwdev->mutex);
3995 rtw89_leave_ps_mode(rtwdev);
3996 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
3997 mutex_unlock(&rtwdev->mutex);
3998 }
3999
4000 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
4001 {
4002 const struct rtw89_chip_info *chip = rtwdev->chip;
4003 struct rtw89_btc *btc = &rtwdev->btc;
4004 struct rtw89_btc_cx *cx = &btc->cx;
4005 struct rtw89_btc_bt_info *bt = &cx->bt;
4006 struct rtw89_btc_bt_link_info *b = &bt->link_info;
4007 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4008 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4009 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
4010 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
4011 union btc_btinfo btinfo;
4012
4013 if (buf[BTC_BTINFO_L1] != 6)
4014 return;
4015
4016 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
4017 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4018 "[BTC], %s(): return by bt-info duplicate!!\n",
4019 __func__);
4020 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
4021 return;
4022 }
4023
4024 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
4025
4026 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4027 "[BTC], %s(): bt_info[2]=0x%02x\n",
4028 __func__, bt->raw_info[2]);
4029
4030
4031 b->status.val = BTC_BLINK_NOCONNECT;
4032 b->profile_cnt.last = b->profile_cnt.now;
4033 b->relink.last = b->relink.now;
4034 a2dp->exist_last = a2dp->exist;
4035 b->multi_link.last = b->multi_link.now;
4036 bt->inq_pag.last = bt->inq_pag.now;
4037 b->profile_cnt.now = 0;
4038 hid->type = 0;
4039
4040
4041 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
4042 b->status.map.connect = btinfo.lb2.connect;
4043 b->status.map.sco_busy = btinfo.lb2.sco_busy;
4044 b->status.map.acl_busy = btinfo.lb2.acl_busy;
4045 b->status.map.inq_pag = btinfo.lb2.inq_pag;
4046 bt->inq_pag.now = btinfo.lb2.inq_pag;
4047 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
4048
4049 hfp->exist = btinfo.lb2.hfp;
4050 b->profile_cnt.now += (u8)hfp->exist;
4051 hid->exist = btinfo.lb2.hid;
4052 b->profile_cnt.now += (u8)hid->exist;
4053 a2dp->exist = btinfo.lb2.a2dp;
4054 b->profile_cnt.now += (u8)a2dp->exist;
4055 pan->active = btinfo.lb2.pan;
4056
4057
4058 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
4059 if (btinfo.lb3.retry != 0)
4060 cx->cnt_bt[BTC_BCNT_RETRY]++;
4061 b->cqddr = btinfo.lb3.cqddr;
4062 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
4063 bt->inq = btinfo.lb3.inq;
4064 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
4065 bt->pag = btinfo.lb3.pag;
4066
4067 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
4068
4069 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
4070
4071 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
4072
4073
4074 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
4075 b->status.map.ble_connect = btinfo.hb1.ble_connect;
4076 if (btinfo.hb1.ble_connect)
4077 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
4078
4079 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
4080 bt->reinit = btinfo.hb1.reinit;
4081 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
4082 b->relink.now = btinfo.hb1.relink;
4083 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
4084 bt->igno_wl = btinfo.hb1.igno_wl;
4085
4086 if (bt->igno_wl && !cx->wl.status.map.rf_off)
4087 _set_bt_ignore_wlan_act(rtwdev, false);
4088
4089 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
4090 bt->ble_scan_en = btinfo.hb1.ble_scan;
4091
4092 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
4093 b->role_sw = btinfo.hb1.role_sw;
4094
4095 b->multi_link.now = btinfo.hb1.multi_link;
4096
4097
4098 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
4099 pan->exist = btinfo.hb2.pan_active;
4100 b->profile_cnt.now += (u8)pan->exist;
4101
4102 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
4103 b->afh_update = btinfo.hb2.afh_update;
4104 a2dp->active = btinfo.hb2.a2dp_active;
4105 b->slave_role = btinfo.hb2.slave;
4106 hid->slot_info = btinfo.hb2.hid_slot;
4107 hid->pair_cnt = btinfo.hb2.hid_cnt;
4108 hid->type |= (hid->slot_info == BTC_HID_218 ?
4109 BTC_HID_218 : BTC_HID_418);
4110
4111 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
4112 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
4113
4114 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
4115 cx->cnt_bt[BTC_BCNT_RATECHG]++;
4116 b->tx_3m = (u32)btinfo.hb3.tx_3m;
4117
4118 a2dp->sink = btinfo.hb3.a2dp_sink;
4119
4120 if (b->profile_cnt.now || b->status.map.ble_connect)
4121 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1);
4122 else
4123 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0);
4124
4125 if (!a2dp->exist_last && a2dp->exist) {
4126 a2dp->vendor_id = 0;
4127 a2dp->flush_time = 0;
4128 a2dp->play_latency = 1;
4129 ieee80211_queue_delayed_work(rtwdev->hw,
4130 &rtwdev->coex_bt_devinfo_work,
4131 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
4132 }
4133
4134 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 ||
4135 a2dp->play_latency == 1))
4136 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1);
4137 else
4138 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0);
4139
4140 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
4141 }
4142
4143 enum btc_wl_mode {
4144 BTC_WL_MODE_HT = 0,
4145 BTC_WL_MODE_VHT = 1,
4146 BTC_WL_MODE_HE = 2,
4147 BTC_WL_MODE_NUM,
4148 };
4149
4150 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
4151 struct rtw89_sta *rtwsta, enum btc_role_state state)
4152 {
4153 struct rtw89_hal *hal = &rtwdev->hal;
4154 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
4155 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
4156 struct rtw89_btc *btc = &rtwdev->btc;
4157 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4158 struct rtw89_btc_wl_link_info r = {0};
4159 struct rtw89_btc_wl_link_info *wlinfo = NULL;
4160 u8 mode = 0;
4161
4162 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
4163 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4164 "[BTC], role is STA=%d\n",
4165 vif->type == NL80211_IFTYPE_STATION);
4166 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
4167 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
4168 hal->current_band_type, hal->current_channel,
4169 hal->current_band_width);
4170 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
4171 state == BTC_ROLE_MSTS_STA_CONN_END);
4172 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4173 "[BTC], bcn_period=%d dtim_period=%d\n",
4174 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
4175
4176 if (rtwsta) {
4177 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
4178 rtwsta->mac_id);
4179
4180 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4181 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
4182 sta->deflink.he_cap.has_he,
4183 sta->deflink.vht_cap.vht_supported,
4184 sta->deflink.ht_cap.ht_supported);
4185 if (sta->deflink.he_cap.has_he)
4186 mode |= BIT(BTC_WL_MODE_HE);
4187 if (sta->deflink.vht_cap.vht_supported)
4188 mode |= BIT(BTC_WL_MODE_VHT);
4189 if (sta->deflink.ht_cap.ht_supported)
4190 mode |= BIT(BTC_WL_MODE_HT);
4191
4192 r.mode = mode;
4193 }
4194
4195 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
4196 return;
4197
4198 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4199 "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
4200
4201 r.role = rtwvif->wifi_role;
4202 r.phy = rtwvif->phy_idx;
4203 r.pid = rtwvif->port;
4204 r.active = true;
4205 r.connected = MLME_LINKED;
4206 r.bcn_period = vif->bss_conf.beacon_int;
4207 r.dtim_period = vif->bss_conf.dtim_period;
4208 r.band = hal->current_band_type;
4209 r.ch = hal->current_channel;
4210 r.bw = hal->current_band_width;
4211 ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
4212
4213 if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
4214 r.mac_id = rtwsta->mac_id;
4215
4216 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
4217
4218 wlinfo = &wl->link_info[r.pid];
4219
4220 memcpy(wlinfo, &r, sizeof(*wlinfo));
4221 _update_wl_info(rtwdev);
4222
4223 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
4224 wlinfo->connected == MLME_NO_LINK)
4225 btc->dm.leak_ap = 0;
4226
4227 if (state == BTC_ROLE_MSTS_STA_CONN_START)
4228 wl->status.map.connecting = 1;
4229 else
4230 wl->status.map.connecting = 0;
4231
4232 if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
4233 wl->status.map._4way = false;
4234
4235 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
4236 }
4237
4238 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
4239 {
4240 const struct rtw89_chip_info *chip = rtwdev->chip;
4241 struct rtw89_btc *btc = &rtwdev->btc;
4242 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4243
4244 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
4245 __func__, rf_state);
4246 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
4247
4248 switch (rf_state) {
4249 case BTC_RFCTRL_WL_OFF:
4250 wl->status.map.rf_off = 1;
4251 wl->status.map.lps = BTC_LPS_OFF;
4252 break;
4253 case BTC_RFCTRL_FW_CTRL:
4254 wl->status.map.rf_off = 0;
4255 wl->status.map.lps = BTC_LPS_RF_OFF;
4256 break;
4257 case BTC_RFCTRL_WL_ON:
4258 default:
4259 wl->status.map.rf_off = 0;
4260 wl->status.map.lps = BTC_LPS_OFF;
4261 break;
4262 }
4263
4264 if (rf_state == BTC_RFCTRL_WL_ON) {
4265 rtw89_btc_fw_en_rpt(rtwdev,
4266 RPT_EN_MREG | RPT_EN_BT_VER_INFO, true);
4267 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, true);
4268 _update_bt_scbd(rtwdev, true);
4269 chip->ops->btc_init_cfg(rtwdev);
4270 } else {
4271 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
4272 _write_scbd(rtwdev, BTC_WSCB_ACTIVE | BTC_WSCB_WLBUSY, false);
4273 }
4274
4275 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
4276
4277 wl->status.map.rf_off_pre = wl->status.map.rf_off;
4278 wl->status.map.lps_pre = wl->status.map.lps;
4279 }
4280
4281 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
4282 enum btc_wl_rfk_type type,
4283 enum btc_wl_rfk_state state)
4284 {
4285 struct rtw89_btc *btc = &rtwdev->btc;
4286 struct rtw89_btc_cx *cx = &btc->cx;
4287 struct rtw89_btc_wl_info *wl = &cx->wl;
4288 bool result = BTC_WRFK_REJECT;
4289
4290 wl->rfk_info.type = type;
4291 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
4292 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
4293 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
4294
4295 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4296 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
4297 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
4298 type, state);
4299
4300 switch (state) {
4301 case BTC_WRFK_START:
4302 result = _chk_wl_rfk_request(rtwdev);
4303 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
4304
4305 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
4306
4307 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
4308 break;
4309 case BTC_WRFK_ONESHOT_START:
4310 case BTC_WRFK_ONESHOT_STOP:
4311 if (wl->rfk_info.state == BTC_WRFK_STOP) {
4312 result = BTC_WRFK_REJECT;
4313 } else {
4314 result = BTC_WRFK_ALLOW;
4315 wl->rfk_info.state = state;
4316 }
4317 break;
4318 case BTC_WRFK_STOP:
4319 result = BTC_WRFK_ALLOW;
4320 wl->rfk_info.state = BTC_WRFK_STOP;
4321
4322 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
4323 cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
4324 break;
4325 default:
4326 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4327 "[BTC], %s() warning state=%d\n", __func__, state);
4328 break;
4329 }
4330
4331 if (result == BTC_WRFK_ALLOW) {
4332 if (wl->rfk_info.state == BTC_WRFK_START ||
4333 wl->rfk_info.state == BTC_WRFK_STOP)
4334 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
4335
4336 if (wl->rfk_info.state == BTC_WRFK_START)
4337 ieee80211_queue_delayed_work(rtwdev->hw,
4338 &rtwdev->coex_rfk_chk_work,
4339 RTW89_COEX_RFK_CHK_WORK_PERIOD);
4340 }
4341
4342 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4343 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
4344 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
4345
4346 return result == BTC_WRFK_ALLOW;
4347 }
4348
4349 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
4350 enum btc_wl_rfk_type type,
4351 enum btc_wl_rfk_state state)
4352 {
4353 u8 band;
4354 bool allow;
4355 int ret;
4356
4357 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
4358
4359 rtw89_debug(rtwdev, RTW89_DBG_RFK,
4360 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
4361 band == RTW89_BAND_2G ? "2G" :
4362 band == RTW89_BAND_5G ? "5G" : "6G",
4363 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
4364 type,
4365 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
4366 state == BTC_WRFK_STOP ? "RFK_STOP" :
4367 state == BTC_WRFK_START ? "RFK_START" :
4368 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
4369 "ONE-SHOT_STOP");
4370
4371 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
4372 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
4373 return;
4374 }
4375
4376 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
4377 rtwdev, phy_map, type, state);
4378 if (ret) {
4379 rtw89_warn(rtwdev, "RFK notify timeout\n");
4380 rtwdev->is_bt_iqk_timeout = true;
4381 }
4382 }
4383 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
4384
4385 struct rtw89_btc_wl_sta_iter_data {
4386 struct rtw89_dev *rtwdev;
4387 u8 busy_all;
4388 u8 dir_all;
4389 u8 rssi_map_all;
4390 bool is_sta_change;
4391 bool is_traffic_change;
4392 };
4393
4394 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
4395 {
4396 struct rtw89_btc_wl_sta_iter_data *iter_data =
4397 (struct rtw89_btc_wl_sta_iter_data *)data;
4398 struct rtw89_dev *rtwdev = iter_data->rtwdev;
4399 struct rtw89_btc *btc = &rtwdev->btc;
4400 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4401 struct rtw89_btc_wl_link_info *link_info = NULL;
4402 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
4403 struct rtw89_traffic_stats *link_info_t = NULL;
4404 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
4405 struct rtw89_traffic_stats *stats = &rtwvif->stats;
4406 const struct rtw89_chip_info *chip = rtwdev->chip;
4407 u32 last_tx_rate, last_rx_rate;
4408 u16 last_tx_lvl, last_rx_lvl;
4409 u8 port = rtwvif->port;
4410 u8 rssi;
4411 u8 busy = 0;
4412 u8 dir = 0;
4413 u8 rssi_map = 0;
4414 u8 i = 0;
4415 bool is_sta_change = false, is_traffic_change = false;
4416
4417 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
4418 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
4419
4420 link_info = &wl->link_info[port];
4421 link_info->stat.traffic = rtwvif->stats;
4422 link_info_t = &link_info->stat.traffic;
4423
4424 if (link_info->connected == MLME_NO_LINK) {
4425 link_info->rx_rate_drop_cnt = 0;
4426 return;
4427 }
4428
4429 link_info->stat.rssi = rssi;
4430 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
4431 link_info->rssi_state[i] =
4432 _update_rssi_state(rtwdev,
4433 link_info->rssi_state[i],
4434 link_info->stat.rssi,
4435 chip->wl_rssi_thres[i]);
4436 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
4437 rssi_map |= BIT(i);
4438
4439 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED &&
4440 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
4441 is_sta_change = true;
4442 }
4443 iter_data->rssi_map_all |= rssi_map;
4444
4445 last_tx_rate = link_info_t->tx_rate;
4446 last_rx_rate = link_info_t->rx_rate;
4447 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
4448 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
4449
4450 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
4451 stats->rx_tfc_lv != RTW89_TFC_IDLE)
4452 busy = 1;
4453
4454 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
4455 dir = RTW89_TFC_UL;
4456 else
4457 dir = RTW89_TFC_DL;
4458
4459 link_info = &wl->link_info[port];
4460 if (link_info->busy != busy || link_info->dir != dir) {
4461 is_sta_change = true;
4462 link_info->busy = busy;
4463 link_info->dir = dir;
4464 }
4465
4466 iter_data->busy_all |= busy;
4467 iter_data->dir_all |= BIT(dir);
4468
4469 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
4470 last_rx_rate > RTW89_HW_RATE_CCK2 &&
4471 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
4472 link_info->rx_rate_drop_cnt++;
4473
4474 if (last_tx_rate != rtwsta->ra_report.hw_rate ||
4475 last_rx_rate != rtwsta->rx_hw_rate ||
4476 last_tx_lvl != link_info_t->tx_tfc_lv ||
4477 last_rx_lvl != link_info_t->rx_tfc_lv)
4478 is_traffic_change = true;
4479
4480 link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
4481 link_info_t->rx_rate = rtwsta->rx_hw_rate;
4482
4483 wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv;
4484 wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv;
4485 wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
4486 wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate;
4487
4488 if (is_sta_change)
4489 iter_data->is_sta_change = true;
4490
4491 if (is_traffic_change)
4492 iter_data->is_traffic_change = true;
4493 }
4494
4495 #define BTC_NHM_CHK_INTVL 20
4496
4497 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
4498 {
4499 struct rtw89_btc *btc = &rtwdev->btc;
4500 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4501 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
4502 u8 i;
4503
4504 ieee80211_iterate_stations_atomic(rtwdev->hw,
4505 rtw89_btc_ntfy_wl_sta_iter,
4506 &data);
4507
4508 wl->rssi_level = 0;
4509 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
4510 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
4511
4512 if (data.rssi_map_all & BIT(i - 1)) {
4513 wl->rssi_level = i;
4514 break;
4515 }
4516 }
4517
4518 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
4519 __func__, !!wl->status.map.busy);
4520
4521 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
4522
4523 if (data.is_traffic_change)
4524 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4525 if (data.is_sta_change) {
4526 wl->status.map.busy = data.busy_all;
4527 wl->status.map.traffic_dir = data.dir_all;
4528 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
4529 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
4530 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
4531 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
4532 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
4533 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
4534 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
4535 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
4536 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
4537 }
4538 }
4539
4540 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
4541 u32 len, u8 class, u8 func)
4542 {
4543 struct rtw89_btc *btc = &rtwdev->btc;
4544 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
4545 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
4546
4547 len -= RTW89_C2H_HEADER_LEN;
4548
4549 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4550 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
4551 __func__, len, class, func);
4552
4553 if (class != BTFC_FW_EVENT)
4554 return;
4555
4556 switch (func) {
4557 case BTF_EVNT_RPT:
4558 case BTF_EVNT_BUF_OVERFLOW:
4559 pfwinfo->event[func]++;
4560
4561 btc_fw_event(rtwdev, func, buf, len);
4562 break;
4563 case BTF_EVNT_BT_INFO:
4564 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4565 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
4566 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
4567 _update_bt_info(rtwdev, buf, len);
4568 break;
4569 case BTF_EVNT_BT_SCBD:
4570 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4571 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
4572 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
4573 _update_bt_scbd(rtwdev, false);
4574 break;
4575 case BTF_EVNT_BT_PSD:
4576 break;
4577 case BTF_EVNT_BT_REG:
4578 btc->dbg.rb_done = true;
4579 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
4580
4581 break;
4582 case BTF_EVNT_C2H_LOOPBACK:
4583 btc->dbg.rb_done = true;
4584 btc->dbg.rb_val = buf[0];
4585 break;
4586 case BTF_EVNT_CX_RUNINFO:
4587 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
4588 break;
4589 }
4590 }
4591
4592 #define BTC_CX_FW_OFFLOAD 0
4593
4594 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
4595 {
4596 const struct rtw89_chip_info *chip = rtwdev->chip;
4597 struct rtw89_hal *hal = &rtwdev->hal;
4598 struct rtw89_btc *btc = &rtwdev->btc;
4599 struct rtw89_btc_dm *dm = &btc->dm;
4600 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4601 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4602 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
4603
4604 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
4605 return;
4606
4607 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
4608
4609 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
4610 chip->chip_id);
4611
4612 ver_main = FIELD_GET(GENMASK(31, 24), chip->para_ver);
4613 ver_sub = FIELD_GET(GENMASK(23, 16), chip->para_ver);
4614 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->para_ver);
4615 id_branch = FIELD_GET(GENMASK(7, 0), chip->para_ver);
4616 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
4617 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
4618
4619 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD)
4620 dm->error.map.offload_mismatch = true;
4621 else
4622 dm->error.map.offload_mismatch = false;
4623
4624 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
4625 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
4626 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
4627 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
4628 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
4629 ver_main, ver_sub, ver_hotfix, id_branch);
4630
4631 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
4632 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
4633 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
4634 seq_printf(m, "(%s, desired:%d.%d.%d), ",
4635 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
4636 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
4637
4638 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
4639 bt->ver_info.fw_coex,
4640 (bt->ver_info.fw_coex >= chip->btcx_desired ?
4641 "Match" : "Mismatch"), chip->btcx_desired);
4642
4643 if (bt->enable.now && bt->ver_info.fw == 0)
4644 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
4645 else
4646 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
4647
4648 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
4649 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
4650 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
4651 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
4652 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
4653 "[sub_module]",
4654 ver_main, ver_sub, ver_hotfix, id_branch,
4655 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
4656
4657 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
4658 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type,
4659 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num,
4660 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ?
4661 "1Ant_Pos:S1, " : "1Ant_Pos:S0, ")));
4662
4663 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
4664 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
4665 hal->rx_nss);
4666 }
4667
4668 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
4669 {
4670 struct rtw89_btc *btc = &rtwdev->btc;
4671 struct rtw89_btc_wl_link_info *plink = NULL;
4672 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4673 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4674 struct rtw89_traffic_stats *t;
4675 u8 i;
4676
4677 if (rtwdev->dbcc_en) {
4678 seq_printf(m,
4679 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
4680 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
4681 wl_dinfo->scan_band[RTW89_PHY_0],
4682 wl_dinfo->real_band[RTW89_PHY_0]);
4683 seq_printf(m,
4684 "PHY1_band(op:%d/scan:%d/real:%d)\n",
4685 wl_dinfo->op_band[RTW89_PHY_1],
4686 wl_dinfo->scan_band[RTW89_PHY_1],
4687 wl_dinfo->real_band[RTW89_PHY_1]);
4688 }
4689
4690 for (i = 0; i < RTW89_PORT_NUM; i++) {
4691 plink = &btc->cx.wl.link_info[i];
4692
4693 if (!plink->active)
4694 continue;
4695
4696 seq_printf(m,
4697 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
4698 plink->pid, (u32)plink->role, plink->phy,
4699 (u32)plink->connected, plink->client_cnt - 1,
4700 (u32)plink->mode, plink->ch, (u32)plink->bw);
4701
4702 if (plink->connected == MLME_NO_LINK)
4703 continue;
4704
4705 seq_printf(m,
4706 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
4707 plink->mac_id, plink->tx_time, plink->tx_retry);
4708
4709 seq_printf(m,
4710 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
4711 plink->pid, 110 - plink->stat.rssi,
4712 plink->stat.rssi, plink->busy,
4713 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
4714
4715 t = &plink->stat.traffic;
4716
4717 seq_printf(m,
4718 "tx[rate:%d/busy_level:%d], ",
4719 (u32)t->tx_rate, t->tx_tfc_lv);
4720
4721 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
4722 (u32)t->rx_rate,
4723 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
4724 }
4725 }
4726
4727 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
4728 {
4729 struct rtw89_btc *btc = &rtwdev->btc;
4730 struct rtw89_btc_cx *cx = &btc->cx;
4731 struct rtw89_btc_wl_info *wl = &cx->wl;
4732 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4733
4734 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
4735 return;
4736
4737 seq_puts(m, "========== [WL Status] ==========\n");
4738
4739 seq_printf(m, " %-15s : link_mode:%d, ",
4740 "[status]", (u32)wl_rinfo->link_mode);
4741
4742 seq_printf(m,
4743 "rf_off:%s, power_save:%s, scan:%s(band:%d/phy_map:0x%x), ",
4744 wl->status.map.rf_off ? "Y" : "N",
4745 wl->status.map.lps ? "Y" : "N",
4746 wl->status.map.scan ? "Y" : "N",
4747 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
4748
4749 seq_printf(m,
4750 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
4751 wl->status.map.connecting ? "Y" : "N",
4752 wl->status.map.roaming ? "Y" : "N",
4753 wl->status.map._4way ? "Y" : "N",
4754 wl->status.map.init_ok ? "Y" : "N");
4755
4756 _show_wl_role_info(rtwdev, m);
4757 }
4758
4759 enum btc_bt_a2dp_type {
4760 BTC_A2DP_LEGACY = 0,
4761 BTC_A2DP_TWS_SNIFF = 1,
4762 BTC_A2DP_TWS_RELAY = 2,
4763 };
4764
4765 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
4766 {
4767 struct rtw89_btc *btc = &rtwdev->btc;
4768 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4769 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
4770 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
4771 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4772 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
4773
4774 if (hfp.exist) {
4775 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
4776 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
4777 bt_linfo->sut_pwr_level[0],
4778 bt_linfo->golden_rx_shift[0]);
4779 }
4780
4781 if (hid.exist) {
4782 seq_printf(m,
4783 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
4784 "[HID]",
4785 hid.type & BTC_HID_218 ? "2/18," : "",
4786 hid.type & BTC_HID_418 ? "4/18," : "",
4787 hid.type & BTC_HID_BLE ? "BLE," : "",
4788 hid.type & BTC_HID_RCU ? "RCU," : "",
4789 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
4790 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
4791 bt_linfo->golden_rx_shift[1]);
4792 }
4793
4794 if (a2dp.exist) {
4795 seq_printf(m,
4796 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
4797 "[A2DP]",
4798 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
4799 a2dp.bitpool, a2dp.flush_time);
4800
4801 seq_printf(m,
4802 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
4803 a2dp.vendor_id, a2dp.device_name,
4804 bt_linfo->sut_pwr_level[2],
4805 bt_linfo->golden_rx_shift[2]);
4806 }
4807
4808 if (pan.exist) {
4809 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
4810 "[PAN]",
4811 bt_linfo->sut_pwr_level[3],
4812 bt_linfo->golden_rx_shift[3]);
4813 }
4814 }
4815
4816 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
4817 {
4818 struct rtw89_btc *btc = &rtwdev->btc;
4819 struct rtw89_btc_cx *cx = &btc->cx;
4820 struct rtw89_btc_bt_info *bt = &cx->bt;
4821 struct rtw89_btc_wl_info *wl = &cx->wl;
4822 struct rtw89_btc_module *module = &btc->mdinfo;
4823 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
4824 u8 *afh = bt_linfo->afh_map;
4825
4826 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
4827 return;
4828
4829 seq_puts(m, "========== [BT Status] ==========\n");
4830
4831 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
4832 "[status]", bt->enable.now ? "Y" : "N",
4833 bt->btg_type ? "Y" : "N",
4834 (bt->enable.now && (bt->btg_type != module->bt_pos) ?
4835 "(efuse-mismatch!!)" : ""),
4836 (bt_linfo->status.map.connect ? "Y" : "N"));
4837
4838 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
4839 bt->igno_wl ? "Y" : "N",
4840 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
4841
4842 seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
4843 "[profile]",
4844 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
4845 bt_linfo->hfp_desc.exist ? "HFP," : "",
4846 bt_linfo->hid_desc.exist ? "HID," : "",
4847 bt_linfo->a2dp_desc.exist ?
4848 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
4849 bt_linfo->pan_desc.exist ? "PAN," : "");
4850
4851 seq_printf(m,
4852 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
4853 bt_linfo->multi_link.now ? "Y" : "N",
4854 bt_linfo->slave_role ? "Slave" : "Master",
4855 bt_linfo->status.map.ble_connect ? "Y" : "N",
4856 bt_linfo->cqddr ? "Y" : "N",
4857 bt_linfo->a2dp_desc.active ? "Y" : "N",
4858 bt_linfo->pan_desc.active ? "Y" : "N");
4859
4860 seq_printf(m,
4861 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s",
4862 "[link]", bt_linfo->rssi - 100,
4863 bt_linfo->tx_3m ? 3 : 2,
4864 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
4865 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
4866 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
4867
4868 seq_printf(m,
4869 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
4870 bt_linfo->relink.now ? " ReLink!!" : "",
4871 afh[0], afh[1], afh[2], afh[3], afh[4],
4872 afh[5], afh[6], afh[7], afh[8], afh[9]);
4873
4874 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
4875 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
4876
4877 seq_printf(m,
4878 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
4879 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
4880 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
4881 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
4882
4883 seq_printf(m,
4884 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
4885 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
4886 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
4887 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
4888
4889 _show_bt_profile_info(rtwdev, m);
4890
4891 seq_printf(m,
4892 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
4893 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
4894 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
4895 bt->raw_info[7],
4896 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
4897 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
4898 cx->cnt_bt[BTC_BCNT_INFOSAME]);
4899
4900 seq_printf(m,
4901 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n",
4902 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
4903 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
4904 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
4905 }
4906
4907 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
4908 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
4909 #define CASE_BTC_POLICY_STR(e) \
4910 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
4911
4912 static const char *steps_to_str(u16 step)
4913 {
4914 switch (step) {
4915 CASE_BTC_RSN_STR(NONE);
4916 CASE_BTC_RSN_STR(NTFY_INIT);
4917 CASE_BTC_RSN_STR(NTFY_SWBAND);
4918 CASE_BTC_RSN_STR(NTFY_WL_STA);
4919 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
4920 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
4921 CASE_BTC_RSN_STR(NTFY_WL_RFK);
4922 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
4923 CASE_BTC_RSN_STR(NTFY_SCAN_START);
4924 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
4925 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
4926 CASE_BTC_RSN_STR(NTFY_POWEROFF);
4927 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
4928 CASE_BTC_RSN_STR(CMD_SET_COEX);
4929 CASE_BTC_RSN_STR(ACT1_WORK);
4930 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
4931 CASE_BTC_RSN_STR(RFK_CHK_WORK);
4932
4933 CASE_BTC_ACT_STR(NONE);
4934 CASE_BTC_ACT_STR(WL_ONLY);
4935 CASE_BTC_ACT_STR(WL_5G);
4936 CASE_BTC_ACT_STR(WL_OTHER);
4937 CASE_BTC_ACT_STR(WL_IDLE);
4938 CASE_BTC_ACT_STR(WL_NC);
4939 CASE_BTC_ACT_STR(WL_RFK);
4940 CASE_BTC_ACT_STR(WL_INIT);
4941 CASE_BTC_ACT_STR(WL_OFF);
4942 CASE_BTC_ACT_STR(FREERUN);
4943 CASE_BTC_ACT_STR(BT_WHQL);
4944 CASE_BTC_ACT_STR(BT_RFK);
4945 CASE_BTC_ACT_STR(BT_OFF);
4946 CASE_BTC_ACT_STR(BT_IDLE);
4947 CASE_BTC_ACT_STR(BT_HFP);
4948 CASE_BTC_ACT_STR(BT_HID);
4949 CASE_BTC_ACT_STR(BT_A2DP);
4950 CASE_BTC_ACT_STR(BT_A2DPSINK);
4951 CASE_BTC_ACT_STR(BT_PAN);
4952 CASE_BTC_ACT_STR(BT_A2DP_HID);
4953 CASE_BTC_ACT_STR(BT_A2DP_PAN);
4954 CASE_BTC_ACT_STR(BT_PAN_HID);
4955 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
4956 CASE_BTC_ACT_STR(WL_25G_MCC);
4957 CASE_BTC_ACT_STR(WL_2G_MCC);
4958 CASE_BTC_ACT_STR(WL_2G_SCC);
4959 CASE_BTC_ACT_STR(WL_2G_AP);
4960 CASE_BTC_ACT_STR(WL_2G_GO);
4961 CASE_BTC_ACT_STR(WL_2G_GC);
4962 CASE_BTC_ACT_STR(WL_2G_NAN);
4963
4964 CASE_BTC_POLICY_STR(OFF_BT);
4965 CASE_BTC_POLICY_STR(OFF_WL);
4966 CASE_BTC_POLICY_STR(OFF_EQ0);
4967 CASE_BTC_POLICY_STR(OFF_EQ1);
4968 CASE_BTC_POLICY_STR(OFF_EQ2);
4969 CASE_BTC_POLICY_STR(OFF_EQ3);
4970 CASE_BTC_POLICY_STR(OFF_BWB0);
4971 CASE_BTC_POLICY_STR(OFF_BWB1);
4972 CASE_BTC_POLICY_STR(OFFB_BWB0);
4973 CASE_BTC_POLICY_STR(OFFE_DEF);
4974 CASE_BTC_POLICY_STR(OFFE_DEF2);
4975 CASE_BTC_POLICY_STR(FIX_TD3030);
4976 CASE_BTC_POLICY_STR(FIX_TD5050);
4977 CASE_BTC_POLICY_STR(FIX_TD2030);
4978 CASE_BTC_POLICY_STR(FIX_TD4010);
4979 CASE_BTC_POLICY_STR(FIX_TD7010);
4980 CASE_BTC_POLICY_STR(FIX_TD2060);
4981 CASE_BTC_POLICY_STR(FIX_TD3060);
4982 CASE_BTC_POLICY_STR(FIX_TD2080);
4983 CASE_BTC_POLICY_STR(FIX_TDW1B1);
4984 CASE_BTC_POLICY_STR(FIX_TD4020);
4985 CASE_BTC_POLICY_STR(PFIX_TD3030);
4986 CASE_BTC_POLICY_STR(PFIX_TD5050);
4987 CASE_BTC_POLICY_STR(PFIX_TD2030);
4988 CASE_BTC_POLICY_STR(PFIX_TD2060);
4989 CASE_BTC_POLICY_STR(PFIX_TD3070);
4990 CASE_BTC_POLICY_STR(PFIX_TD2080);
4991 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
4992 CASE_BTC_POLICY_STR(AUTO_TD50200);
4993 CASE_BTC_POLICY_STR(AUTO_TD60200);
4994 CASE_BTC_POLICY_STR(AUTO_TD20200);
4995 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
4996 CASE_BTC_POLICY_STR(PAUTO_TD50200);
4997 CASE_BTC_POLICY_STR(PAUTO_TD60200);
4998 CASE_BTC_POLICY_STR(PAUTO_TD20200);
4999 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
5000 CASE_BTC_POLICY_STR(AUTO2_TD3050);
5001 CASE_BTC_POLICY_STR(AUTO2_TD3070);
5002 CASE_BTC_POLICY_STR(AUTO2_TD5050);
5003 CASE_BTC_POLICY_STR(AUTO2_TD6060);
5004 CASE_BTC_POLICY_STR(AUTO2_TD2080);
5005 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
5006 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
5007 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
5008 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
5009 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
5010 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
5011 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
5012 default:
5013 return "unknown step";
5014 }
5015 }
5016
5017 static
5018 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
5019 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
5020 {
5021 u8 i;
5022 u8 cur_index;
5023
5024 for (i = 0; i < len ; i++) {
5025 if ((i % seg_len) == 0)
5026 seq_printf(m, " %-15s : ", prefix);
5027 cur_index = (start_idx + i) % ring_len;
5028 if (i % 3 == 0)
5029 seq_printf(m, "-> %-20s",
5030 steps_to_str(*(data + cur_index)));
5031 else if (i % 3 == 1)
5032 seq_printf(m, "-> %-15s",
5033 steps_to_str(*(data + cur_index)));
5034 else
5035 seq_printf(m, "-> %-13s",
5036 steps_to_str(*(data + cur_index)));
5037 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
5038 seq_puts(m, "\n");
5039 }
5040 }
5041
5042 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
5043 {
5044 struct rtw89_btc *btc = &rtwdev->btc;
5045 struct rtw89_btc_dm *dm = &btc->dm;
5046 u8 start_idx;
5047 u8 len;
5048
5049 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
5050 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
5051
5052 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
5053 ARRAY_SIZE(dm->dm_step.step));
5054 }
5055
5056 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5057 {
5058 struct rtw89_btc *btc = &rtwdev->btc;
5059 struct rtw89_btc_module *module = &btc->mdinfo;
5060 struct rtw89_btc_dm *dm = &btc->dm;
5061 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5062 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5063
5064 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
5065 return;
5066
5067 seq_printf(m, "========== [Mechanism Status %s] ==========\n",
5068 (btc->ctrl.manual ? "(Manual)" : "(Auto)"));
5069
5070 seq_printf(m,
5071 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n",
5072 "[status]",
5073 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated",
5074 steps_to_str(dm->run_reason),
5075 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
5076 FIELD_GET(GENMASK(7, 0), dm->set_ant_path),
5077 dm->cnt_dm[BTC_DCNT_RUN]);
5078
5079 _show_dm_step(rtwdev, m);
5080
5081 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
5082 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
5083 dm->freerun, btc->lps, dm->wl_mimo_ps);
5084
5085 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
5086 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
5087 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
5088 "" : "(Mismatch!!)"));
5089
5090 if (dm->rf_trx_para.wl_tx_power == 0xff)
5091 seq_printf(m,
5092 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
5093 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
5094
5095 else
5096 seq_printf(m,
5097 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
5098 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
5099 dm->rf_trx_para.wl_tx_power);
5100
5101 seq_printf(m,
5102 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
5103 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
5104 dm->rf_trx_para.bt_rx_gain,
5105 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
5106
5107 seq_printf(m,
5108 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU\n",
5109 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
5110 dm->wl_tx_limit.tx_retry, btc->bt_req_len);
5111 }
5112
5113 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
5114 {
5115 struct rtw89_btc *btc = &rtwdev->btc;
5116 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5117 struct rtw89_btc_fbtc_cysta *pcysta = NULL;
5118
5119 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
5120
5121 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 &&
5122 pcysta->except_cnt == 0 &&
5123 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
5124 return;
5125
5126 seq_printf(m, " %-15s : ", "[error]");
5127
5128 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
5129 seq_printf(m,
5130 "overflow-cnt: %d, ",
5131 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
5132 }
5133
5134 if (pfwinfo->len_mismch) {
5135 seq_printf(m,
5136 "len-mismatch: 0x%x, ",
5137 pfwinfo->len_mismch);
5138 }
5139
5140 if (pfwinfo->fver_mismch) {
5141 seq_printf(m,
5142 "fver-mismatch: 0x%x, ",
5143 pfwinfo->fver_mismch);
5144 }
5145
5146
5147 if (pcysta->exception || pcysta->except_cnt) {
5148 seq_printf(m,
5149 "exception-type: 0x%x, exception-cnt = %d",
5150 pcysta->exception, pcysta->except_cnt);
5151 }
5152 seq_puts(m, "\n");
5153 }
5154
5155 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
5156 {
5157 struct rtw89_btc *btc = &rtwdev->btc;
5158 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5159 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5160 struct rtw89_btc_fbtc_tdma *t = NULL;
5161 struct rtw89_btc_fbtc_slot *s = NULL;
5162 struct rtw89_btc_dm *dm = &btc->dm;
5163 u8 i, cnt = 0;
5164
5165 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
5166 if (!pcinfo->valid)
5167 return;
5168
5169 t = &pfwinfo->rpt_fbtc_tdma.finfo;
5170
5171 seq_printf(m,
5172 " %-15s : ", "[tdma_policy]");
5173 seq_printf(m,
5174 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
5175 (u32)t->type,
5176 t->rxflctrl, t->txpause);
5177
5178 seq_printf(m,
5179 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
5180 t->wtgle_n, t->leak_n, t->ext_ctrl);
5181
5182 seq_printf(m,
5183 "policy_type:%d",
5184 (u32)btc->policy_type);
5185
5186 s = pfwinfo->rpt_fbtc_slots.finfo.slot;
5187
5188 for (i = 0; i < CXST_MAX; i++) {
5189 if (dm->update_slot_map == BIT(CXST_MAX) - 1)
5190 break;
5191
5192 if (!(dm->update_slot_map & BIT(i)))
5193 continue;
5194
5195 if (cnt % 6 == 0)
5196 seq_printf(m,
5197 " %-15s : %d[%d/0x%x/%d]",
5198 "[slot_policy]",
5199 (u32)i,
5200 s[i].dur, s[i].cxtbl, s[i].cxtype);
5201 else
5202 seq_printf(m,
5203 ", %d[%d/0x%x/%d]",
5204 (u32)i,
5205 s[i].dur, s[i].cxtbl, s[i].cxtype);
5206 if (cnt % 6 == 5)
5207 seq_puts(m, "\n");
5208 cnt++;
5209 }
5210 seq_puts(m, "\n");
5211 }
5212
5213 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
5214 {
5215 struct rtw89_btc *btc = &rtwdev->btc;
5216 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5217 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5218 struct rtw89_btc_fbtc_slots *pslots = NULL;
5219 struct rtw89_btc_fbtc_slot s;
5220 u8 i = 0;
5221
5222 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
5223 if (!pcinfo->valid)
5224 return;
5225
5226 pslots = &pfwinfo->rpt_fbtc_slots.finfo;
5227
5228 for (i = 0; i < CXST_MAX; i++) {
5229 s = pslots->slot[i];
5230 if (i % 6 == 0)
5231 seq_printf(m,
5232 " %-15s : %02d[%03d/0x%x/%d]",
5233 "[slot_list]",
5234 (u32)i,
5235 s.dur, s.cxtbl, s.cxtype);
5236 else
5237 seq_printf(m,
5238 ", %02d[%03d/0x%x/%d]",
5239 (u32)i,
5240 s.dur, s.cxtbl, s.cxtype);
5241 if (i % 6 == 5)
5242 seq_puts(m, "\n");
5243 }
5244 }
5245
5246 static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m)
5247 {
5248 struct rtw89_btc *btc = &rtwdev->btc;
5249 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5250 struct rtw89_btc_dm *dm = &btc->dm;
5251 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
5252 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5253 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
5254 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
5255 union rtw89_btc_fbtc_rxflct r;
5256 u8 i, cnt = 0, slot_pair;
5257 u16 cycle, c_begin, c_end, store_index;
5258
5259 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
5260 if (!pcinfo->valid)
5261 return;
5262
5263 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
5264 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
5265 seq_printf(m,
5266 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
5267 "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL],
5268 pcysta->bcn_cnt[CXBCN_ALL_OK],
5269 pcysta->bcn_cnt[CXBCN_BT_SLOT],
5270 pcysta->bcn_cnt[CXBCN_BT_OK]);
5271
5272 for (i = 0; i < CXST_MAX; i++) {
5273 if (!pcysta->slot_cnt[i])
5274 continue;
5275 seq_printf(m,
5276 ", %d:%d", (u32)i, pcysta->slot_cnt[i]);
5277 }
5278
5279 if (dm->tdma_now.rxflctrl) {
5280 seq_printf(m,
5281 ", leak_rx:%d", pcysta->leakrx_cnt);
5282 }
5283
5284 if (pcysta->collision_cnt) {
5285 seq_printf(m,
5286 ", collision:%d", pcysta->collision_cnt);
5287 }
5288
5289 if (pcysta->skip_cnt) {
5290 seq_printf(m,
5291 ", skip:%d", pcysta->skip_cnt);
5292 }
5293 seq_puts(m, "\n");
5294
5295 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
5296 "[cycle_time]",
5297 pcysta->tavg_cycle[CXT_WL],
5298 pcysta->tavg_cycle[CXT_BT],
5299 pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000);
5300 seq_printf(m,
5301 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
5302 pcysta->tmax_cycle[CXT_WL],
5303 pcysta->tmax_cycle[CXT_BT],
5304 pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000);
5305 seq_printf(m,
5306 ", maxdiff_t[wl:%d/bt:%d]\n",
5307 pcysta->tmaxdiff_cycle[CXT_WL],
5308 pcysta->tmaxdiff_cycle[CXT_BT]);
5309
5310 if (pcysta->cycles == 0)
5311 return;
5312
5313
5314 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
5315
5316 if (pcysta->cycles <= slot_pair)
5317 c_begin = 1;
5318 else
5319 c_begin = pcysta->cycles - slot_pair + 1;
5320
5321 c_end = pcysta->cycles;
5322
5323 for (cycle = c_begin; cycle <= c_end; cycle++) {
5324 cnt++;
5325 store_index = ((cycle - 1) % slot_pair) * 2;
5326
5327 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
5328 seq_printf(m,
5329 " %-15s : ->b%02d->w%02d", "[cycle_step]",
5330 pcysta->tslot_cycle[store_index],
5331 pcysta->tslot_cycle[store_index + 1]);
5332 else
5333 seq_printf(m,
5334 "->b%02d->w%02d",
5335 pcysta->tslot_cycle[store_index],
5336 pcysta->tslot_cycle[store_index + 1]);
5337 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
5338 seq_puts(m, "\n");
5339 }
5340
5341 if (a2dp->exist) {
5342 seq_printf(m,
5343 " %-15s : a2dp_ept:%d, a2dp_late:%d",
5344 "[a2dp_t_sta]",
5345 pcysta->a2dpept, pcysta->a2dpeptto);
5346
5347 seq_printf(m,
5348 ", avg_t:%d, max_t:%d",
5349 pcysta->tavg_a2dpept, pcysta->tmax_a2dpept);
5350 r.val = dm->tdma_now.rxflctrl;
5351
5352 if (r.type && r.tgln_n) {
5353 seq_printf(m,
5354 ", cycle[PSTDMA:%d/TDMA:%d], ",
5355 pcysta->cycles_a2dp[CXT_FLCTRL_ON],
5356 pcysta->cycles_a2dp[CXT_FLCTRL_OFF]);
5357
5358 seq_printf(m,
5359 "avg_t[PSTDMA:%d/TDMA:%d], ",
5360 pcysta->tavg_a2dp[CXT_FLCTRL_ON],
5361 pcysta->tavg_a2dp[CXT_FLCTRL_OFF]);
5362
5363 seq_printf(m,
5364 "max_t[PSTDMA:%d/TDMA:%d]",
5365 pcysta->tmax_a2dp[CXT_FLCTRL_ON],
5366 pcysta->tmax_a2dp[CXT_FLCTRL_OFF]);
5367 }
5368 seq_puts(m, "\n");
5369 }
5370 }
5371
5372 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
5373 {
5374 struct rtw89_btc *btc = &rtwdev->btc;
5375 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5376 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5377 struct rtw89_btc_fbtc_cynullsta *ns = NULL;
5378 u8 i = 0;
5379
5380 if (!btc->dm.tdma_now.rxflctrl)
5381 return;
5382
5383 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
5384 if (!pcinfo->valid)
5385 return;
5386
5387 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
5388
5389 seq_printf(m, " %-15s : ", "[null_sta]");
5390
5391 for (i = 0; i < 2; i++) {
5392 if (i != 0)
5393 seq_printf(m, ", null-%d", i);
5394 else
5395 seq_printf(m, "null-%d", i);
5396 seq_printf(m, "[ok:%d/", le32_to_cpu(ns->result[i][1]));
5397 seq_printf(m, "fail:%d/", le32_to_cpu(ns->result[i][0]));
5398 seq_printf(m, "on_time:%d/", le32_to_cpu(ns->result[i][2]));
5399 seq_printf(m, "retry:%d/", le32_to_cpu(ns->result[i][3]));
5400 seq_printf(m, "avg_t:%d.%03d/",
5401 le32_to_cpu(ns->avg_t[i]) / 1000,
5402 le32_to_cpu(ns->avg_t[i]) % 1000);
5403 seq_printf(m, "max_t:%d.%03d]",
5404 le32_to_cpu(ns->max_t[i]) / 1000,
5405 le32_to_cpu(ns->max_t[i]) % 1000);
5406 }
5407 seq_puts(m, "\n");
5408 }
5409
5410 static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m)
5411 {
5412 struct rtw89_btc *btc = &rtwdev->btc;
5413 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5414 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5415 struct rtw89_btc_fbtc_steps *pstep = NULL;
5416 u8 type, val, cnt = 0, state = 0;
5417 bool outloop = false;
5418 u16 i, diff_t, n_start = 0, n_stop = 0;
5419 u16 pos_old, pos_new;
5420
5421 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
5422 if (!pcinfo->valid)
5423 return;
5424
5425 pstep = &pfwinfo->rpt_fbtc_step.finfo;
5426 pos_old = le16_to_cpu(pstep->pos_old);
5427 pos_new = le16_to_cpu(pstep->pos_new);
5428
5429 if (pcinfo->req_fver != pstep->fver)
5430 return;
5431
5432
5433 do {
5434 switch (state) {
5435 case 0:
5436 n_start = pos_old;
5437 if (pos_new >= pos_old)
5438 n_stop = pos_new;
5439 else
5440 n_stop = btc->ctrl.trace_step - 1;
5441
5442 state = 1;
5443 break;
5444 case 1:
5445 for (i = n_start; i <= n_stop; i++) {
5446 type = pstep->step[i].type;
5447 val = pstep->step[i].val;
5448 diff_t = le16_to_cpu(pstep->step[i].difft);
5449
5450 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
5451 continue;
5452
5453 if (cnt % 10 == 0)
5454 seq_printf(m, " %-15s : ", "[steps]");
5455
5456 seq_printf(m, "-> %s(%02d)(%02d)",
5457 (type == CXSTEP_SLOT ? "SLT" :
5458 "EVT"), (u32)val, diff_t);
5459 if (cnt % 10 == 9)
5460 seq_puts(m, "\n");
5461 cnt++;
5462 }
5463
5464 state = 2;
5465 break;
5466 case 2:
5467 if (pos_new < pos_old && n_start != 0) {
5468 n_start = 0;
5469 n_stop = pos_new;
5470 state = 1;
5471 } else {
5472 outloop = true;
5473 }
5474 break;
5475 }
5476 } while (!outloop);
5477 }
5478
5479 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
5480 {
5481 struct rtw89_btc *btc = &rtwdev->btc;
5482
5483 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
5484 return;
5485
5486 _show_error(rtwdev, m);
5487 _show_fbtc_tdma(rtwdev, m);
5488 _show_fbtc_slots(rtwdev, m);
5489 _show_fbtc_cysta(rtwdev, m);
5490 _show_fbtc_nullsta(rtwdev, m);
5491 _show_fbtc_step(rtwdev, m);
5492 }
5493
5494 static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
5495 {
5496 const struct rtw89_chip_info *chip = rtwdev->chip;
5497 struct rtw89_btc *btc = &rtwdev->btc;
5498 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5499 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5500 struct rtw89_btc_fbtc_mreg_val *pmreg = NULL;
5501 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
5502 struct rtw89_btc_cx *cx = &btc->cx;
5503 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5504 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5505 struct rtw89_mac_ax_gnt gnt[2] = {0};
5506 u8 i = 0, type = 0, cnt = 0;
5507 u32 val, offset;
5508
5509 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
5510 return;
5511
5512 seq_puts(m, "========== [HW Status] ==========\n");
5513
5514 seq_printf(m,
5515 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
5516 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
5517 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
5518 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
5519
5520
5521 if (!wl->status.map.lps && !wl->status.map.rf_off) {
5522 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
5523 if (val & (B_AX_GNT_BT_RFC_S0_SW_VAL |
5524 B_AX_GNT_BT_BB_S0_SW_VAL))
5525 gnt[0].gnt_bt = true;
5526 if (val & (B_AX_GNT_BT_RFC_S0_SW_CTRL |
5527 B_AX_GNT_BT_BB_S0_SW_CTRL))
5528 gnt[0].gnt_bt_sw_en = true;
5529 if (val & (B_AX_GNT_WL_RFC_S0_SW_VAL |
5530 B_AX_GNT_WL_BB_S0_SW_VAL))
5531 gnt[0].gnt_wl = true;
5532 if (val & (B_AX_GNT_WL_RFC_S0_SW_CTRL |
5533 B_AX_GNT_WL_BB_S0_SW_CTRL))
5534 gnt[0].gnt_wl_sw_en = true;
5535
5536 if (val & (B_AX_GNT_BT_RFC_S1_SW_VAL |
5537 B_AX_GNT_BT_BB_S1_SW_VAL))
5538 gnt[1].gnt_bt = true;
5539 if (val & (B_AX_GNT_BT_RFC_S1_SW_CTRL |
5540 B_AX_GNT_BT_BB_S1_SW_CTRL))
5541 gnt[1].gnt_bt_sw_en = true;
5542 if (val & (B_AX_GNT_WL_RFC_S1_SW_VAL |
5543 B_AX_GNT_WL_BB_S1_SW_VAL))
5544 gnt[1].gnt_wl = true;
5545 if (val & (B_AX_GNT_WL_RFC_S1_SW_CTRL |
5546 B_AX_GNT_WL_BB_S1_SW_CTRL))
5547 gnt[1].gnt_wl_sw_en = true;
5548
5549 seq_printf(m,
5550 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
5551 "[gnt_status]",
5552 (rtw89_mac_get_ctrl_path(rtwdev) ? "WL" : "BT"),
5553 (gnt[0].gnt_wl_sw_en ? "SW" : "HW"), gnt[0].gnt_wl,
5554 (gnt[0].gnt_bt_sw_en ? "SW" : "HW"), gnt[0].gnt_bt);
5555
5556 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
5557 (gnt[1].gnt_wl_sw_en ? "SW" : "HW"), gnt[1].gnt_wl,
5558 (gnt[1].gnt_bt_sw_en ? "SW" : "HW"), gnt[1].gnt_bt);
5559 }
5560
5561 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
5562 if (!pcinfo->valid) {
5563 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5564 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
5565 __func__);
5566 return;
5567 }
5568
5569 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo;
5570 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5571 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
5572 __func__, pmreg->reg_num);
5573
5574 for (i = 0; i < pmreg->reg_num; i++) {
5575 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
5576 offset = le32_to_cpu(chip->mon_reg[i].offset);
5577 val = le32_to_cpu(pmreg->mreg_val[i]);
5578
5579 if (cnt % 6 == 0)
5580 seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
5581 "[reg]", (u32)type, offset, val);
5582 else
5583 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
5584 offset, val);
5585 if (cnt % 6 == 5)
5586 seq_puts(m, "\n");
5587 cnt++;
5588 }
5589
5590 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
5591 if (!pcinfo->valid) {
5592 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5593 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
5594 __func__);
5595 return;
5596 }
5597
5598 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
5599 if (!gdbg->en_map)
5600 return;
5601
5602 seq_printf(m, " %-15s : enable_map:0x%08x",
5603 "[gpio_dbg]", gdbg->en_map);
5604
5605 for (i = 0; i < BTC_DBG_MAX1; i++) {
5606 if (!(gdbg->en_map & BIT(i)))
5607 continue;
5608 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]);
5609 }
5610 seq_puts(m, "\n");
5611 }
5612
5613 static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m)
5614 {
5615 struct rtw89_btc *btc = &rtwdev->btc;
5616 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5617 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
5618 struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL;
5619 struct rtw89_btc_cx *cx = &btc->cx;
5620 struct rtw89_btc_dm *dm = &btc->dm;
5621 struct rtw89_btc_wl_info *wl = &cx->wl;
5622 struct rtw89_btc_bt_info *bt = &cx->bt;
5623 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
5624 u8 i;
5625
5626 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
5627 return;
5628
5629 seq_puts(m, "========== [Statistics] ==========\n");
5630
5631 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
5632 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
5633 prptctrl = &pfwinfo->rpt_ctrl.finfo;
5634
5635 seq_printf(m,
5636 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
5637 "[summary]", pfwinfo->cnt_h2c,
5638 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
5639 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
5640
5641 seq_printf(m,
5642 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
5643 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
5644 prptctrl->rpt_enable, dm->error.val);
5645
5646 if (dm->error.map.wl_fw_hang)
5647 seq_puts(m, " (WL FW Hang!!)");
5648 seq_puts(m, "\n");
5649 seq_printf(m,
5650 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
5651 "[mailbox]", prptctrl->mb_send_ok_cnt,
5652 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
5653
5654 seq_printf(m,
5655 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
5656 prptctrl->mb_a2dp_empty_cnt,
5657 prptctrl->mb_a2dp_flct_cnt,
5658 prptctrl->mb_a2dp_full_cnt);
5659
5660 seq_printf(m,
5661 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
5662 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
5663 cx->cnt_wl[BTC_WCNT_RFK_GO],
5664 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
5665 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
5666
5667 seq_printf(m,
5668 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
5669 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
5670 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
5671 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
5672 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
5673 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
5674
5675 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
5676 bt->rfk_info.map.timeout = 1;
5677 else
5678 bt->rfk_info.map.timeout = 0;
5679
5680 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
5681 } else {
5682 seq_printf(m,
5683 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
5684 "[summary]", pfwinfo->cnt_h2c,
5685 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
5686 pfwinfo->event[BTF_EVNT_RPT],
5687 btc->fwinfo.rpt_en_map);
5688 seq_puts(m, " (WL FW report invalid!!)\n");
5689 }
5690
5691 for (i = 0; i < BTC_NCNT_NUM; i++)
5692 cnt_sum += dm->cnt_notify[i];
5693
5694 seq_printf(m,
5695 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
5696 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
5697 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
5698
5699 seq_printf(m,
5700 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
5701 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
5702 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
5703 cnt[BTC_NCNT_WL_STA]);
5704
5705 seq_printf(m,
5706 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
5707 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
5708 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
5709 cnt[BTC_NCNT_SPECIAL_PACKET]);
5710
5711 seq_printf(m,
5712 "timer=%d, control=%d, customerize=%d\n",
5713 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
5714 cnt[BTC_NCNT_CUSTOMERIZE]);
5715 }
5716
5717 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5718 {
5719 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
5720 struct rtw89_btc *btc = &rtwdev->btc;
5721 struct rtw89_btc_cx *cx = &btc->cx;
5722 struct rtw89_btc_bt_info *bt = &cx->bt;
5723
5724 seq_puts(m, "=========================================\n");
5725 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n",
5726 fw_suit->major_ver, fw_suit->minor_ver,
5727 fw_suit->sub_ver, fw_suit->sub_idex);
5728 seq_printf(m, "manual %d\n", btc->ctrl.manual);
5729
5730 seq_puts(m, "=========================================\n");
5731
5732 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
5733 "[bt_info]",
5734 bt->raw_info[2], bt->raw_info[3],
5735 bt->raw_info[4], bt->raw_info[5],
5736 bt->raw_info[6], bt->raw_info[7],
5737 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
5738 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
5739 cx->cnt_bt[BTC_BCNT_INFOSAME]);
5740
5741 seq_puts(m, "\n=========================================\n");
5742
5743 _show_cx_info(rtwdev, m);
5744 _show_wl_info(rtwdev, m);
5745 _show_bt_info(rtwdev, m);
5746 _show_dm_info(rtwdev, m);
5747 _show_fw_dm_msg(rtwdev, m);
5748 _show_mreg(rtwdev, m);
5749 _show_summary(rtwdev, m);
5750 }