1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2019-2020 Realtek Corporation 3 */ 4 5 #include "chan.h" 6 #include "coex.h" 7 #include "debug.h" 8 #include "fw.h" 9 #include "mac.h" 10 #include "phy.h" 11 #include "ps.h" 12 #include "reg.h" 13 14 #define RTW89_COEX_VERSION 0x09000013 15 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/ 16 #define BTC_E2G_LIMIT_DEF 80 17 18 enum btc_fbtc_tdma_template { 19 CXTD_OFF = 0x0, 20 CXTD_OFF_B2, 21 CXTD_OFF_EXT, 22 CXTD_FIX, 23 CXTD_PFIX, 24 CXTD_AUTO, 25 CXTD_PAUTO, 26 CXTD_AUTO2, 27 CXTD_PAUTO2, 28 CXTD_MAX, 29 }; 30 31 enum btc_fbtc_tdma_type { 32 CXTDMA_OFF = 0x0, 33 CXTDMA_FIX = 0x1, 34 CXTDMA_AUTO = 0x2, 35 CXTDMA_AUTO2 = 0x3, 36 CXTDMA_MAX 37 }; 38 39 enum btc_fbtc_tdma_rx_flow_ctrl { 40 CXFLC_OFF = 0x0, 41 CXFLC_NULLP = 0x1, 42 CXFLC_QOSNULL = 0x2, 43 CXFLC_CTS = 0x3, 44 CXFLC_MAX 45 }; 46 47 enum btc_fbtc_tdma_wlan_tx_pause { 48 CXTPS_OFF = 0x0, /* no wl tx pause*/ 49 CXTPS_ON = 0x1, 50 CXTPS_MAX 51 }; 52 53 enum btc_mlme_state { 54 MLME_NO_LINK, 55 MLME_LINKING, 56 MLME_LINKED, 57 }; 58 59 struct btc_fbtc_1slot { 60 u8 fver; 61 u8 sid; /* slot id */ 62 struct rtw89_btc_fbtc_slot slot; 63 } __packed; 64 65 static const struct rtw89_btc_fbtc_tdma t_def[] = { 66 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 67 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0}, 68 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0}, 69 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 70 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 71 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 72 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, 73 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, 74 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0} 75 }; 76 77 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \ 78 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \ 79 .cxtype = cpu_to_le16(__cxtype),} 80 81 static const struct rtw89_btc_fbtc_slot s_def[] = { 82 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX), 83 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO), 84 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO), 85 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 86 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO), 87 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX), 88 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX), 89 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 90 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX), 91 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO), 92 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX), 93 [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX), 94 [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO), 95 [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), 96 [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX), 97 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), 98 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), 99 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), 100 }; 101 102 static const u32 cxtbl[] = { 103 0xffffffff, /* 0 */ 104 0xaaaaaaaa, /* 1 */ 105 0xe5555555, /* 2 */ 106 0xee555555, /* 3 */ 107 0xd5555555, /* 4 */ 108 0x5a5a5a5a, /* 5 */ 109 0xfa5a5a5a, /* 6 */ 110 0xda5a5a5a, /* 7 */ 111 0xea5a5a5a, /* 8 */ 112 0x6a5a5aaa, /* 9 */ 113 0x6a5a6a5a, /* 10 */ 114 0x6a5a6aaa, /* 11 */ 115 0x6afa5afa, /* 12 */ 116 0xaaaa5aaa, /* 13 */ 117 0xaaffffaa, /* 14 */ 118 0xaa5555aa, /* 15 */ 119 0xfafafafa, /* 16 */ 120 0xffffddff, /* 17 */ 121 0xdaffdaff, /* 18 */ 122 0xfafadafa, /* 19 */ 123 0xea6a6a6a, /* 20 */ 124 0xea55556a, /* 21 */ 125 0xaafafafa, /* 22 */ 126 0xfafaaafa, /* 23 */ 127 0xfafffaff, /* 24 */ 128 0xea6a5a5a, /* 25 */ 129 0xfaff5aff, /* 26 */ 130 0xffffdfff, /* 27 */ 131 0xe6555555, /* 28 */ 132 }; 133 134 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { 135 /* firmware version must be in decreasing order for each chip */ 136 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0), 137 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 138 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 139 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 140 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 141 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, 142 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 143 }, 144 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0), 145 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 146 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 147 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 148 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 149 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, 150 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 151 }, 152 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0), 153 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 154 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 155 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 156 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7, 157 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800, 158 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, 159 }, 160 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0), 161 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 162 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 163 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 164 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7, 165 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800, 166 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9, 167 }, 168 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), 169 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 170 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 171 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 172 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 173 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800, 174 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 175 }, 176 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), 177 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 178 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 179 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 180 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 181 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, 182 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 183 }, 184 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), 185 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 186 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 187 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 188 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 189 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, 190 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 191 }, 192 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), 193 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 194 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 195 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 196 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 197 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, 198 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 199 }, 200 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), 201 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 202 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 203 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 204 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, 205 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, 206 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 207 }, 208 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0), 209 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, 210 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, 211 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, 212 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, 213 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, 214 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8, 215 }, 216 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), 217 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, 218 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, 219 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, 220 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 221 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, 222 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 223 }, 224 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), 225 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, 226 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 227 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 228 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 229 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, 230 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 231 }, 232 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), 233 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 234 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 235 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 236 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, 237 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, 238 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 239 }, 240 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), 241 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, 242 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, 243 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, 244 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, 245 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280, 246 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 247 }, 248 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), 249 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 250 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 251 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 252 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 253 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024, 254 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 255 }, 256 257 /* keep it to be the last as default entry */ 258 {0, RTW89_FW_VER_CODE(0, 0, 0, 0), 259 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, 260 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, 261 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, 262 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, 263 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024, 264 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7, 265 }, 266 }; 267 268 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1) 269 270 static const union rtw89_btc_wl_state_map btc_scanning_map = { 271 .map = { 272 .scan = 1, 273 .connecting = 1, 274 .roaming = 1, 275 .dbccing = 1, 276 ._4way = 1, 277 }, 278 }; 279 280 static u32 chip_id_to_bt_rom_code_id(u32 id) 281 { 282 switch (id) { 283 case RTL8852A: 284 case RTL8852B: 285 case RTL8852C: 286 case RTL8852BT: 287 return 0x8852; 288 case RTL8851B: 289 return 0x8851; 290 case RTL8922A: 291 return 0x8922; 292 default: 293 return 0; 294 } 295 } 296 297 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e 298 299 static const char *id_to_mlme_state(u32 id) 300 { 301 switch (id) { 302 CASE_BTC_MLME_STATE(NO_LINK); 303 CASE_BTC_MLME_STATE(LINKING); 304 CASE_BTC_MLME_STATE(LINKED); 305 default: 306 return "unknown"; 307 } 308 } 309 310 static char *chip_id_str(u32 id) 311 { 312 switch (id) { 313 case RTL8852A: 314 return "RTL8852A"; 315 case RTL8852B: 316 return "RTL8852B"; 317 case RTL8852C: 318 return "RTL8852C"; 319 case RTL8852BT: 320 return "RTL8852BT"; 321 case RTL8851B: 322 return "RTL8851B"; 323 case RTL8922A: 324 return "RTL8922A"; 325 default: 326 return "UNKNOWN"; 327 } 328 } 329 330 struct rtw89_btc_btf_tlv { 331 u8 type; 332 u8 len; 333 u8 val[]; 334 } __packed; 335 336 struct rtw89_btc_btf_tlv_v7 { 337 u8 type; 338 u8 ver; 339 u8 len; 340 u8 val[]; 341 } __packed; 342 343 enum btc_btf_set_report_en { 344 RPT_EN_TDMA, 345 RPT_EN_CYCLE, 346 RPT_EN_MREG, 347 RPT_EN_BT_VER_INFO, 348 RPT_EN_BT_SCAN_INFO, 349 RPT_EN_BT_DEVICE_INFO, 350 RPT_EN_BT_AFH_MAP, 351 RPT_EN_BT_AFH_MAP_LE, 352 RPT_EN_BT_TX_PWR_LVL, 353 RPT_EN_FW_STEP_INFO, 354 RPT_EN_TEST, 355 RPT_EN_WL_ALL, 356 RPT_EN_BT_ALL, 357 RPT_EN_ALL, 358 RPT_EN_MONITER, 359 }; 360 361 struct rtw89_btc_btf_set_report_v1 { 362 u8 fver; 363 __le32 enable; 364 __le32 para; 365 } __packed; 366 367 struct rtw89_btc_btf_set_report_v8 { 368 u8 type; 369 u8 fver; 370 u8 len; 371 __le32 map; 372 } __packed; 373 374 union rtw89_fbtc_rtp_ctrl { 375 struct rtw89_btc_btf_set_report_v1 v1; 376 struct rtw89_btc_btf_set_report_v8 v8; 377 }; 378 379 #define BTF_SET_SLOT_TABLE_VER 1 380 struct rtw89_btc_btf_set_slot_table { 381 u8 fver; 382 u8 tbl_num; 383 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num); 384 } __packed; 385 386 struct rtw89_btc_btf_set_slot_table_v7 { 387 u8 type; 388 u8 ver; 389 u8 len; 390 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX]; 391 } __packed; 392 393 struct rtw89_btc_btf_set_mon_reg_v1 { 394 u8 fver; 395 u8 reg_num; 396 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num); 397 } __packed; 398 399 struct rtw89_btc_btf_set_mon_reg_v7 { 400 u8 type; 401 u8 fver; 402 u8 len; 403 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len); 404 } __packed; 405 406 union rtw89_fbtc_set_mon_reg { 407 struct rtw89_btc_btf_set_mon_reg_v1 v1; 408 struct rtw89_btc_btf_set_mon_reg_v7 v7; 409 } __packed; 410 411 struct _wl_rinfo_now { 412 u8 link_mode; 413 u32 dbcc_2g_phy: 2; 414 }; 415 416 enum btc_btf_set_cx_policy { 417 CXPOLICY_TDMA = 0x0, 418 CXPOLICY_SLOT = 0x1, 419 CXPOLICY_TYPE = 0x2, 420 CXPOLICY_MAX, 421 }; 422 423 enum btc_b2w_scoreboard { 424 BTC_BSCB_ACT = BIT(0), 425 BTC_BSCB_ON = BIT(1), 426 BTC_BSCB_WHQL = BIT(2), 427 BTC_BSCB_BT_S1 = BIT(3), 428 BTC_BSCB_A2DP_ACT = BIT(4), 429 BTC_BSCB_RFK_RUN = BIT(5), 430 BTC_BSCB_RFK_REQ = BIT(6), 431 BTC_BSCB_LPS = BIT(7), 432 BTC_BSCB_BT_LNAB0 = BIT(8), 433 BTC_BSCB_BT_LNAB1 = BIT(10), 434 BTC_BSCB_WLRFK = BIT(11), 435 BTC_BSCB_BT_HILNA = BIT(13), 436 BTC_BSCB_BT_CONNECT = BIT(16), 437 BTC_BSCB_PATCH_CODE = BIT(30), 438 BTC_BSCB_ALL = GENMASK(30, 0), 439 }; 440 441 enum btc_phymap { 442 BTC_PHY_0 = BIT(0), 443 BTC_PHY_1 = BIT(1), 444 BTC_PHY_ALL = BIT(0) | BIT(1), 445 }; 446 447 enum btc_cx_state_map { 448 BTC_WIDLE = 0, 449 BTC_WBUSY_BNOSCAN, 450 BTC_WBUSY_BSCAN, 451 BTC_WSCAN_BNOSCAN, 452 BTC_WSCAN_BSCAN, 453 BTC_WLINKING 454 }; 455 456 enum btc_ant_phase { 457 BTC_ANT_WPOWERON = 0, 458 BTC_ANT_WINIT, 459 BTC_ANT_WONLY, 460 BTC_ANT_WOFF, 461 BTC_ANT_W2G, 462 BTC_ANT_W5G, 463 BTC_ANT_W25G, 464 BTC_ANT_FREERUN, 465 BTC_ANT_WRFK, 466 BTC_ANT_WRFK2, 467 BTC_ANT_BRFK, 468 BTC_ANT_MAX 469 }; 470 471 enum btc_plt { 472 BTC_PLT_NONE = 0, 473 BTC_PLT_LTE_RX = BIT(0), 474 BTC_PLT_GNT_BT_TX = BIT(1), 475 BTC_PLT_GNT_BT_RX = BIT(2), 476 BTC_PLT_GNT_WL = BIT(3), 477 BTC_PLT_BT = BIT(1) | BIT(2), 478 BTC_PLT_ALL = 0xf 479 }; 480 481 enum btc_cx_poicy_main_type { 482 BTC_CXP_OFF = 0, 483 BTC_CXP_OFFB, 484 BTC_CXP_OFFE, 485 BTC_CXP_FIX, 486 BTC_CXP_PFIX, 487 BTC_CXP_AUTO, 488 BTC_CXP_PAUTO, 489 BTC_CXP_AUTO2, 490 BTC_CXP_PAUTO2, 491 BTC_CXP_MANUAL, 492 BTC_CXP_USERDEF0, 493 BTC_CXP_MAIN_MAX 494 }; 495 496 enum btc_cx_poicy_type { 497 /* TDMA off + pri: BT > WL */ 498 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0, 499 500 /* TDMA off + pri: WL > BT */ 501 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1, 502 503 /* TDMA off + pri: BT = WL */ 504 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2, 505 506 /* TDMA off + pri: BT = WL > BT_Lo */ 507 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3, 508 509 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */ 510 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4, 511 512 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 513 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5, 514 515 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 516 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6, 517 518 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */ 519 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7, 520 521 /* TDMA off + pri: BT_Hi > WL > BT_Lo */ 522 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8, 523 524 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */ 525 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9, 526 527 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */ 528 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10, 529 530 /* TDMA off + pri: WL_Hi-Tx = BT */ 531 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11, 532 533 /* TDMA off + pri: WL > BT, Block-BT*/ 534 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12, 535 536 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/ 537 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0, 538 539 /* TDMA off + Ext-Ctrl + pri: default */ 540 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0, 541 542 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 543 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1, 544 545 /* TDMA off + Ext-Ctrl + pri: default */ 546 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2, 547 548 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */ 549 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3, 550 551 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */ 552 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4, 553 554 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */ 555 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5, 556 557 /* TDMA off + Ext-Ctrl + pri: default */ 558 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6, 559 560 /* TDMA Fix slot-0: W1:B1 = 30:30 */ 561 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0, 562 563 /* TDMA Fix slot-1: W1:B1 = 50:50 */ 564 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1, 565 566 /* TDMA Fix slot-2: W1:B1 = 20:30 */ 567 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2, 568 569 /* TDMA Fix slot-3: W1:B1 = 40:10 */ 570 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3, 571 572 /* TDMA Fix slot-4: W1:B1 = 70:10 */ 573 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4, 574 575 /* TDMA Fix slot-5: W1:B1 = 20:60 */ 576 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5, 577 578 /* TDMA Fix slot-6: W1:B1 = 30:60 */ 579 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6, 580 581 /* TDMA Fix slot-7: W1:B1 = 20:80 */ 582 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7, 583 584 /* TDMA Fix slot-8: W1:B1 = user-define */ 585 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8, 586 587 /* TDMA Fix slot-9: W1:B1 = 40:10 */ 588 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9, 589 590 /* TDMA Fix slot-10: W1:B1 = 40:10 */ 591 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10, 592 593 /* TDMA Fix slot-11: W1:B1 = 40:10 */ 594 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11, 595 596 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */ 597 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0, 598 599 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */ 600 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1, 601 602 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */ 603 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2, 604 605 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */ 606 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3, 607 608 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */ 609 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4, 610 611 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */ 612 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5, 613 614 /* PS-TDMA Fix slot-6: W1:B1 = user-define */ 615 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6, 616 617 /* TDMA Auto slot-0: W1:B1 = 50:200 */ 618 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0, 619 620 /* TDMA Auto slot-1: W1:B1 = 60:200 */ 621 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1, 622 623 /* TDMA Auto slot-2: W1:B1 = 20:200 */ 624 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2, 625 626 /* TDMA Auto slot-3: W1:B1 = user-define */ 627 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3, 628 629 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */ 630 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0, 631 632 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */ 633 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1, 634 635 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */ 636 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2, 637 638 /* PS-TDMA Auto slot-3: W1:B1 = user-define */ 639 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3, 640 641 /* TDMA Auto slot2-0: W1:B4 = 30:50 */ 642 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0, 643 644 /* TDMA Auto slot2-1: W1:B4 = 30:70 */ 645 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1, 646 647 /* TDMA Auto slot2-2: W1:B4 = 50:50 */ 648 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2, 649 650 /* TDMA Auto slot2-3: W1:B4 = 60:60 */ 651 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3, 652 653 /* TDMA Auto slot2-4: W1:B4 = 20:80 */ 654 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4, 655 656 /* TDMA Auto slot2-5: W1:B4 = user-define */ 657 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5, 658 659 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */ 660 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0, 661 662 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */ 663 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1, 664 665 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */ 666 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2, 667 668 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */ 669 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3, 670 671 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */ 672 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4, 673 674 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */ 675 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5, 676 677 BTC_CXP_MAX = 0xffff 678 }; 679 680 enum btc_wl_rfk_result { 681 BTC_WRFK_REJECT = 0, 682 BTC_WRFK_ALLOW = 1, 683 }; 684 685 enum btc_coex_info_map_en { 686 BTC_COEX_INFO_CX = BIT(0), 687 BTC_COEX_INFO_WL = BIT(1), 688 BTC_COEX_INFO_BT = BIT(2), 689 BTC_COEX_INFO_DM = BIT(3), 690 BTC_COEX_INFO_MREG = BIT(4), 691 BTC_COEX_INFO_SUMMARY = BIT(5), 692 BTC_COEX_INFO_ALL = GENMASK(7, 0), 693 }; 694 695 #define BTC_CXP_MASK GENMASK(15, 8) 696 697 enum btc_w2b_scoreboard { 698 BTC_WSCB_ACTIVE = BIT(0), 699 BTC_WSCB_ON = BIT(1), 700 BTC_WSCB_SCAN = BIT(2), 701 BTC_WSCB_UNDERTEST = BIT(3), 702 BTC_WSCB_RXGAIN = BIT(4), 703 BTC_WSCB_WLBUSY = BIT(7), 704 BTC_WSCB_EXTFEM = BIT(8), 705 BTC_WSCB_TDMA = BIT(9), 706 BTC_WSCB_FIX2M = BIT(10), 707 BTC_WSCB_WLRFK = BIT(11), 708 BTC_WSCB_RXSCAN_PRI = BIT(12), 709 BTC_WSCB_BT_HILNA = BIT(13), 710 BTC_WSCB_BTLOG = BIT(14), 711 BTC_WSCB_ALL = GENMASK(23, 0), 712 }; 713 714 enum btc_wl_link_mode { 715 BTC_WLINK_NOLINK = 0x0, 716 BTC_WLINK_2G_STA, 717 BTC_WLINK_2G_AP, 718 BTC_WLINK_2G_GO, 719 BTC_WLINK_2G_GC, 720 BTC_WLINK_2G_SCC, 721 BTC_WLINK_2G_MCC, 722 BTC_WLINK_25G_MCC, 723 BTC_WLINK_25G_DBCC, 724 BTC_WLINK_5G, 725 BTC_WLINK_2G_NAN, 726 BTC_WLINK_OTHER, 727 BTC_WLINK_MAX 728 }; 729 730 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e 731 732 static const char *id_to_linkmode(u8 id) 733 { 734 switch (id) { 735 CASE_BTC_WL_LINK_MODE(NOLINK); 736 CASE_BTC_WL_LINK_MODE(2G_STA); 737 CASE_BTC_WL_LINK_MODE(2G_AP); 738 CASE_BTC_WL_LINK_MODE(2G_GO); 739 CASE_BTC_WL_LINK_MODE(2G_GC); 740 CASE_BTC_WL_LINK_MODE(2G_SCC); 741 CASE_BTC_WL_LINK_MODE(2G_MCC); 742 CASE_BTC_WL_LINK_MODE(25G_MCC); 743 CASE_BTC_WL_LINK_MODE(25G_DBCC); 744 CASE_BTC_WL_LINK_MODE(5G); 745 CASE_BTC_WL_LINK_MODE(OTHER); 746 default: 747 return "unknown"; 748 } 749 } 750 751 enum btc_wl_mrole_type { 752 BTC_WLMROLE_NONE = 0x0, 753 BTC_WLMROLE_STA_GC, 754 BTC_WLMROLE_STA_GC_NOA, 755 BTC_WLMROLE_STA_GO, 756 BTC_WLMROLE_STA_GO_NOA, 757 BTC_WLMROLE_STA_STA, 758 BTC_WLMROLE_MAX 759 }; 760 761 enum btc_bt_hid_type { 762 BTC_HID_218 = BIT(0), 763 BTC_HID_418 = BIT(1), 764 BTC_HID_BLE = BIT(2), 765 BTC_HID_RCU = BIT(3), 766 BTC_HID_RCU_VOICE = BIT(4), 767 BTC_HID_OTHER_LEGACY = BIT(5) 768 }; 769 770 enum btc_reset_module { 771 BTC_RESET_CX = BIT(0), 772 BTC_RESET_DM = BIT(1), 773 BTC_RESET_CTRL = BIT(2), 774 BTC_RESET_CXDM = BIT(0) | BIT(1), 775 BTC_RESET_BTINFO = BIT(3), 776 BTC_RESET_MDINFO = BIT(4), 777 BTC_RESET_ALL = GENMASK(7, 0), 778 }; 779 780 enum btc_gnt_state { 781 BTC_GNT_HW = 0, 782 BTC_GNT_SW_LO, 783 BTC_GNT_SW_HI, 784 BTC_GNT_MAX 785 }; 786 787 enum btc_ctr_path { 788 BTC_CTRL_BY_BT = 0, 789 BTC_CTRL_BY_WL 790 }; 791 792 enum btc_wlact_state { 793 BTC_WLACT_HW = 0, 794 BTC_WLACT_SW_LO, 795 BTC_WLACT_SW_HI, 796 BTC_WLACT_MAX, 797 }; 798 799 enum btc_wl_max_tx_time { 800 BTC_MAX_TX_TIME_L1 = 500, 801 BTC_MAX_TX_TIME_L2 = 1000, 802 BTC_MAX_TX_TIME_L3 = 2000, 803 BTC_MAX_TX_TIME_DEF = 5280 804 }; 805 806 enum btc_wl_max_tx_retry { 807 BTC_MAX_TX_RETRY_L1 = 7, 808 BTC_MAX_TX_RETRY_L2 = 15, 809 BTC_MAX_TX_RETRY_DEF = 31, 810 }; 811 812 enum btc_reason_and_action { 813 BTC_RSN_NONE, 814 BTC_RSN_NTFY_INIT, 815 BTC_RSN_NTFY_SWBAND, 816 BTC_RSN_NTFY_WL_STA, 817 BTC_RSN_NTFY_RADIO_STATE, 818 BTC_RSN_UPDATE_BT_SCBD, 819 BTC_RSN_NTFY_WL_RFK, 820 BTC_RSN_UPDATE_BT_INFO, 821 BTC_RSN_NTFY_SCAN_START, 822 BTC_RSN_NTFY_SCAN_FINISH, 823 BTC_RSN_NTFY_SPECIFIC_PACKET, 824 BTC_RSN_NTFY_POWEROFF, 825 BTC_RSN_NTFY_ROLE_INFO, 826 BTC_RSN_CMD_SET_COEX, 827 BTC_RSN_ACT1_WORK, 828 BTC_RSN_BT_DEVINFO_WORK, 829 BTC_RSN_RFK_CHK_WORK, 830 BTC_RSN_NUM, 831 BTC_ACT_NONE = 100, 832 BTC_ACT_WL_ONLY, 833 BTC_ACT_WL_5G, 834 BTC_ACT_WL_OTHER, 835 BTC_ACT_WL_IDLE, 836 BTC_ACT_WL_NC, 837 BTC_ACT_WL_RFK, 838 BTC_ACT_WL_INIT, 839 BTC_ACT_WL_OFF, 840 BTC_ACT_FREERUN, 841 BTC_ACT_BT_WHQL, 842 BTC_ACT_BT_RFK, 843 BTC_ACT_BT_OFF, 844 BTC_ACT_BT_IDLE, 845 BTC_ACT_BT_HFP, 846 BTC_ACT_BT_HID, 847 BTC_ACT_BT_A2DP, 848 BTC_ACT_BT_A2DPSINK, 849 BTC_ACT_BT_PAN, 850 BTC_ACT_BT_A2DP_HID, 851 BTC_ACT_BT_A2DP_PAN, 852 BTC_ACT_BT_PAN_HID, 853 BTC_ACT_BT_A2DP_PAN_HID, 854 BTC_ACT_WL_25G_MCC, 855 BTC_ACT_WL_2G_MCC, 856 BTC_ACT_WL_2G_SCC, 857 BTC_ACT_WL_2G_AP, 858 BTC_ACT_WL_2G_GO, 859 BTC_ACT_WL_2G_GC, 860 BTC_ACT_WL_2G_NAN, 861 BTC_ACT_LAST, 862 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE, 863 BTC_ACT_EXT_BIT = BIT(14), 864 BTC_POLICY_EXT_BIT = BIT(15), 865 }; 866 867 #define BTC_FREERUN_ANTISO_MIN 30 868 #define BTC_TDMA_BTHID_MAX 2 869 #define BTC_BLINK_NOCONNECT 0 870 #define BTC_B1_MAX 250 /* unit ms */ 871 872 static void _run_coex(struct rtw89_dev *rtwdev, 873 enum btc_reason_and_action reason); 874 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state); 875 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update); 876 877 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, 878 void *param, u16 len) 879 { 880 struct rtw89_btc *btc = &rtwdev->btc; 881 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 882 struct rtw89_btc_cx *cx = &btc->cx; 883 struct rtw89_btc_wl_info *wl = &cx->wl; 884 struct rtw89_btc_dm *dm = &btc->dm; 885 int ret; 886 887 if (len > BTC_H2C_MAXLEN || len == 0) { 888 btc->fwinfo.cnt_h2c_fail++; 889 dm->error.map.h2c_buffer_over = true; 890 return -EINVAL; 891 } else if (!wl->status.map.init_ok) { 892 rtw89_debug(rtwdev, RTW89_DBG_BTC, 893 "[BTC], %s(): return by btc not init!!\n", __func__); 894 pfwinfo->cnt_h2c_fail++; 895 return -EINVAL; 896 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF && 897 wl->status.map.rf_off == BTC_LPS_RF_OFF) || 898 (wl->status.map.lps_pre == BTC_LPS_RF_OFF && 899 wl->status.map.lps == BTC_LPS_RF_OFF)) { 900 rtw89_debug(rtwdev, RTW89_DBG_BTC, 901 "[BTC], %s(): return by wl off!!\n", __func__); 902 pfwinfo->cnt_h2c_fail++; 903 return -EINVAL; 904 } 905 906 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len, 907 false, true); 908 if (ret) 909 pfwinfo->cnt_h2c_fail++; 910 else 911 pfwinfo->cnt_h2c++; 912 913 return ret; 914 } 915 916 #define BTC_BT_DEF_BR_TX_PWR 4 917 #define BTC_BT_DEF_LE_TX_PWR 4 918 919 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type) 920 { 921 struct rtw89_btc *btc = &rtwdev->btc; 922 const struct rtw89_btc_ver *ver = btc->ver; 923 struct rtw89_btc_cx *cx = &btc->cx; 924 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 925 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 926 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 927 struct rtw89_btc_wl_link_info *wl_linfo; 928 u8 i; 929 930 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 931 932 if (type & BTC_RESET_CX) 933 memset(cx, 0, sizeof(*cx)); 934 935 if (type & BTC_RESET_BTINFO) /* only for BT enable */ 936 memset(bt, 0, sizeof(*bt)); 937 938 if (type & BTC_RESET_CTRL) { 939 memset(&btc->ctrl, 0, sizeof(btc->ctrl)); 940 btc->manual_ctrl = false; 941 if (ver->fcxctrl != 7) 942 btc->ctrl.ctrl.trace_step = FCXDEF_STEP; 943 } 944 945 /* Init Coex variables that are not zero */ 946 if (type & BTC_RESET_DM) { 947 memset(&btc->dm, 0, sizeof(btc->dm)); 948 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state)); 949 for (i = 0; i < RTW89_PORT_NUM; i++) { 950 if (btc->ver->fwlrole == 8) 951 wl_linfo = &wl->rlink_info[i][0]; 952 else 953 wl_linfo = &wl->link_info[i]; 954 memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state)); 955 } 956 957 /* set the slot_now table to original */ 958 btc->dm.tdma_now = t_def[CXTD_OFF]; 959 btc->dm.tdma = t_def[CXTD_OFF]; 960 if (ver->fcxslots >= 7) { 961 for (i = 0; i < ARRAY_SIZE(s_def); i++) { 962 btc->dm.slot.v7[i].dur = s_def[i].dur; 963 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype; 964 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl; 965 } 966 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7, 967 sizeof(btc->dm.slot_now.v7)); 968 } else { 969 memcpy(&btc->dm.slot_now.v1, s_def, 970 sizeof(btc->dm.slot_now.v1)); 971 memcpy(&btc->dm.slot.v1, s_def, 972 sizeof(btc->dm.slot.v1)); 973 } 974 975 btc->policy_len = 0; 976 btc->bt_req_len = 0; 977 978 btc->dm.coex_info_map = BTC_COEX_INFO_ALL; 979 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF; 980 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF; 981 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND; 982 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND; 983 } 984 985 if (type & BTC_RESET_MDINFO) 986 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo)); 987 988 bt->link_info.bt_txpwr_desc.br_dbm = BTC_BT_DEF_BR_TX_PWR; 989 bt->link_info.bt_txpwr_desc.le_dbm = BTC_BT_DEF_LE_TX_PWR; 990 } 991 992 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target) 993 { 994 const struct rtw89_chip_info *chip = rtwdev->chip; 995 u8 i; 996 997 for (i = 0; i < mreg_num; i++) 998 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type && 999 le32_to_cpu(chip->mon_reg[i].offset) == target) { 1000 return i; 1001 } 1002 return BTC_REG_NOTFOUND; 1003 } 1004 1005 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val) 1006 { 1007 struct rtw89_btc *btc = &rtwdev->btc; 1008 const struct rtw89_btc_ver *ver = btc->ver; 1009 union rtw89_btc_module_info *md = &btc->mdinfo; 1010 union rtw89_btc_fbtc_mreg_val *pmreg; 1011 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1; 1012 u32 reg_val; 1013 u8 idx, switch_type; 1014 1015 if (ver->fcxinit == 7) 1016 switch_type = md->md_v7.switch_type; 1017 else 1018 switch_type = md->md.switch_type; 1019 1020 if (btc->btg_pos == RF_PATH_A) 1021 pre_agc_addr = R_BTC_BB_PRE_AGC_S0; 1022 1023 switch (type) { 1024 case BTC_CSTATUS_TXDIV_POS: 1025 if (switch_type == BTC_SWITCH_INTERNAL) 1026 *val = BTC_ANT_DIV_MAIN; 1027 break; 1028 case BTC_CSTATUS_RXDIV_POS: 1029 if (switch_type == BTC_SWITCH_INTERNAL) 1030 *val = BTC_ANT_DIV_MAIN; 1031 break; 1032 case BTC_CSTATUS_BB_GNT_MUX: 1033 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX); 1034 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1035 break; 1036 case BTC_CSTATUS_BB_GNT_MUX_MON: 1037 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 1038 return; 1039 1040 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 1041 if (ver->fcxmreg == 1) { 1042 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 1043 REG_BB, R_BTC_BB_BTG_RX); 1044 if (idx == BTC_REG_NOTFOUND) { 1045 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1046 } else { 1047 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]); 1048 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1049 } 1050 } else if (ver->fcxmreg == 2) { 1051 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 1052 REG_BB, R_BTC_BB_BTG_RX); 1053 if (idx == BTC_REG_NOTFOUND) { 1054 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND; 1055 } else { 1056 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]); 1057 *val = !(reg_val & B_BTC_BB_GNT_MUX); 1058 } 1059 } 1060 break; 1061 case BTC_CSTATUS_BB_PRE_AGC: 1062 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr); 1063 reg_val &= B_BTC_BB_PRE_AGC_MASK; 1064 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1065 break; 1066 case BTC_CSTATUS_BB_PRE_AGC_MON: 1067 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid) 1068 return; 1069 1070 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo; 1071 if (ver->fcxmreg == 1) { 1072 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num, 1073 REG_BB, pre_agc_addr); 1074 if (idx == BTC_REG_NOTFOUND) { 1075 *val = BTC_PREAGC_NOTFOUND; 1076 } else { 1077 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) & 1078 B_BTC_BB_PRE_AGC_MASK; 1079 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1080 } 1081 } else if (ver->fcxmreg == 2) { 1082 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num, 1083 REG_BB, pre_agc_addr); 1084 if (idx == BTC_REG_NOTFOUND) { 1085 *val = BTC_PREAGC_NOTFOUND; 1086 } else { 1087 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) & 1088 B_BTC_BB_PRE_AGC_MASK; 1089 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL); 1090 } 1091 } 1092 break; 1093 default: 1094 break; 1095 } 1096 } 1097 1098 #define BTC_RPT_HDR_SIZE 3 1099 #define BTC_CHK_WLSLOT_DRIFT_MAX 15 1100 #define BTC_CHK_BTSLOT_DRIFT_MAX 15 1101 #define BTC_CHK_HANG_MAX 3 1102 1103 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt) 1104 { 1105 struct rtw89_btc *btc = &rtwdev->btc; 1106 struct rtw89_btc_cx *cx = &btc->cx; 1107 struct rtw89_btc_bt_info *bt = &cx->bt; 1108 struct rtw89_btc_wl_info *wl = &cx->wl; 1109 struct rtw89_btc_dm *dm = &btc->dm; 1110 1111 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1112 "[BTC], %s(): type:%d cnt:%d\n", 1113 __func__, type, cnt); 1114 1115 switch (type) { 1116 case BTC_DCNT_WL_FW_VER_MATCH: 1117 if ((wl->ver_info.fw_coex & 0xffff0000) != 1118 rtwdev->chip->wlcx_desired) { 1119 wl->fw_ver_mismatch = true; 1120 dm->error.map.wl_ver_mismatch = true; 1121 } else { 1122 wl->fw_ver_mismatch = false; 1123 dm->error.map.wl_ver_mismatch = false; 1124 } 1125 break; 1126 case BTC_DCNT_RPT_HANG: 1127 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map) 1128 dm->cnt_dm[BTC_DCNT_RPT_HANG]++; 1129 else 1130 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0; 1131 1132 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX) 1133 dm->error.map.wl_fw_hang = true; 1134 else 1135 dm->error.map.wl_fw_hang = false; 1136 1137 dm->cnt_dm[BTC_DCNT_RPT] = cnt; 1138 break; 1139 case BTC_DCNT_CYCLE_HANG: 1140 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt && 1141 (dm->tdma_now.type != CXTDMA_OFF || 1142 dm->tdma_now.ext_ctrl == CXECTL_EXT)) 1143 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++; 1144 else 1145 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0; 1146 1147 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX) 1148 dm->error.map.cycle_hang = true; 1149 else 1150 dm->error.map.cycle_hang = false; 1151 1152 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt; 1153 break; 1154 case BTC_DCNT_W1_HANG: 1155 if (dm->cnt_dm[BTC_DCNT_W1] == cnt && 1156 dm->tdma_now.type != CXTDMA_OFF) 1157 dm->cnt_dm[BTC_DCNT_W1_HANG]++; 1158 else 1159 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0; 1160 1161 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX) 1162 dm->error.map.w1_hang = true; 1163 else 1164 dm->error.map.w1_hang = false; 1165 1166 dm->cnt_dm[BTC_DCNT_W1] = cnt; 1167 break; 1168 case BTC_DCNT_B1_HANG: 1169 if (dm->cnt_dm[BTC_DCNT_B1] == cnt && 1170 dm->tdma_now.type != CXTDMA_OFF) 1171 dm->cnt_dm[BTC_DCNT_B1_HANG]++; 1172 else 1173 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0; 1174 1175 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX) 1176 dm->error.map.b1_hang = true; 1177 else 1178 dm->error.map.b1_hang = false; 1179 1180 dm->cnt_dm[BTC_DCNT_B1] = cnt; 1181 break; 1182 case BTC_DCNT_E2G_HANG: 1183 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt && 1184 dm->tdma_now.ext_ctrl == CXECTL_EXT) 1185 dm->cnt_dm[BTC_DCNT_E2G_HANG]++; 1186 else 1187 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0; 1188 1189 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX) 1190 dm->error.map.wl_e2g_hang = true; 1191 else 1192 dm->error.map.wl_e2g_hang = false; 1193 1194 dm->cnt_dm[BTC_DCNT_E2G] = cnt; 1195 break; 1196 case BTC_DCNT_TDMA_NONSYNC: 1197 if (cnt != 0) /* if tdma not sync between drv/fw */ 1198 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++; 1199 else 1200 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0; 1201 1202 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX) 1203 dm->error.map.tdma_no_sync = true; 1204 else 1205 dm->error.map.tdma_no_sync = false; 1206 break; 1207 case BTC_DCNT_SLOT_NONSYNC: 1208 if (cnt != 0) /* if slot not sync between drv/fw */ 1209 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++; 1210 else 1211 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0; 1212 1213 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX) 1214 dm->error.map.slot_no_sync = true; 1215 else 1216 dm->error.map.slot_no_sync = false; 1217 break; 1218 case BTC_DCNT_BTTX_HANG: 1219 cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX]; 1220 1221 if (cnt == 0 && bt->link_info.slave_role) 1222 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++; 1223 else 1224 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0; 1225 1226 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX) 1227 dm->error.map.bt_tx_hang = true; 1228 else 1229 dm->error.map.bt_tx_hang = false; 1230 break; 1231 case BTC_DCNT_BTCNT_HANG: 1232 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] + 1233 cx->cnt_bt[BTC_BCNT_HIPRI_TX] + 1234 cx->cnt_bt[BTC_BCNT_LOPRI_RX] + 1235 cx->cnt_bt[BTC_BCNT_LOPRI_TX]; 1236 1237 if (cnt == 0) 1238 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++; 1239 else 1240 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 1241 1242 if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX && 1243 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] && 1244 !bt->enable.now)) 1245 _update_bt_scbd(rtwdev, false); 1246 break; 1247 case BTC_DCNT_WL_SLOT_DRIFT: 1248 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX) 1249 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++; 1250 else 1251 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0; 1252 1253 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1254 dm->error.map.wl_slot_drift = true; 1255 else 1256 dm->error.map.wl_slot_drift = false; 1257 break; 1258 case BTC_DCNT_BT_SLOT_DRIFT: 1259 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX) 1260 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++; 1261 else 1262 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0; 1263 1264 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX) 1265 dm->error.map.bt_slot_drift = true; 1266 else 1267 dm->error.map.bt_slot_drift = false; 1268 1269 break; 1270 } 1271 } 1272 1273 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo) 1274 { 1275 struct rtw89_btc *btc = &rtwdev->btc; 1276 const struct rtw89_btc_ver *ver = btc->ver; 1277 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 1278 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 1279 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc; 1280 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo; 1281 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL; 1282 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL; 1283 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL; 1284 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL; 1285 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1; 1286 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2; 1287 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7; 1288 bool scan_update = true; 1289 int i; 1290 1291 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1292 "[BTC], %s(): rpt_type:%d\n", 1293 __func__, rpt_type); 1294 1295 switch (rpt_type) { 1296 case BTC_RPT_TYPE_BT_VER: 1297 if (ver->fcxbtver == 7) { 1298 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo; 1299 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver); 1300 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver, 1301 GENMASK(7, 0)); 1302 bt->feature = le32_to_cpu(pver->v7.feature); 1303 } else { 1304 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo; 1305 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver); 1306 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver, 1307 GENMASK(7, 0)); 1308 bt->feature = le32_to_cpu(pver->v1.feature); 1309 } 1310 break; 1311 case BTC_RPT_TYPE_BT_SCAN: 1312 if (ver->fcxbtscan == 1) { 1313 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo; 1314 for (i = 0; i < BTC_SCAN_MAX1; i++) { 1315 bt->scan_info_v1[i] = pscan_v1->scan[i]; 1316 if (bt->scan_info_v1[i].win == 0 && 1317 bt->scan_info_v1[i].intvl == 0) 1318 scan_update = false; 1319 } 1320 } else if (ver->fcxbtscan == 2) { 1321 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo; 1322 for (i = 0; i < CXSCAN_MAX; i++) { 1323 bt->scan_info_v2[i] = pscan_v2->para[i]; 1324 if ((pscan_v2->type & BIT(i)) && 1325 pscan_v2->para[i].win == 0 && 1326 pscan_v2->para[i].intvl == 0) 1327 scan_update = false; 1328 } 1329 } else if (ver->fcxbtscan == 7) { 1330 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo; 1331 for (i = 0; i < CXSCAN_MAX; i++) { 1332 bt->scan_info_v2[i] = pscan_v7->para[i]; 1333 if ((pscan_v7->type & BIT(i)) && 1334 pscan_v7->para[i].win == 0 && 1335 pscan_v7->para[i].intvl == 0) 1336 scan_update = false; 1337 } 1338 } 1339 if (scan_update) 1340 bt->scan_info_update = 1; 1341 break; 1342 case BTC_RPT_TYPE_BT_AFH: 1343 if (ver->fcxbtafh == 2) { 1344 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo; 1345 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1346 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4); 1347 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4); 1348 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2); 1349 } 1350 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) { 1351 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4); 1352 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1); 1353 } 1354 } else if (ver->fcxbtafh == 7) { 1355 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo; 1356 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) { 1357 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4); 1358 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4); 1359 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2); 1360 } 1361 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) { 1362 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4); 1363 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1); 1364 } 1365 } else if (ver->fcxbtafh == 1) { 1366 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo; 1367 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4); 1368 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4); 1369 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2); 1370 } 1371 break; 1372 case BTC_RPT_TYPE_BT_DEVICE: 1373 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo; 1374 a2dp->device_name = le32_to_cpu(pdev->dev_name); 1375 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id); 1376 a2dp->flush_time = le32_to_cpu(pdev->flush_time); 1377 break; 1378 default: 1379 break; 1380 } 1381 } 1382 1383 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index) 1384 { 1385 struct rtw89_btc *btc = &rtwdev->btc; 1386 const struct rtw89_btc_ver *ver = btc->ver; 1387 1388 if (ver->fwevntrptl == 1) 1389 return; 1390 1391 if (*index <= __BTC_RPT_TYPE_V0_SAME) 1392 return; 1393 else if (*index <= __BTC_RPT_TYPE_V0_MAX) 1394 (*index)++; 1395 else 1396 *index = BTC_RPT_TYPE_MAX; 1397 } 1398 1399 #define BTC_LEAK_AP_TH 10 1400 #define BTC_CYSTA_CHK_PERIOD 100 1401 1402 struct rtw89_btc_prpt { 1403 u8 type; 1404 __le16 len; 1405 u8 content[]; 1406 } __packed; 1407 1408 static u32 _chk_btc_report(struct rtw89_dev *rtwdev, 1409 struct rtw89_btc_btf_fwinfo *pfwinfo, 1410 u8 *prptbuf, u32 index) 1411 { 1412 struct rtw89_btc *btc = &rtwdev->btc; 1413 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; 1414 const struct rtw89_btc_ver *ver = btc->ver; 1415 struct rtw89_btc_dm *dm = &btc->dm; 1416 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 1417 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 1418 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 1419 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL; 1420 union rtw89_btc_fbtc_cysta_info *pcysta = NULL; 1421 struct rtw89_btc_prpt *btc_prpt = NULL; 1422 void *rpt_content = NULL, *pfinfo = NULL; 1423 u8 rpt_type = 0; 1424 u16 wl_slot_set = 0, wl_slot_real = 0, val16; 1425 u32 trace_step = 0, rpt_len = 0, diff_t = 0; 1426 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr; 1427 u8 i, val = 0, val1, val2; 1428 1429 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1430 "[BTC], %s(): index:%d\n", 1431 __func__, index); 1432 1433 if (!prptbuf) { 1434 pfwinfo->err[BTFRE_INVALID_INPUT]++; 1435 return 0; 1436 } 1437 1438 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index]; 1439 rpt_type = btc_prpt->type; 1440 rpt_len = le16_to_cpu(btc_prpt->len); 1441 rpt_content = btc_prpt->content; 1442 1443 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1444 "[BTC], %s(): rpt_type:%d\n", 1445 __func__, rpt_type); 1446 1447 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type); 1448 1449 switch (rpt_type) { 1450 case BTC_RPT_TYPE_CTRL: 1451 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 1452 prpt = &pfwinfo->rpt_ctrl.finfo; 1453 if (ver->fcxbtcrpt == 1) { 1454 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1; 1455 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1); 1456 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver; 1457 } else if (ver->fcxbtcrpt == 4) { 1458 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4; 1459 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4); 1460 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver; 1461 } else if (ver->fcxbtcrpt == 5) { 1462 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5; 1463 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5); 1464 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver; 1465 } else if (ver->fcxbtcrpt == 105) { 1466 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105; 1467 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105); 1468 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver; 1469 pcinfo->req_fver = 5; 1470 break; 1471 } else if (ver->fcxbtcrpt == 8) { 1472 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8; 1473 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8); 1474 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver; 1475 } else if (ver->fcxbtcrpt == 7) { 1476 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7; 1477 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7); 1478 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver; 1479 } else { 1480 goto err; 1481 } 1482 pcinfo->req_fver = ver->fcxbtcrpt; 1483 break; 1484 case BTC_RPT_TYPE_TDMA: 1485 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 1486 if (ver->fcxtdma == 1) { 1487 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 1488 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1); 1489 fwsubver->fcxtdma = 0; 1490 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) { 1491 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3; 1492 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3); 1493 fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver; 1494 } else { 1495 goto err; 1496 } 1497 pcinfo->req_fver = ver->fcxtdma; 1498 break; 1499 case BTC_RPT_TYPE_SLOT: 1500 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo; 1501 if (ver->fcxslots == 1) { 1502 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1; 1503 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1); 1504 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver; 1505 } else if (ver->fcxslots == 7) { 1506 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7; 1507 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7); 1508 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver; 1509 } else { 1510 goto err; 1511 } 1512 pcinfo->req_fver = ver->fcxslots; 1513 break; 1514 case BTC_RPT_TYPE_CYSTA: 1515 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 1516 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 1517 if (ver->fcxcysta == 2) { 1518 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 1519 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 1520 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2); 1521 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver; 1522 } else if (ver->fcxcysta == 3) { 1523 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 1524 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 1525 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3); 1526 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver; 1527 } else if (ver->fcxcysta == 4) { 1528 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 1529 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 1530 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4); 1531 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver; 1532 } else if (ver->fcxcysta == 5) { 1533 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 1534 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 1535 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5); 1536 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver; 1537 } else if (ver->fcxcysta == 7) { 1538 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 1539 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 1540 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7); 1541 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver; 1542 } else { 1543 goto err; 1544 } 1545 pcinfo->req_fver = ver->fcxcysta; 1546 break; 1547 case BTC_RPT_TYPE_STEP: 1548 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 1549 if (ver->fcxctrl != 7) 1550 trace_step = btc->ctrl.ctrl.trace_step; 1551 1552 if (ver->fcxstep == 2) { 1553 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2; 1554 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) * 1555 trace_step + 1556 offsetof(struct rtw89_btc_fbtc_steps_v2, step); 1557 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver; 1558 } else if (ver->fcxstep == 3) { 1559 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3; 1560 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) * 1561 trace_step + 1562 offsetof(struct rtw89_btc_fbtc_steps_v3, step); 1563 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver; 1564 } else { 1565 goto err; 1566 } 1567 pcinfo->req_fver = ver->fcxstep; 1568 break; 1569 case BTC_RPT_TYPE_NULLSTA: 1570 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 1571 if (ver->fcxnullsta == 1) { 1572 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1; 1573 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1); 1574 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver; 1575 } else if (ver->fcxnullsta == 2) { 1576 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2; 1577 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2); 1578 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver; 1579 } else if (ver->fcxnullsta == 7) { 1580 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7; 1581 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7); 1582 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver; 1583 } else { 1584 goto err; 1585 } 1586 pcinfo->req_fver = ver->fcxnullsta; 1587 break; 1588 case BTC_RPT_TYPE_MREG: 1589 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 1590 if (ver->fcxmreg == 1) { 1591 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 1592 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1); 1593 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver; 1594 } else if (ver->fcxmreg == 2) { 1595 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 1596 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2); 1597 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver; 1598 } else if (ver->fcxmreg == 7) { 1599 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 1600 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7); 1601 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver; 1602 } else { 1603 goto err; 1604 } 1605 pcinfo->req_fver = ver->fcxmreg; 1606 break; 1607 case BTC_RPT_TYPE_GPIO_DBG: 1608 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 1609 if (ver->fcxgpiodbg == 7) { 1610 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7; 1611 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7); 1612 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver; 1613 } else { 1614 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1; 1615 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1); 1616 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver; 1617 } 1618 pcinfo->req_fver = ver->fcxgpiodbg; 1619 break; 1620 case BTC_RPT_TYPE_BT_VER: 1621 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo; 1622 if (ver->fcxbtver == 1) { 1623 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1; 1624 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1); 1625 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver; 1626 } else if (ver->fcxbtver == 7) { 1627 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7; 1628 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7); 1629 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver; 1630 } 1631 pcinfo->req_fver = ver->fcxbtver; 1632 break; 1633 case BTC_RPT_TYPE_BT_SCAN: 1634 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo; 1635 if (ver->fcxbtscan == 1) { 1636 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1; 1637 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1); 1638 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver; 1639 } else if (ver->fcxbtscan == 2) { 1640 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2; 1641 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2); 1642 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver; 1643 } else if (ver->fcxbtscan == 7) { 1644 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7; 1645 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7); 1646 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver; 1647 } else { 1648 goto err; 1649 } 1650 pcinfo->req_fver = ver->fcxbtscan; 1651 break; 1652 case BTC_RPT_TYPE_BT_AFH: 1653 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo; 1654 if (ver->fcxbtafh == 1) { 1655 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1; 1656 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1); 1657 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver; 1658 } else if (ver->fcxbtafh == 2) { 1659 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2; 1660 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2); 1661 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver; 1662 } else if (ver->fcxbtafh == 7) { 1663 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7; 1664 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7); 1665 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver; 1666 } else { 1667 goto err; 1668 } 1669 pcinfo->req_fver = ver->fcxbtafh; 1670 break; 1671 case BTC_RPT_TYPE_BT_DEVICE: 1672 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo; 1673 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo; 1674 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo); 1675 fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver; 1676 pcinfo->req_fver = ver->fcxbtdevinfo; 1677 break; 1678 default: 1679 pfwinfo->err[BTFRE_UNDEF_TYPE]++; 1680 return 0; 1681 } 1682 1683 pcinfo->rx_len = rpt_len; 1684 pcinfo->rx_cnt++; 1685 1686 if (rpt_len != pcinfo->req_len) { 1687 if (rpt_type < BTC_RPT_TYPE_MAX) 1688 pfwinfo->len_mismch |= (0x1 << rpt_type); 1689 else 1690 pfwinfo->len_mismch |= BIT(31); 1691 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1692 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n", 1693 __func__, rpt_type, rpt_len, pcinfo->req_len); 1694 1695 pcinfo->valid = 0; 1696 return 0; 1697 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) { 1698 pfwinfo->err[BTFRE_EXCEPTION]++; 1699 pcinfo->valid = 0; 1700 return 0; 1701 } 1702 1703 memcpy(pfinfo, rpt_content, pcinfo->req_len); 1704 pcinfo->valid = 1; 1705 1706 switch (rpt_type) { 1707 case BTC_RPT_TYPE_CTRL: 1708 if (ver->fcxbtcrpt == 1) { 1709 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1; 1710 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable; 1711 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver; 1712 wl->ver_info.fw = prpt->v1.wl_fw_ver; 1713 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload; 1714 1715 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1716 pfwinfo->event[BTF_EVNT_RPT]); 1717 1718 /* To avoid I/O if WL LPS or power-off */ 1719 if (wl->status.map.lps != BTC_LPS_RF_OFF && 1720 !wl->status.map.rf_off) { 1721 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev); 1722 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1723 1724 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1725 rtw89_mac_get_plt_cnt(rtwdev, 1726 RTW89_MAC_0); 1727 } 1728 } else if (ver->fcxbtcrpt == 4) { 1729 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4; 1730 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en); 1731 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver); 1732 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver); 1733 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload); 1734 1735 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 1736 memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i], 1737 sizeof(dm->gnt.band[i])); 1738 1739 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1740 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]); 1741 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1742 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]); 1743 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1744 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]); 1745 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1746 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]); 1747 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1748 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]); 1749 1750 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1751 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1752 pfwinfo->event[BTF_EVNT_RPT]); 1753 1754 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 1755 bt->rfk_info.map.timeout = 1; 1756 else 1757 bt->rfk_info.map.timeout = 0; 1758 1759 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1760 } else if (ver->fcxbtcrpt == 5) { 1761 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5; 1762 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en); 1763 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver); 1764 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver); 1765 dm->wl_fw_cx_offload = 0; 1766 1767 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 1768 memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0], 1769 sizeof(dm->gnt.band[i])); 1770 1771 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1772 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]); 1773 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1774 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]); 1775 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1776 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]); 1777 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1778 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]); 1779 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1780 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]); 1781 1782 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1783 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1784 pfwinfo->event[BTF_EVNT_RPT]); 1785 1786 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1787 } else if (ver->fcxbtcrpt == 105) { 1788 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105; 1789 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en); 1790 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver); 1791 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver); 1792 dm->wl_fw_cx_offload = 0; 1793 1794 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 1795 memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0], 1796 sizeof(dm->gnt.band[i])); 1797 1798 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1799 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]); 1800 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1801 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]); 1802 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1803 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]); 1804 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1805 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]); 1806 btc->cx.cnt_bt[BTC_BCNT_POLUT] = 1807 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1808 1809 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1810 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, 1811 pfwinfo->event[BTF_EVNT_RPT]); 1812 1813 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout; 1814 } else if (ver->fcxbtcrpt == 7) { 1815 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7; 1816 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en); 1817 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver); 1818 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver); 1819 1820 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 1821 memcpy(&dm->gnt.band[i], &prpt->v7.gnt_val[i][0], 1822 sizeof(dm->gnt.band[i])); 1823 1824 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1825 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]); 1826 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1827 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]); 1828 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1829 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]); 1830 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1831 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]); 1832 1833 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1834 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]) 1835 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */ 1836 1837 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1; 1838 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] = 1839 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1840 1841 val1 = pfwinfo->event[BTF_EVNT_RPT]; 1842 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1843 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 1844 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 1845 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 1846 } else if (ver->fcxbtcrpt == 8) { 1847 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8; 1848 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en); 1849 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver); 1850 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver); 1851 1852 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) 1853 memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0], 1854 sizeof(dm->gnt.band[i])); 1855 1856 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = 1857 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]); 1858 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = 1859 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]); 1860 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = 1861 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]); 1862 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = 1863 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]); 1864 1865 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1866 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]) 1867 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */ 1868 1869 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1; 1870 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] = 1871 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]); 1872 1873 val1 = pfwinfo->event[BTF_EVNT_RPT]; 1874 if (((prpt->v8.rpt_len_max_h << 8) + 1875 prpt->v8.rpt_len_max_l) != ver->info_buf) 1876 dm->error.map.h2c_c2h_buffer_mismatch = true; 1877 else 1878 dm->error.map.h2c_c2h_buffer_mismatch = false; 1879 1880 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0); 1881 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1); 1882 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0); 1883 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0); 1884 } else { 1885 goto err; 1886 } 1887 break; 1888 case BTC_RPT_TYPE_TDMA: 1889 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1890 "[BTC], %s(): check %d %zu\n", __func__, 1891 BTC_DCNT_TDMA_NONSYNC, 1892 sizeof(dm->tdma_now)); 1893 if (ver->fcxtdma == 1) 1894 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 1895 memcmp(&dm->tdma_now, 1896 &pfwinfo->rpt_fbtc_tdma.finfo.v1, 1897 sizeof(dm->tdma_now))); 1898 else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) 1899 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC, 1900 memcmp(&dm->tdma_now, 1901 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma, 1902 sizeof(dm->tdma_now))); 1903 else 1904 goto err; 1905 break; 1906 case BTC_RPT_TYPE_SLOT: 1907 if (ver->fcxslots == 7) { 1908 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1909 "[BTC], %s(): check %d %zu\n", 1910 __func__, BTC_DCNT_SLOT_NONSYNC, 1911 sizeof(dm->slot_now.v7)); 1912 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 1913 memcmp(dm->slot_now.v7, 1914 pfwinfo->rpt_fbtc_slots.finfo.v7.slot, 1915 sizeof(dm->slot_now.v7))); 1916 } else if (ver->fcxslots == 1) { 1917 rtw89_debug(rtwdev, RTW89_DBG_BTC, 1918 "[BTC], %s(): check %d %zu\n", 1919 __func__, BTC_DCNT_SLOT_NONSYNC, 1920 sizeof(dm->slot_now.v1)); 1921 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC, 1922 memcmp(dm->slot_now.v1, 1923 pfwinfo->rpt_fbtc_slots.finfo.v1.slot, 1924 sizeof(dm->slot_now.v1))); 1925 } 1926 break; 1927 case BTC_RPT_TYPE_CYSTA: 1928 if (ver->fcxcysta == 2) { 1929 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD) 1930 break; 1931 /* Check Leak-AP */ 1932 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 && 1933 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) { 1934 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) < 1935 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt)) 1936 dm->leak_ap = 1; 1937 } 1938 1939 /* Check diff time between WL slot and W1/E2G slot */ 1940 if (dm->tdma_now.type == CXTDMA_OFF && 1941 dm->tdma_now.ext_ctrl == CXECTL_EXT) { 1942 if (ver->fcxslots == 1) 1943 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur); 1944 else if (ver->fcxslots == 7) 1945 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur); 1946 } else { 1947 if (ver->fcxslots == 1) 1948 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 1949 else if (ver->fcxslots == 7) 1950 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 1951 } 1952 1953 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) { 1954 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set; 1955 _chk_btc_err(rtwdev, 1956 BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1957 } 1958 1959 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1960 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1])); 1961 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 1962 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1])); 1963 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 1964 le16_to_cpu(pcysta->v2.cycles)); 1965 } else if (ver->fcxcysta == 3) { 1966 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD) 1967 break; 1968 1969 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]); 1970 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr); 1971 1972 /* Check Leak-AP */ 1973 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 1974 dm->tdma_now.rxflctrl) { 1975 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 1976 dm->leak_ap = 1; 1977 } 1978 1979 /* Check diff time between real WL slot and W1 slot */ 1980 if (dm->tdma_now.type == CXTDMA_OFF) { 1981 if (ver->fcxslots == 1) 1982 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 1983 else if (ver->fcxslots == 7) 1984 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 1985 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]); 1986 if (wl_slot_real > wl_slot_set) { 1987 diff_t = wl_slot_real - wl_slot_set; 1988 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 1989 } 1990 } 1991 1992 /* Check diff time between real BT slot and EBT/E5G slot */ 1993 if (dm->tdma_now.type == CXTDMA_OFF && 1994 dm->tdma_now.ext_ctrl == CXECTL_EXT && 1995 btc->bt_req_len != 0) { 1996 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]); 1997 if (btc->bt_req_len > bt_slot_real) { 1998 diff_t = btc->bt_req_len - bt_slot_real; 1999 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2000 } 2001 } 2002 2003 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2004 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1])); 2005 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2006 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1])); 2007 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2008 le16_to_cpu(pcysta->v3.cycles)); 2009 } else if (ver->fcxcysta == 4) { 2010 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD) 2011 break; 2012 2013 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]); 2014 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr); 2015 2016 /* Check Leak-AP */ 2017 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2018 dm->tdma_now.rxflctrl) { 2019 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2020 dm->leak_ap = 1; 2021 } 2022 2023 /* Check diff time between real WL slot and W1 slot */ 2024 if (dm->tdma_now.type == CXTDMA_OFF) { 2025 if (ver->fcxslots == 1) 2026 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2027 else if (ver->fcxslots == 7) 2028 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2029 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]); 2030 if (wl_slot_real > wl_slot_set) { 2031 diff_t = wl_slot_real - wl_slot_set; 2032 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2033 } 2034 } 2035 2036 /* Check diff time between real BT slot and EBT/E5G slot */ 2037 if (dm->tdma_now.type == CXTDMA_OFF && 2038 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2039 btc->bt_req_len != 0) { 2040 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]); 2041 2042 if (btc->bt_req_len > bt_slot_real) { 2043 diff_t = btc->bt_req_len - bt_slot_real; 2044 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2045 } 2046 } 2047 2048 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2049 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1])); 2050 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2051 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1])); 2052 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2053 le16_to_cpu(pcysta->v4.cycles)); 2054 } else if (ver->fcxcysta == 5) { 2055 if (dm->fddt_train == BTC_FDDT_ENABLE) 2056 break; 2057 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]); 2058 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr); 2059 2060 /* Check Leak-AP */ 2061 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 && 2062 dm->tdma_now.rxflctrl) { 2063 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD && 2064 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr) 2065 dm->leak_ap = 1; 2066 } 2067 2068 /* Check diff time between real WL slot and W1 slot */ 2069 if (dm->tdma_now.type == CXTDMA_OFF) { 2070 if (ver->fcxslots == 1) 2071 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur); 2072 else if (ver->fcxslots == 7) 2073 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur); 2074 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]); 2075 2076 if (wl_slot_real > wl_slot_set) 2077 diff_t = wl_slot_real - wl_slot_set; 2078 else 2079 diff_t = wl_slot_set - wl_slot_real; 2080 } 2081 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t); 2082 2083 /* Check diff time between real BT slot and EBT/E5G slot */ 2084 bt_slot_set = btc->bt_req_len; 2085 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]); 2086 diff_t = 0; 2087 if (dm->tdma_now.type == CXTDMA_OFF && 2088 dm->tdma_now.ext_ctrl == CXECTL_EXT && 2089 bt_slot_set != 0) { 2090 if (bt_slot_set > bt_slot_real) 2091 diff_t = bt_slot_set - bt_slot_real; 2092 else 2093 diff_t = bt_slot_real - bt_slot_set; 2094 } 2095 2096 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t); 2097 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2098 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G])); 2099 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2100 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1])); 2101 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2102 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1])); 2103 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2104 le16_to_cpu(pcysta->v5.cycles)); 2105 } else if (ver->fcxcysta == 7) { 2106 if (dm->fddt_train == BTC_FDDT_ENABLE) 2107 break; 2108 2109 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 2110 2111 if (dm->tdma_now.type != CXTDMA_OFF) { 2112 /* Check diff time between real WL slot and W1 slot */ 2113 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]); 2114 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16); 2115 2116 /* Check Leak-AP */ 2117 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) * 2118 BTC_LEAK_AP_TH; 2119 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]); 2120 2121 val16 = le16_to_cpu(pcysta->v7.cycles); 2122 if (dm->tdma_now.rxflctrl && 2123 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2124 dm->leak_ap = 1; 2125 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) { 2126 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]); 2127 /* Check diff between real BT slot and EBT/E5G slot */ 2128 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16); 2129 2130 /* Check bt slot length for P2P mode*/ 2131 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) * 2132 BTC_SLOT_REQ_TH; 2133 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt); 2134 2135 val16 = le16_to_cpu(pcysta->v7.cycles); 2136 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2) 2137 dm->slot_req_more = 1; 2138 else if (bt->link_info.status.map.connect == 0) 2139 dm->slot_req_more = 0; 2140 } 2141 2142 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG, 2143 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G])); 2144 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG, 2145 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1])); 2146 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG, 2147 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1])); 2148 2149 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */ 2150 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD, 2151 le16_to_cpu(pcysta->v7.cycles)); 2152 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG, 2153 le16_to_cpu(pcysta->v7.cycles)); 2154 } else { 2155 goto err; 2156 } 2157 break; 2158 case BTC_RPT_TYPE_MREG: 2159 if (ver->fcxmreg == 7) 2160 break; 2161 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val); 2162 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL) 2163 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL; 2164 else 2165 dm->wl_btg_rx_rb = val; 2166 2167 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val); 2168 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL) 2169 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL; 2170 else 2171 dm->wl_pre_agc_rb = val; 2172 break; 2173 case BTC_RPT_TYPE_BT_VER: 2174 case BTC_RPT_TYPE_BT_SCAN: 2175 case BTC_RPT_TYPE_BT_AFH: 2176 case BTC_RPT_TYPE_BT_DEVICE: 2177 _update_bt_report(rtwdev, rpt_type, pfinfo); 2178 break; 2179 } 2180 return (rpt_len + BTC_RPT_HDR_SIZE); 2181 2182 err: 2183 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2184 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type); 2185 return 0; 2186 } 2187 2188 static void _parse_btc_report(struct rtw89_dev *rtwdev, 2189 struct rtw89_btc_btf_fwinfo *pfwinfo, 2190 u8 *pbuf, u32 buf_len) 2191 { 2192 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 2193 struct rtw89_btc_prpt *btc_prpt = NULL; 2194 u32 index = 0, rpt_len = 0; 2195 2196 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2197 "[BTC], %s(): buf_len:%d\n", 2198 __func__, buf_len); 2199 2200 while (pbuf) { 2201 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index]; 2202 if (index + 2 >= ver->info_buf) 2203 break; 2204 /* At least 3 bytes: type(1) & len(2) */ 2205 rpt_len = le16_to_cpu(btc_prpt->len); 2206 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len) 2207 break; 2208 2209 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index); 2210 if (!rpt_len) 2211 break; 2212 index += rpt_len; 2213 } 2214 } 2215 2216 #define BTC_TLV_HDR_LEN 2 2217 #define BTC_TLV_HDR_LEN_V7 3 2218 2219 static void _append_tdma(struct rtw89_dev *rtwdev) 2220 { 2221 struct rtw89_btc *btc = &rtwdev->btc; 2222 const struct rtw89_btc_ver *ver = btc->ver; 2223 struct rtw89_btc_dm *dm = &btc->dm; 2224 struct rtw89_btc_btf_tlv *tlv; 2225 struct rtw89_btc_btf_tlv_v7 *tlv_v7; 2226 struct rtw89_btc_fbtc_tdma *v; 2227 struct rtw89_btc_fbtc_tdma_v3 *v3; 2228 u16 len = btc->policy_len; 2229 2230 if (!btc->update_policy_force && 2231 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) { 2232 rtw89_debug(rtwdev, 2233 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n", 2234 __func__); 2235 return; 2236 } 2237 2238 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 2239 tlv->type = CXPOLICY_TDMA; 2240 if (ver->fcxtdma == 1) { 2241 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0]; 2242 tlv->len = sizeof(*v); 2243 *v = dm->tdma; 2244 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 2245 } else if (ver->fcxtdma == 7) { 2246 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len]; 2247 tlv_v7->len = sizeof(dm->tdma); 2248 tlv_v7->ver = ver->fcxtdma; 2249 tlv_v7->type = CXPOLICY_TDMA; 2250 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len); 2251 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len; 2252 } else { 2253 tlv->len = sizeof(*v3); 2254 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0]; 2255 v3->fver = ver->fcxtdma; 2256 v3->tdma = dm->tdma; 2257 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3); 2258 } 2259 2260 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2261 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n", 2262 __func__, dm->tdma.type, dm->tdma.rxflctrl, 2263 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n, 2264 dm->tdma.ext_ctrl); 2265 } 2266 2267 static void _append_slot_v1(struct rtw89_dev *rtwdev) 2268 { 2269 struct rtw89_btc *btc = &rtwdev->btc; 2270 struct rtw89_btc_dm *dm = &btc->dm; 2271 struct rtw89_btc_btf_tlv *tlv = NULL; 2272 struct btc_fbtc_1slot *v = NULL; 2273 u16 len = 0; 2274 u8 i, cnt = 0; 2275 2276 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2277 "[BTC], %s(): A:btc->policy_len = %d\n", 2278 __func__, btc->policy_len); 2279 2280 for (i = 0; i < CXST_MAX; i++) { 2281 if (!btc->update_policy_force && 2282 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i], 2283 sizeof(dm->slot.v1[i]))) 2284 continue; 2285 2286 len = btc->policy_len; 2287 2288 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len]; 2289 v = (struct btc_fbtc_1slot *)&tlv->val[0]; 2290 tlv->type = CXPOLICY_SLOT; 2291 tlv->len = sizeof(*v); 2292 2293 v->fver = btc->ver->fcxslots; 2294 v->sid = i; 2295 v->slot = dm->slot.v1[i]; 2296 2297 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2298 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n", 2299 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl, 2300 dm->slot.v1[i].cxtype); 2301 cnt++; 2302 2303 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v); 2304 } 2305 2306 if (cnt > 0) 2307 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2308 "[BTC], %s(): slot update (cnt=%d)!!\n", 2309 __func__, cnt); 2310 } 2311 2312 static void _append_slot_v7(struct rtw89_dev *rtwdev) 2313 { 2314 struct rtw89_btc_btf_tlv_v7 *tlv = NULL; 2315 struct rtw89_btc *btc = &rtwdev->btc; 2316 struct rtw89_btc_dm *dm = &btc->dm; 2317 u8 i, cnt = 0; 2318 u16 len; 2319 2320 for (i = 0; i < CXST_MAX; i++) { 2321 if (!btc->update_policy_force && 2322 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i], 2323 sizeof(dm->slot.v7[i]))) 2324 continue; 2325 2326 len = btc->policy_len; 2327 2328 if (!tlv) { 2329 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) { 2330 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2331 "[BTC], %s(): buff overflow!\n", __func__); 2332 break; 2333 } 2334 2335 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len]; 2336 tlv->type = CXPOLICY_SLOT; 2337 tlv->ver = btc->ver->fcxslots; 2338 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7; 2339 len += BTC_TLV_HDR_LEN_V7; 2340 } 2341 2342 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) { 2343 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2344 "[BTC], %s(): buff overflow!\n", __func__); 2345 break; 2346 } 2347 2348 btc->policy[len] = i; /* slot-id */ 2349 memcpy(&btc->policy[len + 1], &dm->slot.v7[i], 2350 sizeof(dm->slot.v7[0])); 2351 len += tlv->len; 2352 2353 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2354 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n", 2355 __func__, btc->policy_len, i, dm->slot.v7[i].dur, 2356 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl); 2357 cnt++; 2358 btc->policy_len = len; /* update total length */ 2359 } 2360 2361 if (cnt > 0) 2362 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2363 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n", 2364 __func__, cnt, btc->policy_len); 2365 } 2366 2367 static void _append_slot(struct rtw89_dev *rtwdev) 2368 { 2369 struct rtw89_btc *btc = &rtwdev->btc; 2370 2371 if (btc->ver->fcxslots == 7) 2372 _append_slot_v7(rtwdev); 2373 else 2374 _append_slot_v1(rtwdev); 2375 } 2376 2377 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map) 2378 { 2379 struct rtw89_btc *btc = &rtwdev->btc; 2380 const struct rtw89_btc_ver *ver = btc->ver; 2381 u32 bit_map = 0; 2382 2383 switch (rpt_map) { 2384 case RPT_EN_TDMA: 2385 bit_map = BIT(0); 2386 break; 2387 case RPT_EN_CYCLE: 2388 bit_map = BIT(1); 2389 break; 2390 case RPT_EN_MREG: 2391 bit_map = BIT(2); 2392 break; 2393 case RPT_EN_BT_VER_INFO: 2394 bit_map = BIT(3); 2395 break; 2396 case RPT_EN_BT_SCAN_INFO: 2397 bit_map = BIT(4); 2398 break; 2399 case RPT_EN_BT_DEVICE_INFO: 2400 switch (ver->frptmap) { 2401 case 0: 2402 case 1: 2403 case 2: 2404 bit_map = BIT(6); 2405 break; 2406 case 3: 2407 case 4: 2408 bit_map = BIT(5); 2409 break; 2410 default: 2411 break; 2412 } 2413 break; 2414 case RPT_EN_BT_AFH_MAP: 2415 switch (ver->frptmap) { 2416 case 0: 2417 case 1: 2418 case 2: 2419 bit_map = BIT(5); 2420 break; 2421 case 3: 2422 case 4: 2423 bit_map = BIT(6); 2424 break; 2425 default: 2426 break; 2427 } 2428 break; 2429 case RPT_EN_BT_AFH_MAP_LE: 2430 switch (ver->frptmap) { 2431 case 2: 2432 bit_map = BIT(8); 2433 break; 2434 case 3: 2435 case 4: 2436 bit_map = BIT(7); 2437 break; 2438 default: 2439 break; 2440 } 2441 break; 2442 case RPT_EN_BT_TX_PWR_LVL: 2443 switch (ver->frptmap) { 2444 case 0: 2445 case 1: 2446 case 2: 2447 case 3: 2448 break; 2449 case 4: 2450 bit_map = BIT(8); 2451 break; 2452 default: 2453 break; 2454 } 2455 break; 2456 case RPT_EN_FW_STEP_INFO: 2457 switch (ver->frptmap) { 2458 case 1: 2459 case 2: 2460 bit_map = BIT(7); 2461 break; 2462 case 3: 2463 bit_map = BIT(8); 2464 break; 2465 case 4: 2466 bit_map = BIT(9); 2467 break; 2468 default: 2469 break; 2470 } 2471 break; 2472 case RPT_EN_TEST: 2473 bit_map = BIT(31); 2474 break; 2475 case RPT_EN_WL_ALL: 2476 switch (ver->frptmap) { 2477 case 0: 2478 case 1: 2479 case 2: 2480 bit_map = GENMASK(2, 0); 2481 break; 2482 case 3: 2483 bit_map = GENMASK(2, 0) | BIT(8); 2484 break; 2485 case 4: 2486 bit_map = GENMASK(2, 0) | BIT(9); 2487 break; 2488 default: 2489 break; 2490 } 2491 break; 2492 case RPT_EN_BT_ALL: 2493 switch (ver->frptmap) { 2494 case 0: 2495 case 1: 2496 bit_map = GENMASK(6, 3); 2497 break; 2498 case 2: 2499 bit_map = GENMASK(6, 3) | BIT(8); 2500 break; 2501 case 3: 2502 bit_map = GENMASK(7, 3); 2503 break; 2504 case 4: 2505 bit_map = GENMASK(8, 3); 2506 break; 2507 default: 2508 break; 2509 } 2510 break; 2511 case RPT_EN_ALL: 2512 switch (ver->frptmap) { 2513 case 0: 2514 bit_map = GENMASK(6, 0); 2515 break; 2516 case 1: 2517 bit_map = GENMASK(7, 0); 2518 break; 2519 case 2: 2520 case 3: 2521 bit_map = GENMASK(8, 0); 2522 break; 2523 case 4: 2524 bit_map = GENMASK(9, 0); 2525 break; 2526 default: 2527 break; 2528 } 2529 break; 2530 case RPT_EN_MONITER: 2531 switch (ver->frptmap) { 2532 case 0: 2533 case 1: 2534 bit_map = GENMASK(6, 2); 2535 break; 2536 case 2: 2537 bit_map = GENMASK(6, 2) | BIT(8); 2538 break; 2539 case 3: 2540 bit_map = GENMASK(8, 2); 2541 break; 2542 case 4: 2543 bit_map = GENMASK(9, 2); 2544 break; 2545 default: 2546 break; 2547 } 2548 break; 2549 } 2550 2551 return bit_map; 2552 } 2553 2554 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev) 2555 { 2556 struct rtw89_btc *btc = &rtwdev->btc; 2557 const struct rtw89_btc_ver *ver = btc->ver; 2558 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL; 2559 struct rtw89_btc_btf_set_slot_table *tbl; 2560 struct rtw89_btc_dm *dm = &btc->dm; 2561 u16 n, len; 2562 2563 if (ver->fcxslots == 7) { 2564 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7); 2565 tlv_v7 = kmalloc(len, GFP_KERNEL); 2566 if (!tlv_v7) 2567 return; 2568 2569 tlv_v7->type = SET_SLOT_TABLE; 2570 tlv_v7->ver = ver->fcxslots; 2571 tlv_v7->len = ARRAY_SIZE(dm->slot.v7); 2572 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7)); 2573 2574 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len); 2575 2576 kfree(tlv_v7); 2577 } else { 2578 n = struct_size(tbl, tbls, CXST_MAX); 2579 tbl = kmalloc(n, GFP_KERNEL); 2580 if (!tbl) 2581 return; 2582 2583 tbl->fver = BTF_SET_SLOT_TABLE_VER; 2584 tbl->tbl_num = CXST_MAX; 2585 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX)); 2586 2587 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n); 2588 2589 kfree(tbl); 2590 } 2591 } 2592 2593 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev, 2594 u32 rpt_map, bool rpt_state) 2595 { 2596 struct rtw89_btc *btc = &rtwdev->btc; 2597 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map; 2598 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo; 2599 union rtw89_fbtc_rtp_ctrl r; 2600 u32 val, bit_map; 2601 int ret; 2602 2603 if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0) 2604 return; 2605 2606 bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map); 2607 2608 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2609 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n", 2610 __func__, rpt_map, rpt_state); 2611 2612 if (rpt_state) 2613 val = fwinfo->rpt_en_map | bit_map; 2614 else 2615 val = fwinfo->rpt_en_map & ~bit_map; 2616 2617 if (val == fwinfo->rpt_en_map) 2618 return; 2619 2620 if (btc->ver->fcxbtcrpt == 7 || btc->ver->fcxbtcrpt == 8) { 2621 r.v8.type = SET_REPORT_EN; 2622 r.v8.fver = btc->ver->fcxbtcrpt; 2623 r.v8.len = sizeof(r.v8.map); 2624 r.v8.map = cpu_to_le32(val); 2625 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8, 2626 sizeof(r.v8)); 2627 } else { 2628 if (btc->ver->fcxbtcrpt == 105) 2629 r.v1.fver = 5; 2630 else 2631 r.v1.fver = btc->ver->fcxbtcrpt; 2632 r.v1.enable = cpu_to_le32(val); 2633 r.v1.para = cpu_to_le32(rpt_state); 2634 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1, 2635 sizeof(r.v1)); 2636 } 2637 2638 if (!ret) 2639 fwinfo->rpt_en_map = val; 2640 } 2641 2642 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev) 2643 { 2644 const struct rtw89_chip_info *chip = rtwdev->chip; 2645 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 2646 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL; 2647 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL; 2648 u8 i, n, ulen, cxmreg_max; 2649 u16 sz = 0; 2650 2651 n = chip->mon_reg_num; 2652 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2653 "[BTC], %s(): mon_reg_num=%d\n", __func__, n); 2654 2655 if (ver->fcxmreg == 1) 2656 cxmreg_max = CXMREG_MAX; 2657 else 2658 cxmreg_max = CXMREG_MAX_V2; 2659 2660 if (n > cxmreg_max) { 2661 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2662 "[BTC], %s(): mon reg count %d > %d\n", 2663 __func__, n, cxmreg_max); 2664 return; 2665 } 2666 2667 ulen = sizeof(struct rtw89_btc_fbtc_mreg); 2668 2669 if (ver->fcxmreg == 7) { 2670 sz = struct_size(v7, regs, n); 2671 v7 = kmalloc(sz, GFP_KERNEL); 2672 if (!v7) 2673 return; 2674 v7->type = RPT_EN_MREG; 2675 v7->fver = ver->fcxmreg; 2676 v7->len = n; 2677 for (i = 0; i < n; i++) { 2678 v7->regs[i].type = chip->mon_reg[i].type; 2679 v7->regs[i].bytes = chip->mon_reg[i].bytes; 2680 v7->regs[i].offset = chip->mon_reg[i].offset; 2681 } 2682 2683 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz); 2684 kfree(v7); 2685 } else { 2686 sz = struct_size(v1, regs, n); 2687 v1 = kmalloc(sz, GFP_KERNEL); 2688 if (!v1) 2689 return; 2690 v1->fver = ver->fcxmreg; 2691 v1->reg_num = n; 2692 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n)); 2693 2694 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz); 2695 kfree(v1); 2696 } 2697 2698 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2699 "[BTC], %s(): sz=%d ulen=%d n=%d\n", 2700 __func__, sz, ulen, n); 2701 2702 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1); 2703 } 2704 2705 static void _update_dm_step(struct rtw89_dev *rtwdev, 2706 enum btc_reason_and_action reason_or_action) 2707 { 2708 struct rtw89_btc *btc = &rtwdev->btc; 2709 struct rtw89_btc_dm *dm = &btc->dm; 2710 2711 /* use ring-structure to store dm step */ 2712 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action; 2713 dm->dm_step.step_pos++; 2714 2715 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) { 2716 dm->dm_step.step_pos = 0; 2717 dm->dm_step.step_ov = true; 2718 } 2719 } 2720 2721 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 2722 enum btc_reason_and_action action) 2723 { 2724 struct rtw89_btc *btc = &rtwdev->btc; 2725 struct rtw89_btc_dm *dm = &btc->dm; 2726 int ret; 2727 2728 dm->run_action = action; 2729 2730 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT); 2731 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT); 2732 2733 btc->policy_len = 0; 2734 btc->policy_type = policy_type; 2735 2736 _append_tdma(rtwdev); 2737 _append_slot(rtwdev); 2738 2739 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN) 2740 return; 2741 2742 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2743 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n", 2744 __func__, action, policy_type, btc->policy_len); 2745 2746 if (dm->tdma.rxflctrl == CXFLC_NULLP || 2747 dm->tdma.rxflctrl == CXFLC_QOSNULL) 2748 btc->lps = 1; 2749 else 2750 btc->lps = 0; 2751 2752 if (btc->lps == 1) 2753 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps); 2754 2755 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY, 2756 btc->policy, btc->policy_len); 2757 if (!ret) { 2758 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now)); 2759 if (btc->ver->fcxslots == 7) 2760 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7)); 2761 else 2762 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1)); 2763 } 2764 2765 if (btc->update_policy_force) 2766 btc->update_policy_force = false; 2767 2768 if (btc->lps == 0) 2769 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps); 2770 } 2771 2772 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type) 2773 { 2774 struct rtw89_btc *btc = &rtwdev->btc; 2775 const struct rtw89_btc_ver *ver = btc->ver; 2776 struct rtw89_btc_dm *dm = &btc->dm; 2777 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 2778 struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para; 2779 2780 switch (type) { 2781 case CXDRVINFO_INIT: 2782 if (ver->fcxinit == 7) 2783 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type); 2784 else 2785 rtw89_fw_h2c_cxdrv_init(rtwdev, type); 2786 break; 2787 case CXDRVINFO_ROLE: 2788 if (ver->fwlrole == 0) 2789 rtw89_fw_h2c_cxdrv_role(rtwdev, type); 2790 else if (ver->fwlrole == 1) 2791 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type); 2792 else if (ver->fwlrole == 2) 2793 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type); 2794 else if (ver->fwlrole == 7) 2795 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, type); 2796 else if (ver->fwlrole == 8) 2797 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, type); 2798 break; 2799 case CXDRVINFO_CTRL: 2800 if (ver->drvinfo_type == 1) 2801 type = 2; 2802 2803 if (ver->fcxctrl == 7) 2804 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type); 2805 else 2806 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type); 2807 break; 2808 case CXDRVINFO_TRX: 2809 if (ver->drvinfo_type == 1) 2810 type = 3; 2811 2812 dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power, 2813 RTW89_BTC_WL_DEF_TX_PWR); 2814 dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain, 2815 RTW89_BTC_WL_DEF_TX_PWR); 2816 dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power, 2817 RTW89_BTC_WL_DEF_TX_PWR); 2818 dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain, 2819 RTW89_BTC_WL_DEF_TX_PWR); 2820 dm->trx_info.cn = wl->cn_report; 2821 dm->trx_info.nhm = wl->nhm.pwr; 2822 rtw89_fw_h2c_cxdrv_trx(rtwdev, type); 2823 break; 2824 case CXDRVINFO_RFK: 2825 if (ver->drvinfo_type == 1) 2826 return; 2827 2828 rtw89_fw_h2c_cxdrv_rfk(rtwdev, type); 2829 break; 2830 case CXDRVINFO_TXPWR: 2831 case CXDRVINFO_FDDT: 2832 case CXDRVINFO_MLO: 2833 case CXDRVINFO_OSI: 2834 if (!ver->fcxosi) 2835 return; 2836 2837 if (ver->drvinfo_type == 2) 2838 type = 7; 2839 else 2840 return; 2841 2842 rtw89_fw_h2c_cxdrv_osi_info(rtwdev, type); 2843 break; 2844 default: 2845 break; 2846 } 2847 } 2848 2849 static 2850 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len) 2851 { 2852 struct rtw89_btc *btc = &rtwdev->btc; 2853 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 2854 2855 rtw89_debug(rtwdev, RTW89_DBG_BTC, 2856 "[BTC], %s(): evt_id:%d len:%d\n", 2857 __func__, evt_id, len); 2858 2859 if (!len || !data) 2860 return; 2861 2862 switch (evt_id) { 2863 case BTF_EVNT_RPT: 2864 _parse_btc_report(rtwdev, pfwinfo, data, len); 2865 break; 2866 default: 2867 break; 2868 } 2869 } 2870 2871 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state) 2872 { 2873 struct rtw89_btc *btc = &rtwdev->btc; 2874 struct rtw89_btc_dm *dm = &btc->dm; 2875 struct rtw89_mac_ax_gnt *g = dm->gnt.band; 2876 u8 i; 2877 2878 if (phy_map > BTC_PHY_ALL) 2879 return; 2880 2881 for (i = 0; i < RTW89_PHY_NUM; i++) { 2882 if (!(phy_map & BIT(i))) 2883 continue; 2884 2885 switch (wl_state) { 2886 case BTC_GNT_HW: 2887 g[i].gnt_wl_sw_en = 0; 2888 g[i].gnt_wl = 0; 2889 break; 2890 case BTC_GNT_SW_LO: 2891 g[i].gnt_wl_sw_en = 1; 2892 g[i].gnt_wl = 0; 2893 break; 2894 case BTC_GNT_SW_HI: 2895 g[i].gnt_wl_sw_en = 1; 2896 g[i].gnt_wl = 1; 2897 break; 2898 } 2899 2900 switch (bt_state) { 2901 case BTC_GNT_HW: 2902 g[i].gnt_bt_sw_en = 0; 2903 g[i].gnt_bt = 0; 2904 break; 2905 case BTC_GNT_SW_LO: 2906 g[i].gnt_bt_sw_en = 1; 2907 g[i].gnt_bt = 0; 2908 break; 2909 case BTC_GNT_SW_HI: 2910 g[i].gnt_bt_sw_en = 1; 2911 g[i].gnt_bt = 1; 2912 break; 2913 } 2914 } 2915 2916 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt); 2917 } 2918 2919 static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map, 2920 u8 wl_state, u8 bt_state, u8 wlact_state) 2921 { 2922 struct rtw89_btc *btc = &rtwdev->btc; 2923 struct rtw89_btc_dm *dm = &btc->dm; 2924 struct rtw89_btc_fbtc_outsrc_set_info *osi = &dm->ost_info; 2925 struct rtw89_mac_ax_wl_act *b = dm->gnt.bt; 2926 struct rtw89_mac_ax_gnt *g = dm->gnt.band; 2927 u8 i, bt_idx = dm->bt_select + 1; 2928 2929 if (phy_map > BTC_PHY_ALL) 2930 return; 2931 2932 for (i = 0; i < RTW89_PHY_NUM; i++) { 2933 if (!(phy_map & BIT(i))) 2934 continue; 2935 2936 switch (wl_state) { 2937 case BTC_GNT_HW: 2938 g[i].gnt_wl_sw_en = 0; 2939 g[i].gnt_wl = 0; 2940 break; 2941 case BTC_GNT_SW_LO: 2942 g[i].gnt_wl_sw_en = 1; 2943 g[i].gnt_wl = 0; 2944 break; 2945 case BTC_GNT_SW_HI: 2946 g[i].gnt_wl_sw_en = 1; 2947 g[i].gnt_wl = 1; 2948 break; 2949 } 2950 2951 switch (bt_state) { 2952 case BTC_GNT_HW: 2953 g[i].gnt_bt_sw_en = 0; 2954 g[i].gnt_bt = 0; 2955 break; 2956 case BTC_GNT_SW_LO: 2957 g[i].gnt_bt_sw_en = 1; 2958 g[i].gnt_bt = 0; 2959 break; 2960 case BTC_GNT_SW_HI: 2961 g[i].gnt_bt_sw_en = 1; 2962 g[i].gnt_bt = 1; 2963 break; 2964 } 2965 } 2966 2967 if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) { 2968 for (i = 0; i < 2; i++) { 2969 if (!(bt_idx & BIT(i))) 2970 continue; 2971 2972 switch (wlact_state) { 2973 case BTC_WLACT_HW: 2974 b[i].wlan_act_en = 0; 2975 b[i].wlan_act = 0; 2976 break; 2977 case BTC_WLACT_SW_LO: 2978 b[i].wlan_act_en = 1; 2979 b[i].wlan_act = 0; 2980 break; 2981 case BTC_WLACT_SW_HI: 2982 b[i].wlan_act_en = 1; 2983 b[i].wlan_act = 1; 2984 break; 2985 } 2986 } 2987 } 2988 2989 if (!btc->ver->fcxosi) { 2990 rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt); 2991 return; 2992 } 2993 2994 memcpy(osi->gnt_set, dm->gnt.band, sizeof(osi->gnt_set)); 2995 memcpy(osi->wlact_set, dm->gnt.bt, sizeof(osi->wlact_set)); 2996 2997 /* GBT source should be GBT_S1 in 1+1 (HWB0:5G + HWB1:2G) case */ 2998 if (osi->rf_band[BTC_RF_S0] == 1 && 2999 osi->rf_band[BTC_RF_S1] == 0) 3000 osi->rf_gbt_source = BTC_RF_S1; 3001 else 3002 osi->rf_gbt_source = BTC_RF_S0; 3003 } 3004 3005 #define BTC_TDMA_WLROLE_MAX 3 3006 3007 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable) 3008 { 3009 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3010 "[BTC], %s(): set bt %s wlan_act\n", __func__, 3011 enable ? "ignore" : "do not ignore"); 3012 3013 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1); 3014 } 3015 3016 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0) 3017 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0) 3018 #define WL_TX_POWER_WITH_BT GENMASK(31, 16) 3019 #define WL_TX_POWER_INT_PART GENMASK(8, 2) 3020 #define WL_TX_POWER_FRA_PART GENMASK(1, 0) 3021 #define B_BTC_WL_TX_POWER_SIGN BIT(7) 3022 #define B_TSSI_WL_TX_POWER_SIGN BIT(8) 3023 3024 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level) 3025 { 3026 const struct rtw89_chip_info *chip = rtwdev->chip; 3027 struct rtw89_btc *btc = &rtwdev->btc; 3028 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3029 u32 pwr_val; 3030 3031 if (wl->rf_para.tx_pwr_freerun == level) 3032 return; 3033 3034 wl->rf_para.tx_pwr_freerun = level; 3035 btc->dm.rf_trx_para.wl_tx_power = level; 3036 3037 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3038 "[BTC], %s(): level = %d\n", 3039 __func__, level); 3040 3041 if (level == RTW89_BTC_WL_DEF_TX_PWR) { 3042 pwr_val = WL_TX_POWER_NO_BTC_CTRL; 3043 } else { /* only apply "force tx power" */ 3044 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level); 3045 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR) 3046 pwr_val = RTW89_BTC_WL_DEF_TX_PWR; 3047 3048 if (level & B_BTC_WL_TX_POWER_SIGN) 3049 pwr_val |= B_TSSI_WL_TX_POWER_SIGN; 3050 pwr_val |= WL_TX_POWER_WITH_BT; 3051 } 3052 3053 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val); 3054 } 3055 3056 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) 3057 { 3058 const struct rtw89_chip_info *chip = rtwdev->chip; 3059 struct rtw89_btc *btc = &rtwdev->btc; 3060 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3061 3062 if (wl->rf_para.rx_gain_freerun == level) 3063 return; 3064 3065 wl->rf_para.rx_gain_freerun = level; 3066 btc->dm.rf_trx_para.wl_rx_gain = level; 3067 3068 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3069 "[BTC], %s(): level = %d\n", 3070 __func__, level); 3071 3072 chip->ops->btc_set_wl_rx_gain(rtwdev, level); 3073 } 3074 3075 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level) 3076 { 3077 struct rtw89_btc *btc = &rtwdev->btc; 3078 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3079 int ret; 3080 u8 buf; 3081 3082 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0) 3083 return; 3084 3085 if (bt->rf_para.tx_pwr_freerun == level) 3086 return; 3087 3088 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3089 "[BTC], %s(): level = %d\n", 3090 __func__, level); 3091 3092 buf = (s8)(-level); 3093 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1); 3094 if (!ret) { 3095 bt->rf_para.tx_pwr_freerun = level; 3096 btc->dm.rf_trx_para.bt_tx_power = level; 3097 } 3098 } 3099 3100 #define BTC_BT_RX_NORMAL_LVL 7 3101 3102 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level) 3103 { 3104 struct rtw89_btc *btc = &rtwdev->btc; 3105 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3106 3107 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0) 3108 return; 3109 3110 if ((bt->rf_para.rx_gain_freerun == level || 3111 level > BTC_BT_RX_NORMAL_LVL) && 3112 (!rtwdev->chip->scbd || bt->lna_constrain == level)) 3113 return; 3114 3115 bt->rf_para.rx_gain_freerun = level; 3116 btc->dm.rf_trx_para.bt_rx_gain = level; 3117 3118 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3119 "[BTC], %s(): level = %d\n", 3120 __func__, level); 3121 3122 if (level == BTC_BT_RX_NORMAL_LVL) 3123 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false); 3124 else 3125 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true); 3126 3127 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level)); 3128 } 3129 3130 static void _set_rf_trx_para(struct rtw89_dev *rtwdev) 3131 { 3132 const struct rtw89_chip_info *chip = rtwdev->chip; 3133 struct rtw89_btc *btc = &rtwdev->btc; 3134 const struct rtw89_btc_ver *ver = btc->ver; 3135 struct rtw89_btc_dm *dm = &btc->dm; 3136 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3137 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3138 struct rtw89_btc_bt_link_info *b = &bt->link_info; 3139 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; 3140 struct rtw89_btc_rf_trx_para para; 3141 u32 wl_stb_chg = 0; 3142 u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0; 3143 3144 if (ver->fwlrole == 0) { 3145 link_mode = wl->role_info.link_mode; 3146 for (i = 0; i < RTW89_PHY_NUM; i++) { 3147 if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G) 3148 dbcc_2g_phy = i; 3149 } 3150 } else if (ver->fwlrole == 1) { 3151 link_mode = wl->role_info_v1.link_mode; 3152 dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy; 3153 } else if (ver->fwlrole == 2) { 3154 link_mode = wl->role_info_v2.link_mode; 3155 dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy; 3156 } 3157 3158 /* decide trx_para_level */ 3159 if (btc->ant_type == BTC_ANT_SHARED) { 3160 /* fix LNA2 + TIA gain not change by GNT_BT */ 3161 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) || 3162 dm->bt_only == 1) 3163 dm->trx_para_level = 1; /* for better BT ACI issue */ 3164 else 3165 dm->trx_para_level = 0; 3166 } else { /* non-shared antenna */ 3167 dm->trx_para_level = 5; 3168 /* modify trx_para if WK 2.4G-STA-DL + bt link */ 3169 if (b->profile_cnt.now != 0 && 3170 link_mode == BTC_WLINK_2G_STA && 3171 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */ 3172 if (wl->rssi_level == 4 && bt->rssi_level > 2) 3173 dm->trx_para_level = 6; 3174 else if (wl->rssi_level == 3 && bt->rssi_level > 3) 3175 dm->trx_para_level = 7; 3176 } 3177 } 3178 3179 level_id = dm->trx_para_level; 3180 if (level_id >= chip->rf_para_dlink_num || 3181 level_id >= chip->rf_para_ulink_num) { 3182 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3183 "[BTC], %s(): invalid level_id: %d\n", 3184 __func__, level_id); 3185 return; 3186 } 3187 3188 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 3189 para = chip->rf_para_ulink[level_id]; 3190 else 3191 para = chip->rf_para_dlink[level_id]; 3192 3193 if (dm->fddt_train) { 3194 _set_wl_rx_gain(rtwdev, 1); 3195 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true); 3196 } else { 3197 _set_wl_tx_power(rtwdev, para.wl_tx_power); 3198 _set_wl_rx_gain(rtwdev, para.wl_rx_gain); 3199 _set_bt_tx_power(rtwdev, para.bt_tx_power); 3200 _set_bt_rx_gain(rtwdev, para.bt_rx_gain); 3201 } 3202 3203 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off || 3204 wl_smap->lps == BTC_LPS_RF_OFF || 3205 link_mode == BTC_WLINK_5G || 3206 link_mode == BTC_WLINK_NOLINK || 3207 (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1)) 3208 wl_stb_chg = 0; 3209 else 3210 wl_stb_chg = 1; 3211 3212 if (wl_stb_chg != dm->wl_stb_chg) { 3213 dm->wl_stb_chg = wl_stb_chg; 3214 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg); 3215 } 3216 } 3217 3218 static void _update_btc_state_map(struct rtw89_dev *rtwdev) 3219 { 3220 struct rtw89_btc *btc = &rtwdev->btc; 3221 struct rtw89_btc_cx *cx = &btc->cx; 3222 struct rtw89_btc_wl_info *wl = &cx->wl; 3223 struct rtw89_btc_bt_info *bt = &cx->bt; 3224 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 3225 3226 if (wl->status.map.connecting || wl->status.map._4way || 3227 wl->status.map.roaming || wl->status.map.dbccing) { 3228 cx->state_map = BTC_WLINKING; 3229 } else if (wl->status.map.scan) { /* wl scan */ 3230 if (bt_linfo->status.map.inq_pag) 3231 cx->state_map = BTC_WSCAN_BSCAN; 3232 else 3233 cx->state_map = BTC_WSCAN_BNOSCAN; 3234 } else if (wl->status.map.busy) { /* only busy */ 3235 if (bt_linfo->status.map.inq_pag) 3236 cx->state_map = BTC_WBUSY_BSCAN; 3237 else 3238 cx->state_map = BTC_WBUSY_BNOSCAN; 3239 } else { /* wl idle */ 3240 cx->state_map = BTC_WIDLE; 3241 } 3242 } 3243 3244 static void _set_bt_afh_info_v0(struct rtw89_dev *rtwdev) 3245 { 3246 const struct rtw89_chip_info *chip = rtwdev->chip; 3247 struct rtw89_btc *btc = &rtwdev->btc; 3248 const struct rtw89_btc_ver *ver = btc->ver; 3249 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3250 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3251 struct rtw89_btc_bt_link_info *b = &bt->link_info; 3252 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3253 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3254 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 3255 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 3256 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 3257 struct rtw89_btc_wl_active_role *r; 3258 struct rtw89_btc_wl_active_role_v1 *r1; 3259 struct rtw89_btc_wl_active_role_v2 *r2; 3260 struct rtw89_btc_wl_active_role_v7 *r7; 3261 struct rtw89_btc_wl_rlink *rlink; 3262 u8 en = 0, i, ch = 0, bw = 0; 3263 u8 mode, connect_cnt; 3264 3265 if (btc->manual_ctrl || wl->status.map.scan) 3266 return; 3267 3268 if (ver->fwlrole == 0) { 3269 mode = wl_rinfo->link_mode; 3270 connect_cnt = wl_rinfo->connect_cnt; 3271 } else if (ver->fwlrole == 1) { 3272 mode = wl_rinfo_v1->link_mode; 3273 connect_cnt = wl_rinfo_v1->connect_cnt; 3274 } else if (ver->fwlrole == 2) { 3275 mode = wl_rinfo_v2->link_mode; 3276 connect_cnt = wl_rinfo_v2->connect_cnt; 3277 } else if (ver->fwlrole == 7) { 3278 mode = wl_rinfo_v7->link_mode; 3279 connect_cnt = wl_rinfo_v7->connect_cnt; 3280 } else if (ver->fwlrole == 8) { 3281 mode = wl_rinfo_v8->link_mode; 3282 connect_cnt = wl_rinfo_v8->connect_cnt; 3283 } else { 3284 return; 3285 } 3286 3287 if (wl->status.map.rf_off || bt->whql_test || 3288 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G || 3289 connect_cnt > BTC_TDMA_WLROLE_MAX) { 3290 en = false; 3291 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) { 3292 en = true; 3293 /* get p2p channel */ 3294 for (i = 0; i < RTW89_PORT_NUM; i++) { 3295 r = &wl_rinfo->active_role[i]; 3296 r1 = &wl_rinfo_v1->active_role_v1[i]; 3297 r2 = &wl_rinfo_v2->active_role_v2[i]; 3298 r7 = &wl_rinfo_v7->active_role[i]; 3299 rlink = &wl_rinfo_v8->rlink[i][0]; 3300 3301 if (ver->fwlrole == 0 && 3302 (r->role == RTW89_WIFI_ROLE_P2P_GO || 3303 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 3304 ch = r->ch; 3305 bw = r->bw; 3306 break; 3307 } else if (ver->fwlrole == 1 && 3308 (r1->role == RTW89_WIFI_ROLE_P2P_GO || 3309 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 3310 ch = r1->ch; 3311 bw = r1->bw; 3312 break; 3313 } else if (ver->fwlrole == 2 && 3314 (r2->role == RTW89_WIFI_ROLE_P2P_GO || 3315 r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 3316 ch = r2->ch; 3317 bw = r2->bw; 3318 break; 3319 } else if (ver->fwlrole == 7 && 3320 (r7->role == RTW89_WIFI_ROLE_P2P_GO || 3321 r7->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 3322 ch = r7->ch; 3323 bw = r7->bw; 3324 break; 3325 } else if (ver->fwlrole == 8 && 3326 (rlink->role == RTW89_WIFI_ROLE_P2P_GO || 3327 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 3328 ch = rlink->ch; 3329 bw = rlink->bw; 3330 break; 3331 } 3332 } 3333 } else { 3334 en = true; 3335 /* get 2g channel */ 3336 for (i = 0; i < RTW89_PORT_NUM; i++) { 3337 r = &wl_rinfo->active_role[i]; 3338 r1 = &wl_rinfo_v1->active_role_v1[i]; 3339 r2 = &wl_rinfo_v2->active_role_v2[i]; 3340 r7 = &wl_rinfo_v7->active_role[i]; 3341 rlink = &wl_rinfo_v8->rlink[i][0]; 3342 3343 if (ver->fwlrole == 0 && 3344 r->connected && r->band == RTW89_BAND_2G) { 3345 ch = r->ch; 3346 bw = r->bw; 3347 break; 3348 } else if (ver->fwlrole == 1 && 3349 r1->connected && r1->band == RTW89_BAND_2G) { 3350 ch = r1->ch; 3351 bw = r1->bw; 3352 break; 3353 } else if (ver->fwlrole == 2 && 3354 r2->connected && r2->band == RTW89_BAND_2G) { 3355 ch = r2->ch; 3356 bw = r2->bw; 3357 break; 3358 } else if (ver->fwlrole == 7 && 3359 r7->connected && r7->band == RTW89_BAND_2G) { 3360 ch = r7->ch; 3361 bw = r7->bw; 3362 break; 3363 } else if (ver->fwlrole == 8 && 3364 rlink->connected && rlink->rf_band == RTW89_BAND_2G) { 3365 ch = rlink->ch; 3366 bw = rlink->bw; 3367 break; 3368 } 3369 } 3370 } 3371 3372 switch (bw) { 3373 case RTW89_CHANNEL_WIDTH_20: 3374 bw = 20 + chip->afh_guard_ch * 2; 3375 break; 3376 case RTW89_CHANNEL_WIDTH_40: 3377 bw = 40 + chip->afh_guard_ch * 2; 3378 break; 3379 case RTW89_CHANNEL_WIDTH_5: 3380 bw = 5 + chip->afh_guard_ch * 2; 3381 break; 3382 case RTW89_CHANNEL_WIDTH_10: 3383 bw = 10 + chip->afh_guard_ch * 2; 3384 break; 3385 default: 3386 bw = 0; 3387 en = false; /* turn off AFH info if BW > 40 */ 3388 break; 3389 } 3390 3391 if (wl->afh_info.en == en && 3392 wl->afh_info.ch == ch && 3393 wl->afh_info.bw == bw && 3394 b->profile_cnt.last == b->profile_cnt.now) { 3395 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3396 "[BTC], %s(): return because no change!\n", 3397 __func__); 3398 return; 3399 } 3400 3401 wl->afh_info.en = en; 3402 wl->afh_info.ch = ch; 3403 wl->afh_info.bw = bw; 3404 3405 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3); 3406 3407 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3408 "[BTC], %s(): en=%d, ch=%d, bw=%d\n", 3409 __func__, en, ch, bw); 3410 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; 3411 } 3412 3413 static void _set_bt_afh_info_v1(struct rtw89_dev *rtwdev) 3414 { 3415 const struct rtw89_chip_info *chip = rtwdev->chip; 3416 struct rtw89_btc *btc = &rtwdev->btc; 3417 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3418 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 3419 struct rtw89_btc_wl_afh_info *wl_afh = &wl->afh_info; 3420 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3421 struct rtw89_btc_wl_rlink *rlink; 3422 u8 en = 0, ch = 0, bw = 0, buf[3] = {}; 3423 u8 i, j, link_mode; 3424 3425 if (btc->manual_ctrl || wl->status.map.scan) 3426 return; 3427 3428 link_mode = wl_rinfo->link_mode; 3429 3430 for (i = 0; i < btc->ver->max_role_num; i++) { 3431 for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) { 3432 if (wl->status.map.rf_off || bt->whql_test || 3433 link_mode == BTC_WLINK_NOLINK || 3434 link_mode == BTC_WLINK_5G) 3435 break; 3436 3437 rlink = &wl_rinfo->rlink[i][j]; 3438 3439 /* Don't care no-connected/non-2G-band role */ 3440 if (!rlink->connected || !rlink->active || 3441 rlink->rf_band != RTW89_BAND_2G) 3442 continue; 3443 3444 en = 1; 3445 ch = rlink->ch; 3446 bw = rlink->bw; 3447 3448 if (link_mode == BTC_WLINK_2G_MCC && 3449 (rlink->role == RTW89_WIFI_ROLE_AP || 3450 rlink->role == RTW89_WIFI_ROLE_P2P_GO || 3451 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) { 3452 /* for 2.4G MCC, take role = ap/go/gc */ 3453 break; 3454 } else if (link_mode != BTC_WLINK_2G_SCC || 3455 rlink->bw == RTW89_CHANNEL_WIDTH_40) { 3456 /* for 2.4G scc, take bw = 40M */ 3457 break; 3458 } 3459 } 3460 } 3461 3462 /* default AFH channel sapn = center-ch +- 6MHz */ 3463 switch (bw) { 3464 case RTW89_CHANNEL_WIDTH_20: 3465 if (btc->dm.freerun || btc->dm.fddt_train) 3466 bw = 48; 3467 else 3468 bw = 20 + chip->afh_guard_ch * 2; 3469 break; 3470 case RTW89_CHANNEL_WIDTH_40: 3471 if (btc->dm.freerun) 3472 bw = 40 + chip->afh_guard_ch * 2; 3473 else 3474 bw = 40; 3475 break; 3476 case RTW89_CHANNEL_WIDTH_5: 3477 bw = 5 + chip->afh_guard_ch * 2; 3478 break; 3479 case RTW89_CHANNEL_WIDTH_10: 3480 bw = 10 + chip->afh_guard_ch * 2; 3481 break; 3482 default: 3483 en = false; /* turn off AFH info if invalid BW */ 3484 bw = 0; 3485 ch = 0; 3486 break; 3487 } 3488 3489 if (!en || ch > 14 || ch == 0) { 3490 en = false; 3491 bw = 0; 3492 ch = 0; 3493 } 3494 3495 if (wl_afh->en == en && 3496 wl_afh->ch == ch && 3497 wl_afh->bw == bw && 3498 (!bt->enable.now || bt->enable.last)) 3499 return; 3500 3501 wl_afh->en = buf[0]; 3502 wl_afh->ch = buf[1]; 3503 wl_afh->bw = buf[2]; 3504 3505 if (_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3)) { 3506 rtw89_debug(rtwdev, RTW89_DBG_BTC, 3507 "[BTC], %s(): en=%d, ch=%d, bw=%d\n", 3508 __func__, en, ch, bw); 3509 3510 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++; 3511 } 3512 } 3513 3514 static void _set_bt_afh_info(struct rtw89_dev *rtwdev) 3515 { 3516 if (rtwdev->chip->chip_id == RTL8922A) 3517 _set_bt_afh_info_v1(rtwdev); 3518 else 3519 _set_bt_afh_info_v0(rtwdev); 3520 } 3521 3522 static bool _check_freerun(struct rtw89_dev *rtwdev) 3523 { 3524 struct rtw89_btc *btc = &rtwdev->btc; 3525 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 3526 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 3527 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 3528 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 3529 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 3530 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 3531 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 3532 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 3533 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc; 3534 union rtw89_btc_module_info *md = &btc->mdinfo; 3535 const struct rtw89_btc_ver *ver = btc->ver; 3536 u8 isolation, connect_cnt = 0; 3537 3538 if (ver->fcxinit == 7) 3539 isolation = md->md_v7.ant.isolation; 3540 else 3541 isolation = md->md.ant.isolation; 3542 3543 if (ver->fwlrole == 0) 3544 connect_cnt = wl_rinfo->connect_cnt; 3545 else if (ver->fwlrole == 1) 3546 connect_cnt = wl_rinfo_v1->connect_cnt; 3547 else if (ver->fwlrole == 2) 3548 connect_cnt = wl_rinfo_v2->connect_cnt; 3549 else if (ver->fwlrole == 7) 3550 connect_cnt = wl_rinfo_v7->connect_cnt; 3551 else if (ver->fwlrole == 8) 3552 connect_cnt = wl_rinfo_v8->connect_cnt; 3553 3554 if (btc->ant_type == BTC_ANT_SHARED) { 3555 btc->dm.trx_para_level = 0; 3556 return false; 3557 } 3558 3559 /* The below is dedicated antenna case */ 3560 if (connect_cnt > BTC_TDMA_WLROLE_MAX) { 3561 btc->dm.trx_para_level = 5; 3562 return true; 3563 } 3564 3565 if (bt_linfo->profile_cnt.now == 0) { 3566 btc->dm.trx_para_level = 5; 3567 return true; 3568 } 3569 3570 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) { 3571 btc->dm.trx_para_level = 5; 3572 return true; 3573 } 3574 3575 /* TODO get isolation by BT psd */ 3576 if (isolation >= BTC_FREERUN_ANTISO_MIN) { 3577 btc->dm.trx_para_level = 5; 3578 return true; 3579 } 3580 3581 if (!wl->status.map.busy) {/* wl idle -> freerun */ 3582 btc->dm.trx_para_level = 5; 3583 return true; 3584 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */ 3585 btc->dm.trx_para_level = 0; 3586 return false; 3587 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 3588 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) { 3589 btc->dm.trx_para_level = 6; 3590 return true; 3591 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) { 3592 btc->dm.trx_para_level = 7; 3593 return true; 3594 } 3595 btc->dm.trx_para_level = 0; 3596 return false; 3597 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) { 3598 if (bt_linfo->rssi > 28) { 3599 btc->dm.trx_para_level = 6; 3600 return true; 3601 } 3602 } 3603 3604 btc->dm.trx_para_level = 0; 3605 return false; 3606 } 3607 3608 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; }) 3609 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; }) 3610 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; }) 3611 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; }) 3612 3613 struct btc_btinfo_lb2 { 3614 u8 connect: 1; 3615 u8 sco_busy: 1; 3616 u8 inq_pag: 1; 3617 u8 acl_busy: 1; 3618 u8 hfp: 1; 3619 u8 hid: 1; 3620 u8 a2dp: 1; 3621 u8 pan: 1; 3622 }; 3623 3624 struct btc_btinfo_lb3 { 3625 u8 retry: 4; 3626 u8 cqddr: 1; 3627 u8 inq: 1; 3628 u8 mesh_busy: 1; 3629 u8 pag: 1; 3630 }; 3631 3632 struct btc_btinfo_hb0 { 3633 s8 rssi; 3634 }; 3635 3636 struct btc_btinfo_hb1 { 3637 u8 ble_connect: 1; 3638 u8 reinit: 1; 3639 u8 relink: 1; 3640 u8 igno_wl: 1; 3641 u8 voice: 1; 3642 u8 ble_scan: 1; 3643 u8 role_sw: 1; 3644 u8 multi_link: 1; 3645 }; 3646 3647 struct btc_btinfo_hb2 { 3648 u8 pan_active: 1; 3649 u8 afh_update: 1; 3650 u8 a2dp_active: 1; 3651 u8 slave: 1; 3652 u8 hid_slot: 2; 3653 u8 hid_cnt: 2; 3654 }; 3655 3656 struct btc_btinfo_hb3 { 3657 u8 a2dp_bitpool: 6; 3658 u8 tx_3m: 1; 3659 u8 a2dp_sink: 1; 3660 }; 3661 3662 union btc_btinfo { 3663 u8 val; 3664 struct btc_btinfo_lb2 lb2; 3665 struct btc_btinfo_lb3 lb3; 3666 struct btc_btinfo_hb0 hb0; 3667 struct btc_btinfo_hb1 hb1; 3668 struct btc_btinfo_hb2 hb2; 3669 struct btc_btinfo_hb3 hb3; 3670 }; 3671 3672 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type, 3673 enum btc_reason_and_action action) 3674 { 3675 const struct rtw89_chip_info *chip = rtwdev->chip; 3676 3677 chip->ops->btc_set_policy(rtwdev, policy_type); 3678 _fw_set_policy(rtwdev, policy_type, action); 3679 } 3680 3681 #define BTC_B1_MAX 250 /* unit ms */ 3682 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type) 3683 { 3684 struct rtw89_btc *btc = &rtwdev->btc; 3685 struct rtw89_btc_dm *dm = &btc->dm; 3686 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 3687 struct rtw89_btc_fbtc_slot *s = dm->slot.v1; 3688 u8 type; 3689 u32 tbl_w1, tbl_b1, tbl_b4; 3690 3691 if (btc->ant_type == BTC_ANT_SHARED) { 3692 if (btc->cx.wl.status.map._4way) 3693 tbl_w1 = cxtbl[1]; 3694 else 3695 tbl_w1 = cxtbl[8]; 3696 tbl_b1 = cxtbl[3]; 3697 tbl_b4 = cxtbl[3]; 3698 } else { 3699 tbl_w1 = cxtbl[16]; 3700 tbl_b1 = cxtbl[17]; 3701 tbl_b4 = cxtbl[17]; 3702 } 3703 3704 type = (u8)((policy_type & BTC_CXP_MASK) >> 8); 3705 btc->bt_req_en = false; 3706 3707 switch (type) { 3708 case BTC_CXP_USERDEF0: 3709 *t = t_def[CXTD_OFF]; 3710 s[CXST_OFF] = s_def[CXST_OFF]; 3711 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 3712 btc->update_policy_force = true; 3713 break; 3714 case BTC_CXP_OFF: /* TDMA off */ 3715 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 3716 *t = t_def[CXTD_OFF]; 3717 s[CXST_OFF] = s_def[CXST_OFF]; 3718 3719 switch (policy_type) { 3720 case BTC_CXP_OFF_BT: 3721 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 3722 break; 3723 case BTC_CXP_OFF_WL: 3724 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 3725 break; 3726 case BTC_CXP_OFF_EQ0: 3727 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 3728 break; 3729 case BTC_CXP_OFF_EQ1: 3730 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 3731 break; 3732 case BTC_CXP_OFF_EQ2: 3733 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]); 3734 break; 3735 case BTC_CXP_OFF_EQ3: 3736 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]); 3737 break; 3738 case BTC_CXP_OFF_BWB0: 3739 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 3740 break; 3741 case BTC_CXP_OFF_BWB1: 3742 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 3743 break; 3744 case BTC_CXP_OFF_BWB3: 3745 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 3746 break; 3747 } 3748 break; 3749 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 3750 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 3751 *t = t_def[CXTD_OFF_B2]; 3752 s[CXST_OFF] = s_def[CXST_OFF]; 3753 switch (policy_type) { 3754 case BTC_CXP_OFFB_BWB0: 3755 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 3756 break; 3757 } 3758 break; 3759 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 3760 btc->bt_req_en = true; 3761 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3762 *t = t_def[CXTD_OFF_EXT]; 3763 switch (policy_type) { 3764 case BTC_CXP_OFFE_DEF: 3765 s[CXST_E2G] = s_def[CXST_E2G]; 3766 s[CXST_E5G] = s_def[CXST_E5G]; 3767 s[CXST_EBT] = s_def[CXST_EBT]; 3768 s[CXST_ENULL] = s_def[CXST_ENULL]; 3769 break; 3770 case BTC_CXP_OFFE_DEF2: 3771 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 3772 s[CXST_E5G] = s_def[CXST_E5G]; 3773 s[CXST_EBT] = s_def[CXST_EBT]; 3774 s[CXST_ENULL] = s_def[CXST_ENULL]; 3775 break; 3776 } 3777 break; 3778 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 3779 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3780 *t = t_def[CXTD_FIX]; 3781 switch (policy_type) { 3782 case BTC_CXP_FIX_TD3030: 3783 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3784 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3785 break; 3786 case BTC_CXP_FIX_TD5050: 3787 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3788 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 3789 break; 3790 case BTC_CXP_FIX_TD2030: 3791 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3792 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3793 break; 3794 case BTC_CXP_FIX_TD4010: 3795 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 3796 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3797 break; 3798 case BTC_CXP_FIX_TD4010ISO: 3799 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 3800 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3801 break; 3802 case BTC_CXP_FIX_TD4010ISO_DL: 3803 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 3804 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 3805 break; 3806 case BTC_CXP_FIX_TD4010ISO_UL: 3807 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 3808 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 3809 break; 3810 case BTC_CXP_FIX_TD7010: 3811 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 3812 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 3813 break; 3814 case BTC_CXP_FIX_TD2060: 3815 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3816 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3817 break; 3818 case BTC_CXP_FIX_TD3060: 3819 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3820 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3821 break; 3822 case BTC_CXP_FIX_TD2080: 3823 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3824 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 3825 break; 3826 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 3827 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3828 tbl_w1, SLOT_ISO); 3829 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3830 tbl_b1, SLOT_MIX); 3831 break; 3832 } 3833 break; 3834 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 3835 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3836 *t = t_def[CXTD_PFIX]; 3837 if (btc->cx.wl.role_info.role_map.role.ap) 3838 _tdma_set_flctrl(btc, CXFLC_QOSNULL); 3839 3840 switch (policy_type) { 3841 case BTC_CXP_PFIX_TD3030: 3842 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3843 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3844 break; 3845 case BTC_CXP_PFIX_TD5050: 3846 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3847 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 3848 break; 3849 case BTC_CXP_PFIX_TD2030: 3850 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3851 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 3852 break; 3853 case BTC_CXP_PFIX_TD2060: 3854 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3855 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3856 break; 3857 case BTC_CXP_PFIX_TD3070: 3858 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3859 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 3860 break; 3861 case BTC_CXP_PFIX_TD2080: 3862 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3863 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 3864 break; 3865 } 3866 break; 3867 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 3868 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3869 *t = t_def[CXTD_AUTO]; 3870 switch (policy_type) { 3871 case BTC_CXP_AUTO_TD50B1: 3872 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3873 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3874 break; 3875 case BTC_CXP_AUTO_TD60B1: 3876 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3877 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3878 break; 3879 case BTC_CXP_AUTO_TD20B1: 3880 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3881 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3882 break; 3883 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 3884 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3885 tbl_w1, SLOT_ISO); 3886 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3887 tbl_b1, SLOT_MIX); 3888 break; 3889 } 3890 break; 3891 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 3892 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3893 *t = t_def[CXTD_PAUTO]; 3894 switch (policy_type) { 3895 case BTC_CXP_PAUTO_TD50B1: 3896 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3897 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3898 break; 3899 case BTC_CXP_PAUTO_TD60B1: 3900 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3901 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3902 break; 3903 case BTC_CXP_PAUTO_TD20B1: 3904 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3905 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3906 break; 3907 case BTC_CXP_PAUTO_TDW1B1: 3908 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3909 tbl_w1, SLOT_ISO); 3910 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 3911 tbl_b1, SLOT_MIX); 3912 break; 3913 } 3914 break; 3915 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 3916 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3917 *t = t_def[CXTD_AUTO2]; 3918 switch (policy_type) { 3919 case BTC_CXP_AUTO2_TD3050: 3920 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3921 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3922 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3923 break; 3924 case BTC_CXP_AUTO2_TD3070: 3925 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3926 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3927 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3928 break; 3929 case BTC_CXP_AUTO2_TD5050: 3930 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3931 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3932 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3933 break; 3934 case BTC_CXP_AUTO2_TD6060: 3935 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3936 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3937 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3938 break; 3939 case BTC_CXP_AUTO2_TD2080: 3940 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3941 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3942 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3943 break; 3944 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 3945 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3946 tbl_w1, SLOT_ISO); 3947 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3948 tbl_b4, SLOT_MIX); 3949 break; 3950 } 3951 break; 3952 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 3953 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 3954 *t = t_def[CXTD_PAUTO2]; 3955 switch (policy_type) { 3956 case BTC_CXP_PAUTO2_TD3050: 3957 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3958 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3959 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3960 break; 3961 case BTC_CXP_PAUTO2_TD3070: 3962 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 3963 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 3964 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3965 break; 3966 case BTC_CXP_PAUTO2_TD5050: 3967 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 3968 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 3969 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3970 break; 3971 case BTC_CXP_PAUTO2_TD6060: 3972 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 3973 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 3974 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3975 break; 3976 case BTC_CXP_PAUTO2_TD2080: 3977 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 3978 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 3979 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 3980 break; 3981 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 3982 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 3983 tbl_w1, SLOT_ISO); 3984 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 3985 tbl_b4, SLOT_MIX); 3986 break; 3987 } 3988 break; 3989 } 3990 } 3991 EXPORT_SYMBOL(rtw89_btc_set_policy); 3992 3993 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) 3994 { 3995 struct rtw89_btc *btc = &rtwdev->btc; 3996 struct rtw89_btc_dm *dm = &btc->dm; 3997 struct rtw89_btc_fbtc_tdma *t = &dm->tdma; 3998 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1; 3999 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 4000 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc; 4001 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc; 4002 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4003 u8 type, null_role; 4004 u32 tbl_w1, tbl_b1, tbl_b4; 4005 u16 dur_2; 4006 4007 if (wl->status.map.lps) { 4008 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 4009 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 4010 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 4011 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 4012 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4013 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4014 } 4015 4016 type = FIELD_GET(BTC_CXP_MASK, policy_type); 4017 4018 if (btc->ant_type == BTC_ANT_SHARED) { 4019 if (btc->cx.wl.status.map._4way) 4020 tbl_w1 = cxtbl[1]; 4021 else if (hid->exist && hid->type == BTC_HID_218) 4022 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */ 4023 else 4024 tbl_w1 = cxtbl[8]; 4025 4026 if (dm->leak_ap && 4027 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) { 4028 tbl_b1 = cxtbl[3]; 4029 tbl_b4 = cxtbl[3]; 4030 } else if (hid->exist && hid->type == BTC_HID_218) { 4031 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */ 4032 tbl_b4 = cxtbl[4]; 4033 } else { 4034 tbl_b1 = cxtbl[2]; 4035 tbl_b4 = cxtbl[2]; 4036 } 4037 } else { 4038 tbl_b1 = cxtbl[17]; 4039 tbl_b4 = cxtbl[17]; 4040 4041 if (wl->bg_mode) 4042 tbl_w1 = cxtbl[8]; 4043 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) && 4044 hid->exist) 4045 tbl_w1 = cxtbl[19]; 4046 else 4047 tbl_w1 = cxtbl[16]; 4048 } 4049 4050 switch (type) { 4051 case BTC_CXP_USERDEF0: 4052 btc->update_policy_force = true; 4053 *t = t_def[CXTD_OFF]; 4054 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4055 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4056 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 4057 break; 4058 case BTC_CXP_OFF: /* TDMA off */ 4059 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 4060 *t = t_def[CXTD_OFF]; 4061 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4062 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4063 4064 switch (policy_type) { 4065 case BTC_CXP_OFF_BT: 4066 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]); 4067 break; 4068 case BTC_CXP_OFF_WL: 4069 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 4070 break; 4071 case BTC_CXP_OFF_WL2: 4072 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); 4073 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 4074 break; 4075 case BTC_CXP_OFF_EQ0: 4076 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 4077 _slot_set_type(btc, CXST_OFF, SLOT_ISO); 4078 break; 4079 case BTC_CXP_OFF_EQ1: 4080 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]); 4081 break; 4082 case BTC_CXP_OFF_EQ2: 4083 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); 4084 break; 4085 case BTC_CXP_OFF_EQ3: 4086 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); 4087 break; 4088 case BTC_CXP_OFF_EQ4: 4089 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]); 4090 break; 4091 case BTC_CXP_OFF_EQ5: 4092 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]); 4093 break; 4094 case BTC_CXP_OFF_BWB0: 4095 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); 4096 break; 4097 case BTC_CXP_OFF_BWB1: 4098 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 4099 break; 4100 case BTC_CXP_OFF_BWB2: 4101 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]); 4102 break; 4103 case BTC_CXP_OFF_BWB3: 4104 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]); 4105 break; 4106 default: 4107 break; 4108 } 4109 break; 4110 case BTC_CXP_OFFB: /* TDMA off + beacon protect */ 4111 _write_scbd(rtwdev, BTC_WSCB_TDMA, false); 4112 *t = t_def[CXTD_OFF_B2]; 4113 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4114 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4115 4116 switch (policy_type) { 4117 case BTC_CXP_OFFB_BWB0: 4118 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]); 4119 break; 4120 default: 4121 break; 4122 } 4123 break; 4124 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ 4125 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4126 *t = t_def[CXTD_OFF_EXT]; 4127 4128 /* To avoid wl-s0 tx break by hid/hfp tx */ 4129 if (hid->exist || hfp->exist) 4130 tbl_w1 = cxtbl[16]; 4131 4132 dur_2 = dm->e2g_slot_limit; 4133 4134 switch (policy_type) { 4135 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */ 4136 _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_ISO); 4137 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4138 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4139 _slot_set_dur(btc, CXST_EBT, dur_2); 4140 break; 4141 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */ 4142 _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_ISO); 4143 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4144 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4145 _slot_set_dur(btc, CXST_EBT, dur_2); 4146 break; 4147 case BTC_CXP_OFFE_DEF: 4148 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur, 4149 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype); 4150 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 4151 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 4152 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4153 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4154 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 4155 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 4156 _slot_set_dur(btc, CXST_EBT, dur_2); 4157 break; 4158 case BTC_CXP_OFFE_DEF2: 4159 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); 4160 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 4161 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 4162 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, 4163 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4164 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, 4165 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); 4166 _slot_set_dur(btc, CXST_EBT, dur_2); 4167 break; 4168 case BTC_CXP_OFFE_2GBWMIXB: 4169 if (a2dp->exist) 4170 _slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX); 4171 else 4172 _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX); 4173 _slot_set_le(btc, CXST_EBT, cpu_to_le16(40), 4174 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); 4175 _slot_set_dur(btc, CXST_EBT, dur_2); 4176 break; 4177 case BTC_CXP_OFFE_WL: /* for 4-way */ 4178 _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX); 4179 _slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX); 4180 break; 4181 default: 4182 break; 4183 } 4184 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, 4185 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); 4186 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, 4187 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); 4188 break; 4189 case BTC_CXP_FIX: /* TDMA Fix-Slot */ 4190 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4191 *t = t_def[CXTD_FIX]; 4192 4193 switch (policy_type) { 4194 case BTC_CXP_FIX_TD3030: 4195 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4196 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4197 break; 4198 case BTC_CXP_FIX_TD5050: 4199 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4200 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 4201 break; 4202 case BTC_CXP_FIX_TD2030: 4203 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4204 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4205 break; 4206 case BTC_CXP_FIX_TD4010: 4207 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO); 4208 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 4209 break; 4210 case BTC_CXP_FIX_TD4010ISO: 4211 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO); 4212 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 4213 break; 4214 case BTC_CXP_FIX_TD4010ISO_DL: 4215 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO); 4216 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO); 4217 break; 4218 case BTC_CXP_FIX_TD4010ISO_UL: 4219 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO); 4220 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX); 4221 break; 4222 case BTC_CXP_FIX_TD7010: 4223 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO); 4224 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX); 4225 break; 4226 case BTC_CXP_FIX_TD2060: 4227 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4228 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4229 break; 4230 case BTC_CXP_FIX_TD3060: 4231 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4232 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4233 break; 4234 case BTC_CXP_FIX_TD2080: 4235 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4236 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 4237 break; 4238 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */ 4239 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4240 tbl_w1, SLOT_ISO); 4241 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4242 tbl_b1, SLOT_MIX); 4243 break; 4244 default: 4245 break; 4246 } 4247 break; 4248 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */ 4249 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4250 *t = t_def[CXTD_PFIX]; 4251 4252 switch (policy_type) { 4253 case BTC_CXP_PFIX_TD3030: 4254 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4255 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4256 break; 4257 case BTC_CXP_PFIX_TD5050: 4258 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4259 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX); 4260 break; 4261 case BTC_CXP_PFIX_TD2030: 4262 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4263 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX); 4264 break; 4265 case BTC_CXP_PFIX_TD2060: 4266 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4267 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4268 break; 4269 case BTC_CXP_PFIX_TD3070: 4270 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4271 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX); 4272 break; 4273 case BTC_CXP_PFIX_TD2080: 4274 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4275 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX); 4276 break; 4277 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */ 4278 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4279 tbl_w1, SLOT_ISO); 4280 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4281 tbl_b1, SLOT_MIX); 4282 break; 4283 default: 4284 break; 4285 } 4286 break; 4287 case BTC_CXP_AUTO: /* TDMA Auto-Slot */ 4288 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4289 *t = t_def[CXTD_AUTO]; 4290 4291 switch (policy_type) { 4292 case BTC_CXP_AUTO_TD50B1: 4293 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4294 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4295 break; 4296 case BTC_CXP_AUTO_TD60B1: 4297 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 4298 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4299 break; 4300 case BTC_CXP_AUTO_TD20B1: 4301 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4302 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4303 break; 4304 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */ 4305 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4306 tbl_w1, SLOT_ISO); 4307 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4308 tbl_b1, SLOT_MIX); 4309 break; 4310 default: 4311 break; 4312 } 4313 break; 4314 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */ 4315 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4316 *t = t_def[CXTD_PAUTO]; 4317 4318 switch (policy_type) { 4319 case BTC_CXP_PAUTO_TD50B1: 4320 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4321 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4322 break; 4323 case BTC_CXP_PAUTO_TD60B1: 4324 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 4325 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4326 break; 4327 case BTC_CXP_PAUTO_TD20B1: 4328 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4329 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4330 break; 4331 case BTC_CXP_PAUTO_TDW1B1: 4332 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4333 tbl_w1, SLOT_ISO); 4334 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4335 tbl_b1, SLOT_MIX); 4336 break; 4337 default: 4338 break; 4339 } 4340 break; 4341 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */ 4342 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4343 *t = t_def[CXTD_AUTO2]; 4344 4345 switch (policy_type) { 4346 case BTC_CXP_AUTO2_TD3050: 4347 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4348 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4349 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 4350 break; 4351 case BTC_CXP_AUTO2_TD3070: 4352 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4353 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4354 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 4355 break; 4356 case BTC_CXP_AUTO2_TD5050: 4357 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4358 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4359 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 4360 break; 4361 case BTC_CXP_AUTO2_TD6060: 4362 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 4363 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4364 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 4365 break; 4366 case BTC_CXP_AUTO2_TD2080: 4367 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4368 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4369 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 4370 break; 4371 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */ 4372 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4373 tbl_w1, SLOT_ISO); 4374 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4375 tbl_b1, SLOT_MIX); 4376 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 4377 tbl_b4, SLOT_MIX); 4378 break; 4379 default: 4380 break; 4381 } 4382 break; 4383 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */ 4384 _write_scbd(rtwdev, BTC_WSCB_TDMA, true); 4385 *t = t_def[CXTD_PAUTO2]; 4386 4387 switch (policy_type) { 4388 case BTC_CXP_PAUTO2_TD3050: 4389 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4390 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4391 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 4392 break; 4393 case BTC_CXP_PAUTO2_TD3070: 4394 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO); 4395 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4396 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX); 4397 break; 4398 case BTC_CXP_PAUTO2_TD5050: 4399 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO); 4400 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4401 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX); 4402 break; 4403 case BTC_CXP_PAUTO2_TD6060: 4404 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO); 4405 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4406 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX); 4407 break; 4408 case BTC_CXP_PAUTO2_TD2080: 4409 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO); 4410 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX); 4411 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX); 4412 break; 4413 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */ 4414 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1], 4415 tbl_w1, SLOT_ISO); 4416 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1], 4417 tbl_b1, SLOT_MIX); 4418 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4], 4419 tbl_b4, SLOT_MIX); 4420 break; 4421 default: 4422 break; 4423 } 4424 break; 4425 } 4426 4427 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) { 4428 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) | 4429 FIELD_PREP(0xf0, dm->wl_scc.null_role2); 4430 _tdma_set_flctrl_role(btc, null_role); 4431 } 4432 4433 /* enter leak_slot after each null-1 */ 4434 if (dm->leak_ap && dm->tdma.leak_n > 1) 4435 _tdma_set_lek(btc, 1); 4436 4437 if (dm->tdma_instant_excute) { 4438 btc->dm.tdma.option_ctrl |= BIT(0); 4439 btc->update_policy_force = true; 4440 } 4441 } 4442 EXPORT_SYMBOL(rtw89_btc_set_policy_v1); 4443 4444 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map, 4445 u8 tx_val, u8 rx_val) 4446 { 4447 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 4448 struct rtw89_mac_ax_plt plt; 4449 4450 plt.tx = tx_val; 4451 plt.rx = rx_val; 4452 4453 if (rtwdev->btc.ver->fwlrole == 8) { 4454 plt.band = wl->pta_req_mac; 4455 if (wl->bt_polut_type[plt.band] == tx_val) 4456 return; 4457 4458 wl->bt_polut_type[plt.band] = tx_val; 4459 rtw89_mac_cfg_plt(rtwdev, &plt); 4460 } else { 4461 plt.band = RTW89_MAC_0; 4462 4463 if (phy_map & BTC_PHY_0) 4464 rtw89_mac_cfg_plt(rtwdev, &plt); 4465 4466 if (!rtwdev->dbcc_en) 4467 return; 4468 4469 plt.band = RTW89_MAC_1; 4470 if (phy_map & BTC_PHY_1) 4471 rtw89_mac_cfg_plt(rtwdev, &plt); 4472 } 4473 } 4474 4475 static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec, 4476 u8 phy_map, u8 type) 4477 { 4478 struct rtw89_btc *btc = &rtwdev->btc; 4479 struct rtw89_btc_dm *dm = &btc->dm; 4480 struct rtw89_btc_cx *cx = &btc->cx; 4481 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4482 struct rtw89_btc_bt_info *bt = &cx->bt; 4483 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4484 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0; 4485 bool dbcc_chg = false; 4486 u32 ant_path_type; 4487 4488 ant_path_type = ((phy_map << 8) + type); 4489 4490 if (btc->ver->fwlrole == 1) 4491 dbcc_chg = wl->role_info_v1.dbcc_chg; 4492 else if (btc->ver->fwlrole == 2) 4493 dbcc_chg = wl->role_info_v2.dbcc_chg; 4494 else if (btc->ver->fwlrole == 7) 4495 dbcc_chg = wl->role_info_v7.dbcc_chg; 4496 else if (btc->ver->fwlrole == 8) 4497 dbcc_chg = wl->role_info_v8.dbcc_chg; 4498 4499 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF || 4500 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE || 4501 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg) 4502 force_exec = FC_EXEC; 4503 4504 if (!force_exec && ant_path_type == dm->set_ant_path) { 4505 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4506 "[BTC], %s(): return by no change!!\n", 4507 __func__); 4508 return; 4509 } else if (bt->rfk_info.map.run) { 4510 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4511 "[BTC], %s(): return by bt rfk!!\n", __func__); 4512 return; 4513 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 4514 wl->rfk_info.state != BTC_WRFK_STOP) { 4515 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4516 "[BTC], %s(): return by wl rfk!!\n", __func__); 4517 return; 4518 } 4519 4520 dm->set_ant_path = ant_path_type; 4521 4522 rtw89_debug(rtwdev, 4523 RTW89_DBG_BTC, 4524 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 4525 __func__, phy_map, dm->set_ant_path & 0xff); 4526 4527 switch (type) { 4528 case BTC_ANT_WPOWERON: 4529 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 4530 break; 4531 case BTC_ANT_WINIT: 4532 if (bt->enable.now) 4533 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 4534 else 4535 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 4536 4537 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4538 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT); 4539 break; 4540 case BTC_ANT_WONLY: 4541 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 4542 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4543 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 4544 break; 4545 case BTC_ANT_WOFF: 4546 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 4547 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 4548 break; 4549 case BTC_ANT_W2G: 4550 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4551 if (rtwdev->dbcc_en) { 4552 for (i = 0; i < RTW89_PHY_NUM; i++) { 4553 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G); 4554 4555 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 4556 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI; 4557 /* BT should control by GNT_BT if WL_2G at S0 */ 4558 if (i == 1 && 4559 wl_dinfo->real_band[0] == RTW89_BAND_2G && 4560 wl_dinfo->real_band[1] == RTW89_BAND_5G) 4561 gnt_bt_ctrl = BTC_GNT_HW; 4562 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl); 4563 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE; 4564 _set_bt_plut(rtwdev, BIT(i), 4565 plt_ctrl, plt_ctrl); 4566 } 4567 } else { 4568 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 4569 _set_bt_plut(rtwdev, BTC_PHY_ALL, 4570 BTC_PLT_BT, BTC_PLT_BT); 4571 } 4572 break; 4573 case BTC_ANT_W5G: 4574 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4575 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW); 4576 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 4577 break; 4578 case BTC_ANT_W25G: 4579 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4580 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW); 4581 _set_bt_plut(rtwdev, BTC_PHY_ALL, 4582 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 4583 break; 4584 case BTC_ANT_FREERUN: 4585 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4586 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI); 4587 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); 4588 break; 4589 case BTC_ANT_WRFK: 4590 case BTC_ANT_WRFK2: 4591 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); 4592 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); 4593 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 4594 break; 4595 case BTC_ANT_BRFK: 4596 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT); 4597 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI); 4598 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); 4599 break; 4600 default: 4601 break; 4602 } 4603 } 4604 4605 static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec, 4606 u8 phy_map, u8 type) 4607 { 4608 struct rtw89_btc *btc = &rtwdev->btc; 4609 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4610 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4611 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 4612 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type); 4613 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 4614 struct rtw89_btc_dm *dm = &btc->dm; 4615 u8 gwl = BTC_GNT_HW; 4616 4617 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF || 4618 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE || 4619 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg) 4620 force_exec = FC_EXEC; 4621 4622 if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC && 4623 btc->dm.wl_btg_rx == 2) 4624 force_exec = FC_EXEC; 4625 4626 if (!force_exec && ant_path_type == dm->set_ant_path) { 4627 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4628 "[BTC], %s(): return by no change!!\n", 4629 __func__); 4630 return; 4631 } else if (bt->rfk_info.map.run) { 4632 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4633 "[BTC], %s(): return by bt rfk!!\n", __func__); 4634 return; 4635 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK && 4636 wl->rfk_info.state != BTC_WRFK_STOP) { 4637 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4638 "[BTC], %s(): return by wl rfk!!\n", __func__); 4639 return; 4640 } 4641 4642 dm->set_ant_path = ant_path_type; 4643 4644 rtw89_debug(rtwdev, RTW89_DBG_BTC, 4645 "[BTC], %s(): path=0x%x, set_type=0x%x\n", 4646 __func__, phy_map, dm->set_ant_path & 0xff); 4647 4648 switch (type) { 4649 case BTC_ANT_WINIT: 4650 /* To avoid BT MP driver case (bt_enable but no mailbox) */ 4651 if (bt->enable.now && bt->run_patch_code) 4652 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI, 4653 BTC_WLACT_SW_LO); 4654 else 4655 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 4656 BTC_WLACT_SW_HI); 4657 break; 4658 case BTC_ANT_WONLY: 4659 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 4660 BTC_WLACT_SW_HI); 4661 break; 4662 case BTC_ANT_WOFF: 4663 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI, 4664 BTC_WLACT_SW_LO); 4665 break; 4666 case BTC_ANT_W2G: 4667 case BTC_ANT_W25G: 4668 if (wl_rinfo->dbcc_en) { 4669 if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G) 4670 gwl = BTC_GNT_HW; 4671 else 4672 gwl = BTC_GNT_SW_HI; 4673 _set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW); 4674 4675 if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G) 4676 gwl = BTC_GNT_HW; 4677 else 4678 gwl = BTC_GNT_SW_HI; 4679 _set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW); 4680 } else { 4681 gwl = BTC_GNT_HW; 4682 _set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW); 4683 } 4684 break; 4685 case BTC_ANT_W5G: 4686 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW); 4687 break; 4688 case BTC_ANT_FREERUN: 4689 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI, 4690 BTC_WLACT_SW_LO); 4691 break; 4692 case BTC_ANT_WRFK: 4693 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 4694 BTC_WLACT_HW); 4695 break; 4696 case BTC_ANT_WRFK2: 4697 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO, 4698 BTC_WLACT_SW_HI); /* no BT-Tx */ 4699 break; 4700 default: 4701 return; 4702 } 4703 4704 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL); 4705 } 4706 4707 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec, 4708 u8 phy_map, u8 type) 4709 { 4710 if (rtwdev->chip->chip_id == RTL8922A) 4711 _set_ant_v1(rtwdev, force_exec, phy_map, type); 4712 else 4713 _set_ant_v0(rtwdev, force_exec, phy_map, type); 4714 } 4715 4716 static void _action_wl_only(struct rtw89_dev *rtwdev) 4717 { 4718 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 4719 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY); 4720 } 4721 4722 static void _action_wl_init(struct rtw89_dev *rtwdev) 4723 { 4724 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4725 4726 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT); 4727 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT); 4728 } 4729 4730 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode) 4731 { 4732 struct rtw89_btc *btc = &rtwdev->btc; 4733 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4734 4735 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4736 4737 if (wl->status.map.rf_off || btc->dm.bt_only) { 4738 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF); 4739 } else if (wl->status.map.lps == BTC_LPS_RF_ON) { 4740 if (mode == BTC_WLINK_5G) 4741 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 4742 else 4743 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4744 } 4745 4746 if (mode == BTC_WLINK_5G) { 4747 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF); 4748 } else if (wl->status.map.lps == BTC_LPS_RF_ON) { 4749 if (btc->cx.bt.link_info.a2dp_desc.active) 4750 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 4751 else 4752 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF); 4753 } else { 4754 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF); 4755 } 4756 } 4757 4758 static void _action_freerun(struct rtw89_dev *rtwdev) 4759 { 4760 struct rtw89_btc *btc = &rtwdev->btc; 4761 4762 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4763 4764 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN); 4765 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN); 4766 4767 btc->dm.freerun = true; 4768 } 4769 4770 static void _action_bt_whql(struct rtw89_dev *rtwdev) 4771 { 4772 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4773 4774 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4775 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL); 4776 } 4777 4778 static void _action_bt_off(struct rtw89_dev *rtwdev) 4779 { 4780 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 4781 4782 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY); 4783 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF); 4784 } 4785 4786 static void _action_bt_idle(struct rtw89_dev *rtwdev) 4787 { 4788 struct rtw89_btc *btc = &rtwdev->btc; 4789 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info; 4790 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4791 4792 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4793 4794 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4795 switch (btc->cx.state_map) { 4796 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/ 4797 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */ 4798 if (b->status.map.connect) 4799 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE); 4800 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 4801 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE); 4802 else 4803 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE); 4804 break; 4805 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */ 4806 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, 4807 BTC_ACT_BT_IDLE); 4808 break; 4809 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */ 4810 _set_policy(rtwdev, BTC_CXP_FIX_TD5050, 4811 BTC_ACT_BT_IDLE); 4812 break; 4813 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */ 4814 _set_policy(rtwdev, BTC_CXP_FIX_TD7010, 4815 BTC_ACT_BT_IDLE); 4816 break; 4817 case BTC_WIDLE: /* wl-idle + bt-idle */ 4818 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE); 4819 break; 4820 } 4821 } else { /* dedicated-antenna */ 4822 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE); 4823 } 4824 } 4825 4826 static void _action_bt_hfp(struct rtw89_dev *rtwdev) 4827 { 4828 struct rtw89_btc *btc = &rtwdev->btc; 4829 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4830 4831 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4832 4833 if (btc->ant_type == BTC_ANT_SHARED) { 4834 if (btc->cx.wl.status.map._4way) { 4835 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP); 4836 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 4837 btc->cx.bt.scan_rx_low_pri = true; 4838 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP); 4839 } else { 4840 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 4841 } 4842 } else { 4843 if (wl->bg_mode) 4844 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP); 4845 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 4846 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP); 4847 else 4848 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP); 4849 } 4850 } 4851 4852 static void _action_bt_hid(struct rtw89_dev *rtwdev) 4853 { 4854 const struct rtw89_chip_info *chip = rtwdev->chip; 4855 struct rtw89_btc *btc = &rtwdev->btc; 4856 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 4857 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 4858 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc; 4859 u16 policy_type = BTC_CXP_OFF_BT; 4860 4861 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4862 4863 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 4864 if (wl->status.map._4way) { 4865 policy_type = BTC_CXP_OFF_WL; 4866 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { 4867 btc->cx.bt.scan_rx_low_pri = true; 4868 if (hid->type & BTC_HID_BLE) 4869 policy_type = BTC_CXP_OFF_BWB0; 4870 else 4871 policy_type = BTC_CXP_OFF_BWB2; 4872 } else if (hid->type == BTC_HID_218) { 4873 bt->scan_rx_low_pri = true; 4874 policy_type = BTC_CXP_OFF_BWB2; 4875 } else if (chip->para_ver == 0x1) { 4876 policy_type = BTC_CXP_OFF_BWB3; 4877 } else { 4878 policy_type = BTC_CXP_OFF_BWB1; 4879 } 4880 } else { /* dedicated-antenna */ 4881 if (wl->bg_mode) 4882 policy_type = BTC_CXP_OFF_BWB1; 4883 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) 4884 policy_type = BTC_CXP_OFF_EQ4; 4885 else 4886 policy_type = BTC_CXP_OFF_EQ3; 4887 } 4888 4889 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID); 4890 } 4891 4892 static void _action_bt_a2dp(struct rtw89_dev *rtwdev) 4893 { 4894 struct rtw89_btc *btc = &rtwdev->btc; 4895 struct rtw89_btc_dm *dm = &btc->dm; 4896 4897 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4898 4899 dm->slot_dur[CXST_W1] = 20; 4900 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 4901 4902 switch (btc->cx.state_map) { 4903 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ 4904 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); 4905 break; 4906 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ 4907 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); 4908 break; 4909 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */ 4910 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP); 4911 break; 4912 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ 4913 case BTC_WLINKING: /* wl-connecting + bt-A2DP */ 4914 if (btc->cx.wl.rfk_info.con_rfk) 4915 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP); 4916 else 4917 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP); 4918 break; 4919 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 4920 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); 4921 break; 4922 } 4923 } 4924 4925 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) 4926 { 4927 struct rtw89_btc *btc = &rtwdev->btc; 4928 4929 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4930 4931 switch (btc->cx.state_map) { 4932 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */ 4933 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK); 4934 break; 4935 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */ 4936 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK); 4937 break; 4938 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */ 4939 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK); 4940 break; 4941 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */ 4942 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); 4943 break; 4944 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ 4945 if (btc->cx.wl.rfk_info.con_rfk) 4946 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK); 4947 else 4948 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); 4949 break; 4950 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ 4951 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); 4952 break; 4953 } 4954 } 4955 4956 static void _action_bt_pan(struct rtw89_dev *rtwdev) 4957 { 4958 struct rtw89_btc *btc = &rtwdev->btc; 4959 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 4960 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 4961 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 4962 4963 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4964 4965 switch (btc->cx.state_map) { 4966 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ 4967 if (a2dp.active || !pan.exist) { 4968 btc->dm.slot_dur[CXST_W1] = 80; 4969 btc->dm.slot_dur[CXST_B1] = 20; 4970 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); 4971 } else { 4972 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); 4973 } 4974 break; 4975 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ 4976 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); 4977 break; 4978 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */ 4979 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN); 4980 break; 4981 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */ 4982 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN); 4983 break; 4984 case BTC_WLINKING: /* wl-connecting + bt-PAN */ 4985 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN); 4986 break; 4987 case BTC_WIDLE: /* wl-idle + bt-pan */ 4988 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN); 4989 break; 4990 } 4991 } 4992 4993 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) 4994 { 4995 struct rtw89_btc *btc = &rtwdev->btc; 4996 struct rtw89_btc_dm *dm = &btc->dm; 4997 4998 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 4999 5000 dm->slot_dur[CXST_W1] = 20; 5001 dm->slot_dur[CXST_B1] = BTC_B1_MAX; 5002 5003 switch (btc->cx.state_map) { 5004 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ 5005 case BTC_WIDLE: /* wl-idle + bt-A2DP */ 5006 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 5007 break; 5008 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ 5009 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID); 5010 break; 5011 5012 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ 5013 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID); 5014 break; 5015 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ 5016 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ 5017 if (btc->cx.wl.rfk_info.con_rfk) 5018 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID); 5019 else 5020 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); 5021 break; 5022 } 5023 } 5024 5025 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev) 5026 { 5027 struct rtw89_btc *btc = &rtwdev->btc; 5028 5029 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5030 5031 switch (btc->cx.state_map) { 5032 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */ 5033 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 5034 break; 5035 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */ 5036 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 5037 break; 5038 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */ 5039 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN); 5040 break; 5041 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */ 5042 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN); 5043 break; 5044 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */ 5045 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN); 5046 break; 5047 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */ 5048 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN); 5049 break; 5050 } 5051 } 5052 5053 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev) 5054 { 5055 struct rtw89_btc *btc = &rtwdev->btc; 5056 5057 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5058 5059 switch (btc->cx.state_map) { 5060 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */ 5061 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID); 5062 break; 5063 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */ 5064 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID); 5065 break; 5066 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */ 5067 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID); 5068 break; 5069 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */ 5070 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID); 5071 break; 5072 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */ 5073 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID); 5074 break; 5075 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */ 5076 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID); 5077 break; 5078 } 5079 } 5080 5081 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev) 5082 { 5083 struct rtw89_btc *btc = &rtwdev->btc; 5084 5085 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5086 5087 switch (btc->cx.state_map) { 5088 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */ 5089 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 5090 BTC_ACT_BT_A2DP_PAN_HID); 5091 break; 5092 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */ 5093 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, 5094 BTC_ACT_BT_A2DP_PAN_HID); 5095 break; 5096 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */ 5097 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, 5098 BTC_ACT_BT_A2DP_PAN_HID); 5099 break; 5100 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */ 5101 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */ 5102 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, 5103 BTC_ACT_BT_A2DP_PAN_HID); 5104 break; 5105 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */ 5106 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, 5107 BTC_ACT_BT_A2DP_PAN_HID); 5108 break; 5109 } 5110 } 5111 5112 static void _action_wl_5g(struct rtw89_dev *rtwdev) 5113 { 5114 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G); 5115 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G); 5116 } 5117 5118 static void _action_wl_other(struct rtw89_dev *rtwdev) 5119 { 5120 struct rtw89_btc *btc = &rtwdev->btc; 5121 5122 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5123 5124 if (btc->ant_type == BTC_ANT_SHARED) 5125 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER); 5126 else 5127 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER); 5128 } 5129 5130 static void _action_wl_nc(struct rtw89_dev *rtwdev) 5131 { 5132 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5133 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC); 5134 } 5135 5136 static void _action_wl_rfk(struct rtw89_dev *rtwdev) 5137 { 5138 struct rtw89_btc *btc = &rtwdev->btc; 5139 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info; 5140 5141 if (rfk.state != BTC_WRFK_START) 5142 return; 5143 5144 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", 5145 __func__, rfk.band); 5146 5147 btc->dm.tdma_instant_excute = 1; 5148 5149 if (rfk.state == BTC_WRFK_ONESHOT_START || 5150 btc->ant_type == BTC_ANT_SHARED) { 5151 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); 5152 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); 5153 } else { 5154 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); 5155 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); 5156 } 5157 } 5158 5159 static void _set_btg_ctrl(struct rtw89_dev *rtwdev) 5160 { 5161 struct rtw89_btc *btc = &rtwdev->btc; 5162 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5163 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5164 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5165 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 5166 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 5167 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info; 5168 struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info; 5169 const struct rtw89_chip_info *chip = rtwdev->chip; 5170 const struct rtw89_btc_ver *ver = btc->ver; 5171 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5172 struct rtw89_btc_dm *dm = &btc->dm; 5173 struct _wl_rinfo_now wl_rinfo; 5174 u32 is_btg = BTC_BTGCTRL_DISABLE; 5175 5176 if (btc->manual_ctrl) 5177 return; 5178 5179 if (ver->fwlrole == 0) 5180 wl_rinfo.link_mode = wl_rinfo_v0->link_mode; 5181 else if (ver->fwlrole == 1) 5182 wl_rinfo.link_mode = wl_rinfo_v1->link_mode; 5183 else if (ver->fwlrole == 2) 5184 wl_rinfo.link_mode = wl_rinfo_v2->link_mode; 5185 else if (ver->fwlrole == 7) 5186 wl_rinfo.link_mode = wl_rinfo_v7->link_mode; 5187 else if (ver->fwlrole == 8) 5188 wl_rinfo.link_mode = wl_rinfo_v8->link_mode; 5189 else 5190 return; 5191 5192 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */ 5193 if (btc->ant_type == BTC_ANT_SHARED) { 5194 if (!(bt->run_patch_code && bt->enable.now)) 5195 is_btg = BTC_BTGCTRL_DISABLE; 5196 else if (wl_rinfo.link_mode != BTC_WLINK_5G) 5197 is_btg = BTC_BTGCTRL_ENABLE; 5198 else 5199 is_btg = BTC_BTGCTRL_DISABLE; 5200 5201 /* bb call ctrl_btg() in WL FW by slot */ 5202 if (!ver->fcxosi && 5203 wl_rinfo.link_mode == BTC_WLINK_25G_MCC) 5204 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL; 5205 } 5206 5207 if (is_btg == dm->wl_btg_rx) 5208 return; 5209 else 5210 dm->wl_btg_rx = is_btg; 5211 5212 /* skip setup if btg_ctrl set by wl fw */ 5213 if (!ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE) 5214 return; 5215 5216 /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */ 5217 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ 5218 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ 5219 o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE; 5220 else 5221 o_info->btg_rx[BTC_RF_S0] = is_btg; 5222 5223 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ 5224 o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE; 5225 else 5226 o_info->btg_rx[BTC_RF_S1] = is_btg; 5227 } else { /* 2+0 or 0+2 */ 5228 o_info->btg_rx[BTC_RF_S0] = is_btg; 5229 o_info->btg_rx[BTC_RF_S1] = is_btg; 5230 } 5231 5232 if (ver->fcxosi) 5233 return; 5234 5235 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0], 5236 RTW89_PHY_0); 5237 if (chip->chip_id != RTL8922A) 5238 return; 5239 5240 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1], 5241 RTW89_PHY_1); 5242 } 5243 5244 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev) 5245 { 5246 struct rtw89_btc *btc = &rtwdev->btc; 5247 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info; 5248 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 5249 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5250 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2; 5251 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; 5252 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; 5253 const struct rtw89_chip_info *chip = rtwdev->chip; 5254 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5255 struct rtw89_btc_dm *dm = &btc->dm; 5256 u8 is_preagc, val, link_mode, dbcc_2g_phy; 5257 u8 role_ver = rtwdev->btc.ver->fwlrole; 5258 bool dbcc_en; 5259 5260 if (btc->manual_ctrl) 5261 return; 5262 5263 if (role_ver == 2) { 5264 dbcc_en = rinfo_v2->dbcc_en; 5265 link_mode = rinfo_v2->link_mode; 5266 dbcc_2g_phy = rinfo_v2->dbcc_2g_phy; 5267 } else if (role_ver == 7) { 5268 dbcc_en = rinfo_v7->dbcc_en; 5269 link_mode = rinfo_v7->link_mode; 5270 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy; 5271 } else if (role_ver == 8) { 5272 dbcc_en = rinfo_v8->dbcc_en; 5273 link_mode = rinfo_v8->link_mode; 5274 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy; 5275 } else { 5276 return; 5277 } 5278 5279 if (!(bt->run_patch_code && bt->enable.now)) { 5280 is_preagc = BTC_PREAGC_DISABLE; 5281 } else if (link_mode == BTC_WLINK_5G) { 5282 is_preagc = BTC_PREAGC_DISABLE; 5283 } else if (link_mode == BTC_WLINK_NOLINK || 5284 btc->cx.bt.link_info.profile_cnt.now == 0) { 5285 is_preagc = BTC_PREAGC_DISABLE; 5286 } else if (dm->tdma_now.type != CXTDMA_OFF && 5287 !bt_linfo->hfp_desc.exist && 5288 !bt_linfo->hid_desc.exist && 5289 dm->fddt_train == BTC_FDDT_DISABLE) { 5290 is_preagc = BTC_PREAGC_DISABLE; 5291 } else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) { 5292 is_preagc = BTC_PREAGC_DISABLE; 5293 } else if (btc->ant_type == BTC_ANT_SHARED) { 5294 is_preagc = BTC_PREAGC_DISABLE; 5295 } else { 5296 is_preagc = BTC_PREAGC_ENABLE; 5297 } 5298 5299 if (!btc->ver->fcxosi && link_mode == BTC_WLINK_25G_MCC) 5300 is_preagc = BTC_PREAGC_BB_FWCTRL; 5301 5302 if (dm->wl_pre_agc_rb != dm->wl_pre_agc && 5303 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) { 5304 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val); 5305 dm->wl_pre_agc_rb = val; 5306 } 5307 5308 if ((wl->coex_mode == BTC_MODE_NORMAL && 5309 (dm->run_reason == BTC_RSN_NTFY_INIT || 5310 dm->run_reason == BTC_RSN_NTFY_SWBAND || 5311 dm->wl_pre_agc_rb != dm->wl_pre_agc)) || 5312 is_preagc != dm->wl_pre_agc) { 5313 dm->wl_pre_agc = is_preagc; 5314 5315 if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE) 5316 return; 5317 5318 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */ 5319 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */ 5320 o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE; 5321 else 5322 o_info->nbtg_tx[BTC_RF_S0] = is_preagc; 5323 5324 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */ 5325 o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE; 5326 else 5327 o_info->nbtg_tx[BTC_RF_S1] = is_preagc; 5328 5329 } else { /* 2+0 or 0+2 */ 5330 o_info->nbtg_tx[BTC_RF_S0] = is_preagc; 5331 o_info->nbtg_tx[BTC_RF_S1] = is_preagc; 5332 } 5333 5334 if (btc->ver->fcxosi) 5335 return; 5336 5337 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0], 5338 RTW89_PHY_0); 5339 if (chip->chip_id != RTL8922A) 5340 return; 5341 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1], 5342 RTW89_PHY_1); 5343 } 5344 } 5345 5346 struct rtw89_txtime_data { 5347 struct rtw89_dev *rtwdev; 5348 int type; 5349 u32 tx_time; 5350 u8 tx_retry; 5351 u16 enable; 5352 bool reenable; 5353 }; 5354 5355 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, 5356 struct rtw89_sta_link *rtwsta_link, 5357 struct rtw89_txtime_data *iter_data) 5358 { 5359 struct rtw89_dev *rtwdev = iter_data->rtwdev; 5360 struct rtw89_btc *btc = &rtwdev->btc; 5361 struct rtw89_btc_cx *cx = &btc->cx; 5362 struct rtw89_btc_wl_info *wl = &cx->wl; 5363 struct rtw89_btc_wl_link_info *plink = NULL; 5364 u8 port = rtwvif_link->port; 5365 u32 tx_time = iter_data->tx_time; 5366 u8 tx_retry = iter_data->tx_retry; 5367 u16 enable = iter_data->enable; 5368 bool reenable = iter_data->reenable; 5369 5370 if (btc->ver->fwlrole == 8) 5371 plink = &wl->rlink_info[port][0]; 5372 else 5373 plink = &wl->link_info[port]; 5374 5375 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5376 "[BTC], %s(): port = %d\n", __func__, port); 5377 5378 if (!plink->connected) { 5379 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5380 "[BTC], %s(): connected = %d\n", 5381 __func__, plink->connected); 5382 return; 5383 } 5384 5385 /* backup the original tx time before tx-limit on */ 5386 if (reenable) { 5387 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); 5388 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); 5389 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5390 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", 5391 __func__, plink->tx_time, plink->tx_retry); 5392 } 5393 5394 /* restore the original tx time if no tx-limit */ 5395 if (!enable) { 5396 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); 5397 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, 5398 plink->tx_retry); 5399 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5400 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", 5401 __func__, plink->tx_time, plink->tx_retry); 5402 5403 } else { 5404 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); 5405 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); 5406 rtw89_debug(rtwdev, RTW89_DBG_BTC, 5407 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", 5408 __func__, tx_time, tx_retry); 5409 } 5410 } 5411 5412 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) 5413 { 5414 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 5415 struct rtw89_txtime_data *iter_data = 5416 (struct rtw89_txtime_data *)data; 5417 struct rtw89_vif_link *rtwvif_link; 5418 struct rtw89_sta_link *rtwsta_link; 5419 unsigned int link_id; 5420 5421 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 5422 rtwvif_link = rtwsta_link->rtwvif_link; 5423 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); 5424 } 5425 } 5426 5427 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) 5428 { 5429 struct rtw89_btc *btc = &rtwdev->btc; 5430 const struct rtw89_btc_ver *ver = btc->ver; 5431 struct rtw89_btc_cx *cx = &btc->cx; 5432 struct rtw89_btc_dm *dm = &btc->dm; 5433 struct rtw89_btc_wl_info *wl = &cx->wl; 5434 struct rtw89_btc_bt_info *bt = &cx->bt; 5435 struct rtw89_btc_bt_link_info *b = &bt->link_info; 5436 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 5437 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 5438 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5439 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5440 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5441 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 5442 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 5443 struct rtw89_txtime_data data = {.rtwdev = rtwdev}; 5444 u8 mode, igno_bt, tx_retry; 5445 u32 tx_time; 5446 u16 enable; 5447 bool reenable = false; 5448 5449 if (btc->manual_ctrl) 5450 return; 5451 5452 if (ver->fwlrole == 0) 5453 mode = wl_rinfo->link_mode; 5454 else if (ver->fwlrole == 1) 5455 mode = wl_rinfo_v1->link_mode; 5456 else if (ver->fwlrole == 2) 5457 mode = wl_rinfo_v2->link_mode; 5458 else if (ver->fwlrole == 7) 5459 mode = wl_rinfo_v7->link_mode; 5460 else if (ver->fwlrole == 8) 5461 mode = wl_rinfo_v8->link_mode; 5462 else 5463 return; 5464 5465 if (ver->fcxctrl == 7) 5466 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 5467 else 5468 igno_bt = btc->ctrl.ctrl.igno_bt; 5469 5470 if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 || 5471 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) { 5472 enable = 0; 5473 tx_time = BTC_MAX_TX_TIME_DEF; 5474 tx_retry = BTC_MAX_TX_RETRY_DEF; 5475 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) { 5476 enable = 1; 5477 tx_time = BTC_MAX_TX_TIME_L2; 5478 tx_retry = BTC_MAX_TX_RETRY_L1; 5479 } else if (hfp->exist || hid->exist) { 5480 enable = 1; 5481 tx_time = BTC_MAX_TX_TIME_L3; 5482 tx_retry = BTC_MAX_TX_RETRY_L1; 5483 } else { 5484 enable = 0; 5485 tx_time = BTC_MAX_TX_TIME_DEF; 5486 tx_retry = BTC_MAX_TX_RETRY_DEF; 5487 } 5488 5489 if (dm->wl_tx_limit.enable == enable && 5490 dm->wl_tx_limit.tx_time == tx_time && 5491 dm->wl_tx_limit.tx_retry == tx_retry) 5492 return; 5493 5494 if (!dm->wl_tx_limit.enable && enable) 5495 reenable = true; 5496 5497 dm->wl_tx_limit.enable = enable; 5498 dm->wl_tx_limit.tx_time = tx_time; 5499 dm->wl_tx_limit.tx_retry = tx_retry; 5500 5501 data.enable = enable; 5502 data.tx_time = tx_time; 5503 data.tx_retry = tx_retry; 5504 data.reenable = reenable; 5505 5506 ieee80211_iterate_stations_atomic(rtwdev->hw, 5507 rtw89_tx_time_iter, 5508 &data); 5509 } 5510 5511 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev) 5512 { 5513 struct rtw89_btc *btc = &rtwdev->btc; 5514 const struct rtw89_btc_ver *ver = btc->ver; 5515 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5516 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 5517 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 5518 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 5519 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 5520 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 5521 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5522 bool bt_hi_lna_rx = false; 5523 u8 mode; 5524 5525 if (ver->fwlrole == 0) 5526 mode = wl_rinfo->link_mode; 5527 else if (ver->fwlrole == 1) 5528 mode = wl_rinfo_v1->link_mode; 5529 else if (ver->fwlrole == 2) 5530 mode = wl_rinfo_v2->link_mode; 5531 else if (ver->fwlrole == 7) 5532 mode = wl_rinfo_v7->link_mode; 5533 else if (ver->fwlrole == 8) 5534 mode = wl_rinfo_v8->link_mode; 5535 else 5536 return; 5537 5538 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx) 5539 bt_hi_lna_rx = true; 5540 5541 if (bt_hi_lna_rx == bt->hi_lna_rx) 5542 return; 5543 5544 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx); 5545 } 5546 5547 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev) 5548 { 5549 struct rtw89_btc *btc = &rtwdev->btc; 5550 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5551 5552 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri)); 5553 } 5554 5555 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac) 5556 { 5557 struct rtw89_btc *btc = &rtwdev->btc; 5558 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5559 struct rtw89_btc_dm *dm = &btc->dm; 5560 u32 add; 5561 5562 if (mac == wl->pta_req_mac) 5563 return; 5564 5565 dm->ost_info.pta_req_hw_band = mac; 5566 wl->pta_req_mac = mac; 5567 wl->pta_reg_mac_chg = true; 5568 5569 if (btc->ver->fcxosi) 5570 return; 5571 5572 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) 5573 add = R_BE_BTC_CFG; 5574 else 5575 add = R_AX_BTC_CFG; 5576 5577 if (mac == RTW89_MAC_0) 5578 rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC); 5579 else 5580 rtw89_write32_set(rtwdev, add, B_AX_WL_SRC); 5581 } 5582 5583 static void _action_common(struct rtw89_dev *rtwdev) 5584 { 5585 struct rtw89_btc *btc = &rtwdev->btc; 5586 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5587 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; 5588 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map; 5589 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5590 struct rtw89_btc_dm *dm = &btc->dm; 5591 u32 bt_rom_code_id, bt_fw_ver; 5592 5593 if (btc->ver->fwlrole == 8) 5594 _wl_req_mac(rtwdev, rinfo_v8->pta_req_band); 5595 5596 _set_btg_ctrl(rtwdev); 5597 _set_wl_preagc_ctrl(rtwdev); 5598 _set_wl_tx_limit(rtwdev); 5599 _set_bt_afh_info(rtwdev); 5600 _set_bt_rx_agc(rtwdev); 5601 _set_rf_trx_para(rtwdev); 5602 _set_bt_rx_scan_pri(rtwdev); 5603 5604 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id); 5605 bt_fw_ver = bt->ver_info.fw & 0xffff; 5606 if (bt->enable.now && 5607 (bt_fw_ver == 0 || 5608 (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd))) 5609 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1); 5610 else 5611 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0); 5612 5613 if (dm->run_reason == BTC_RSN_NTFY_INIT || 5614 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE || 5615 dm->run_reason == BTC_RSN_NTFY_POWEROFF) { 5616 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 5617 5618 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF) 5619 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 5620 else 5621 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1); 5622 } 5623 5624 if (wl->scbd_change) { 5625 rtw89_mac_cfg_sb(rtwdev, wl->scbd); 5626 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n", 5627 wl->scbd); 5628 wl->scbd_change = false; 5629 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++; 5630 } 5631 5632 if (btc->ver->fcxosi) { 5633 if (memcmp(&dm->ost_info_last, &dm->ost_info, 5634 sizeof(dm->ost_info_last)) || 5635 dm->run_reason == BTC_RSN_NTFY_INIT || 5636 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) { 5637 dm->ost_info_last = dm->ost_info; 5638 _fw_set_drv_info(rtwdev, CXDRVINFO_OSI); 5639 } 5640 } 5641 btc->dm.tdma_instant_excute = 0; 5642 wl->pta_reg_mac_chg = false; 5643 } 5644 5645 static void _action_by_bt(struct rtw89_dev *rtwdev) 5646 { 5647 struct rtw89_btc *btc = &rtwdev->btc; 5648 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5649 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 5650 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 5651 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 5652 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 5653 struct rtw89_btc_dm *dm = &btc->dm; 5654 u8 profile_map = 0; 5655 5656 if (dm->freerun_chk) { 5657 _action_freerun(rtwdev); 5658 return; 5659 } 5660 5661 if (bt_linfo->hfp_desc.exist) 5662 profile_map |= BTC_BT_HFP; 5663 5664 if (bt_linfo->hid_desc.exist) 5665 profile_map |= BTC_BT_HID; 5666 5667 if (bt_linfo->a2dp_desc.exist) 5668 profile_map |= BTC_BT_A2DP; 5669 5670 if (bt_linfo->pan_desc.exist) 5671 profile_map |= BTC_BT_PAN; 5672 5673 switch (profile_map) { 5674 case BTC_BT_NOPROFILE: 5675 if (pan.active) 5676 _action_bt_pan(rtwdev); 5677 else 5678 _action_bt_idle(rtwdev); 5679 break; 5680 case BTC_BT_HFP: 5681 _action_bt_hfp(rtwdev); 5682 break; 5683 case BTC_BT_HFP | BTC_BT_HID: 5684 case BTC_BT_HID: 5685 _action_bt_hid(rtwdev); 5686 break; 5687 case BTC_BT_A2DP: 5688 if (a2dp.sink) 5689 _action_bt_a2dpsink(rtwdev); 5690 else if (bt_linfo->multi_link.now && !hid.pair_cnt) 5691 _action_bt_a2dp_pan(rtwdev); 5692 else 5693 _action_bt_a2dp(rtwdev); 5694 break; 5695 case BTC_BT_PAN: 5696 _action_bt_pan(rtwdev); 5697 break; 5698 case BTC_BT_A2DP | BTC_BT_HFP: 5699 case BTC_BT_A2DP | BTC_BT_HID: 5700 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: 5701 if (a2dp.sink) 5702 _action_bt_a2dpsink(rtwdev); 5703 else if (pan.active) 5704 _action_bt_a2dp_pan_hid(rtwdev); 5705 else 5706 _action_bt_a2dp_hid(rtwdev); 5707 break; 5708 case BTC_BT_A2DP | BTC_BT_PAN: 5709 if (a2dp.sink) 5710 _action_bt_a2dpsink(rtwdev); 5711 else 5712 _action_bt_a2dp_pan(rtwdev); 5713 break; 5714 case BTC_BT_PAN | BTC_BT_HFP: 5715 case BTC_BT_PAN | BTC_BT_HID: 5716 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID: 5717 _action_bt_pan_hid(rtwdev); 5718 break; 5719 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: 5720 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: 5721 default: 5722 if (a2dp.sink) 5723 _action_bt_a2dpsink(rtwdev); 5724 else 5725 _action_bt_a2dp_pan_hid(rtwdev); 5726 break; 5727 } 5728 } 5729 5730 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev) 5731 { 5732 _action_by_bt(rtwdev); 5733 } 5734 5735 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) 5736 { 5737 struct rtw89_btc *btc = &rtwdev->btc; 5738 u16 policy_type = BTC_CXP_OFF_BT; 5739 5740 if (btc->ant_type == BTC_ANT_SHARED) { 5741 if (btc->cx.wl.status.map._4way) 5742 policy_type = BTC_CXP_OFFE_WL; 5743 else if (btc->cx.wl.status.val & btc_scanning_map.val) 5744 policy_type = BTC_CXP_OFFE_2GBWMIXB; 5745 else if (btc->cx.bt.link_info.status.map.connect == 0) 5746 policy_type = BTC_CXP_OFFE_2GISOB; 5747 else 5748 policy_type = BTC_CXP_OFFE_2GBWISOB; 5749 } else { /* dedicated-antenna */ 5750 policy_type = BTC_CXP_OFF_EQ0; 5751 } 5752 5753 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF; 5754 5755 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G); 5756 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC); 5757 } 5758 5759 static void _action_wl_scan(struct rtw89_dev *rtwdev) 5760 { 5761 struct rtw89_btc *btc = &rtwdev->btc; 5762 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5763 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 5764 5765 if (btc->cx.state_map != BTC_WLINKING && 5766 RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { 5767 _action_wl_25g_mcc(rtwdev); 5768 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); 5769 } else if (rtwdev->dbcc_en) { 5770 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G && 5771 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G) 5772 _action_wl_5g(rtwdev); 5773 else 5774 _action_by_bt(rtwdev); 5775 } else { 5776 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G) 5777 _action_wl_5g(rtwdev); 5778 else 5779 _action_by_bt(rtwdev); 5780 } 5781 } 5782 5783 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev) 5784 { struct rtw89_btc *btc = &rtwdev->btc; 5785 5786 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5787 5788 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5789 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5790 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 5791 BTC_ACT_WL_2G_MCC); 5792 else 5793 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, 5794 BTC_ACT_WL_2G_MCC); 5795 } else { /* dedicated-antenna */ 5796 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC); 5797 } 5798 } 5799 5800 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev) 5801 { 5802 struct rtw89_btc *btc = &rtwdev->btc; 5803 5804 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5805 5806 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 5807 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5808 _set_policy(rtwdev, 5809 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC); 5810 else 5811 _set_policy(rtwdev, 5812 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC); 5813 } else { /* dedicated-antenna */ 5814 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC); 5815 } 5816 } 5817 5818 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev) 5819 { 5820 struct rtw89_btc *btc = &rtwdev->btc; 5821 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5822 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5823 struct rtw89_btc_dm *dm = &btc->dm; 5824 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 5825 u16 policy_type = BTC_CXP_OFF_BT; 5826 u32 dur; 5827 5828 if (btc->ant_type == BTC_ANT_DEDICATED) { 5829 policy_type = BTC_CXP_OFF_EQ0; 5830 } else { 5831 /* shared-antenna */ 5832 switch (wl_rinfo->mrole_type) { 5833 case BTC_WLMROLE_STA_GC: 5834 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5835 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 5836 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5837 _action_by_bt(rtwdev); 5838 return; 5839 case BTC_WLMROLE_STA_STA: 5840 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5841 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 5842 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5843 _action_by_bt(rtwdev); 5844 return; 5845 case BTC_WLMROLE_STA_GC_NOA: 5846 case BTC_WLMROLE_STA_GO: 5847 case BTC_WLMROLE_STA_GO_NOA: 5848 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5849 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 5850 dur = wl_rinfo->mrole_noa_duration; 5851 5852 if (wl->status.map._4way) { 5853 dm->wl_scc.ebt_null = 0; 5854 policy_type = BTC_CXP_OFFE_WL; 5855 } else if (bt->link_info.status.map.connect == 0) { 5856 dm->wl_scc.ebt_null = 0; 5857 policy_type = BTC_CXP_OFFE_2GISOB; 5858 } else if (bt->link_info.a2dp_desc.exist && 5859 dur < btc->bt_req_len) { 5860 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5861 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 5862 } else if (bt->link_info.a2dp_desc.exist || 5863 bt->link_info.pan_desc.exist) { 5864 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5865 policy_type = BTC_CXP_OFFE_2GBWISOB; 5866 } else { 5867 dm->wl_scc.ebt_null = 0; 5868 policy_type = BTC_CXP_OFFE_2GBWISOB; 5869 } 5870 break; 5871 default: 5872 break; 5873 } 5874 } 5875 5876 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5877 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 5878 } 5879 5880 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev) 5881 { 5882 struct rtw89_btc *btc = &rtwdev->btc; 5883 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5884 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5885 struct rtw89_btc_dm *dm = &btc->dm; 5886 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2; 5887 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; 5888 u32 dur, mrole_type, mrole_noa_duration; 5889 u16 policy_type = BTC_CXP_OFF_BT; 5890 5891 if (btc->ver->fwlrole == 2) { 5892 mrole_type = rinfo_v2->mrole_type; 5893 mrole_noa_duration = rinfo_v2->mrole_noa_duration; 5894 } else if (btc->ver->fwlrole == 7) { 5895 mrole_type = rinfo_v7->mrole_type; 5896 mrole_noa_duration = rinfo_v7->mrole_noa_duration; 5897 } else { 5898 return; 5899 } 5900 5901 if (btc->ant_type == BTC_ANT_DEDICATED) { 5902 policy_type = BTC_CXP_OFF_EQ0; 5903 } else { 5904 /* shared-antenna */ 5905 switch (mrole_type) { 5906 case BTC_WLMROLE_STA_GC: 5907 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5908 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT; 5909 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5910 _action_by_bt(rtwdev); 5911 return; 5912 case BTC_WLMROLE_STA_STA: 5913 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5914 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION; 5915 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */ 5916 _action_by_bt(rtwdev); 5917 return; 5918 case BTC_WLMROLE_STA_GC_NOA: 5919 case BTC_WLMROLE_STA_GO: 5920 case BTC_WLMROLE_STA_GO_NOA: 5921 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION; 5922 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE; 5923 dur = mrole_noa_duration; 5924 5925 if (wl->status.map._4way) { 5926 dm->wl_scc.ebt_null = 0; 5927 policy_type = BTC_CXP_OFFE_WL; 5928 } else if (bt->link_info.status.map.connect == 0) { 5929 dm->wl_scc.ebt_null = 0; 5930 policy_type = BTC_CXP_OFFE_2GISOB; 5931 } else if (bt->link_info.a2dp_desc.exist && 5932 dur < btc->bt_req_len) { 5933 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5934 policy_type = BTC_CXP_OFFE_2GBWMIXB2; 5935 } else if (bt->link_info.a2dp_desc.exist || 5936 bt->link_info.pan_desc.exist) { 5937 dm->wl_scc.ebt_null = 1; /* tx null at EBT */ 5938 policy_type = BTC_CXP_OFFE_2GBWISOB; 5939 } else { 5940 dm->wl_scc.ebt_null = 0; 5941 policy_type = BTC_CXP_OFFE_2GBWISOB; 5942 } 5943 break; 5944 default: 5945 break; 5946 } 5947 } 5948 5949 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5950 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 5951 } 5952 5953 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev) 5954 { 5955 struct rtw89_btc *btc = &rtwdev->btc; 5956 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 5957 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 5958 struct rtw89_btc_dm *dm = &btc->dm; 5959 u16 policy_type = BTC_CXP_OFF_BT; 5960 5961 if (btc->ant_type == BTC_ANT_SHARED) { 5962 if (wl->status.map._4way) 5963 policy_type = BTC_CXP_OFFE_WL; 5964 else if (bt->link_info.status.map.connect == 0) 5965 policy_type = BTC_CXP_OFFE_2GISOB; 5966 else 5967 policy_type = BTC_CXP_OFFE_2GBWISOB; 5968 } else { 5969 policy_type = BTC_CXP_OFF_EQ0; 5970 } 5971 5972 dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF; 5973 5974 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5975 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC); 5976 } 5977 5978 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev) 5979 { 5980 struct rtw89_btc *btc = &rtwdev->btc; 5981 5982 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 5983 5984 if (btc->ant_type == BTC_ANT_SHARED) { 5985 if (btc->cx.bt.link_info.profile_cnt.now == 0) 5986 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2, 5987 BTC_ACT_WL_2G_AP); 5988 else 5989 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP); 5990 } else {/* dedicated-antenna */ 5991 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP); 5992 } 5993 } 5994 5995 static void _action_wl_2g_go(struct rtw89_dev *rtwdev) 5996 { 5997 struct rtw89_btc *btc = &rtwdev->btc; 5998 5999 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6000 6001 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6002 if (btc->cx.bt.link_info.profile_cnt.now == 0) 6003 _set_policy(rtwdev, 6004 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO); 6005 else 6006 _set_policy(rtwdev, 6007 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO); 6008 } else { /* dedicated-antenna */ 6009 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO); 6010 } 6011 } 6012 6013 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev) 6014 { 6015 struct rtw89_btc *btc = &rtwdev->btc; 6016 6017 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6018 6019 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6020 _action_by_bt(rtwdev); 6021 } else {/* dedicated-antenna */ 6022 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC); 6023 } 6024 } 6025 6026 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev) 6027 { 6028 struct rtw89_btc *btc = &rtwdev->btc; 6029 6030 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); 6031 6032 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */ 6033 if (btc->cx.bt.link_info.profile_cnt.now == 0) 6034 _set_policy(rtwdev, 6035 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN); 6036 else 6037 _set_policy(rtwdev, 6038 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN); 6039 } else { /* dedicated-antenna */ 6040 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN); 6041 } 6042 } 6043 6044 static u32 _read_scbd(struct rtw89_dev *rtwdev) 6045 { 6046 const struct rtw89_chip_info *chip = rtwdev->chip; 6047 struct rtw89_btc *btc = &rtwdev->btc; 6048 u32 scbd_val = 0; 6049 6050 if (!chip->scbd) 6051 return 0; 6052 6053 scbd_val = rtw89_mac_get_sb(rtwdev); 6054 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n", 6055 scbd_val); 6056 6057 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++; 6058 return scbd_val; 6059 } 6060 6061 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state) 6062 { 6063 const struct rtw89_chip_info *chip = rtwdev->chip; 6064 struct rtw89_btc *btc = &rtwdev->btc; 6065 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6066 u32 scbd_val = 0; 6067 u8 force_exec = false; 6068 6069 if (!chip->scbd) 6070 return; 6071 6072 scbd_val = state ? wl->scbd | val : wl->scbd & ~val; 6073 6074 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON) 6075 force_exec = true; 6076 6077 if (scbd_val != wl->scbd || force_exec) { 6078 wl->scbd = scbd_val; 6079 wl->scbd_change = true; 6080 } 6081 } 6082 6083 static u8 6084 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh) 6085 { 6086 const struct rtw89_chip_info *chip = rtwdev->chip; 6087 u8 next_state, tol = chip->rssi_tol; 6088 6089 if (pre_state == BTC_RSSI_ST_LOW || 6090 pre_state == BTC_RSSI_ST_STAY_LOW) { 6091 if (rssi >= (thresh + tol)) 6092 next_state = BTC_RSSI_ST_HIGH; 6093 else 6094 next_state = BTC_RSSI_ST_STAY_LOW; 6095 } else { 6096 if (rssi < thresh) 6097 next_state = BTC_RSSI_ST_LOW; 6098 else 6099 next_state = BTC_RSSI_ST_STAY_HIGH; 6100 } 6101 6102 return next_state; 6103 } 6104 6105 static 6106 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 6107 { 6108 struct rtw89_btc *btc = &rtwdev->btc; 6109 6110 btc->cx.wl.dbcc_info.real_band[phy_idx] = 6111 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ? 6112 btc->cx.wl.dbcc_info.scan_band[phy_idx] : 6113 btc->cx.wl.dbcc_info.op_band[phy_idx]; 6114 } 6115 6116 static void _update_wl_info(struct rtw89_dev *rtwdev) 6117 { 6118 struct rtw89_btc *btc = &rtwdev->btc; 6119 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6120 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 6121 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 6122 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6123 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 6124 u8 cnt_2g = 0, cnt_5g = 0, phy; 6125 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0}; 6126 bool b2g = false, b5g = false, client_joined = false; 6127 6128 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 6129 6130 for (i = 0; i < RTW89_PORT_NUM; i++) { 6131 /* check if role active? */ 6132 if (!wl_linfo[i].active) 6133 continue; 6134 6135 cnt_active++; 6136 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role; 6137 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid; 6138 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy; 6139 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band; 6140 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 6141 wl_rinfo->active_role[cnt_active - 1].connected = 0; 6142 6143 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 6144 6145 phy = wl_linfo[i].phy; 6146 6147 /* check dbcc role */ 6148 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) { 6149 wl_dinfo->role[phy] = wl_linfo[i].role; 6150 wl_dinfo->op_band[phy] = wl_linfo[i].band; 6151 _update_dbcc_band(rtwdev, phy); 6152 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 6153 } 6154 6155 if (wl_linfo[i].connected == MLME_NO_LINK) { 6156 continue; 6157 } else if (wl_linfo[i].connected == MLME_LINKING) { 6158 cnt_connecting++; 6159 } else { 6160 cnt_connect++; 6161 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6162 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 6163 wl_linfo[i].client_cnt > 1) 6164 client_joined = true; 6165 } 6166 6167 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 6168 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch; 6169 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw; 6170 wl_rinfo->active_role[cnt_active - 1].connected = 1; 6171 6172 /* only care 2 roles + BT coex */ 6173 if (wl_linfo[i].band != RTW89_BAND_2G) { 6174 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 6175 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 6176 cnt_5g++; 6177 b5g = true; 6178 } else { 6179 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 6180 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 6181 cnt_2g++; 6182 b2g = true; 6183 } 6184 } 6185 6186 wl_rinfo->connect_cnt = cnt_connect; 6187 6188 /* Be careful to change the following sequence!! */ 6189 if (cnt_connect == 0) { 6190 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6191 wl_rinfo->role_map.role.none = 1; 6192 } else if (!b2g && b5g) { 6193 wl_rinfo->link_mode = BTC_WLINK_5G; 6194 } else if (wl_rinfo->role_map.role.nan) { 6195 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 6196 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 6197 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6198 } else if (b2g && b5g && cnt_connect == 2) { 6199 if (rtwdev->dbcc_en) { 6200 switch (wl_dinfo->role[RTW89_PHY_0]) { 6201 case RTW89_WIFI_ROLE_STATION: 6202 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6203 break; 6204 case RTW89_WIFI_ROLE_P2P_GO: 6205 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6206 break; 6207 case RTW89_WIFI_ROLE_P2P_CLIENT: 6208 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6209 break; 6210 case RTW89_WIFI_ROLE_AP: 6211 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6212 break; 6213 default: 6214 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6215 break; 6216 } 6217 } else { 6218 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 6219 } 6220 } else if (!b5g && cnt_connect == 2) { 6221 if (wl_rinfo->role_map.role.station && 6222 (wl_rinfo->role_map.role.p2p_go || 6223 wl_rinfo->role_map.role.p2p_gc || 6224 wl_rinfo->role_map.role.ap)) { 6225 if (wl_2g_ch[0] == wl_2g_ch[1]) 6226 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 6227 else 6228 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6229 } else { 6230 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6231 } 6232 } else if (!b5g && cnt_connect == 1) { 6233 if (wl_rinfo->role_map.role.station) 6234 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6235 else if (wl_rinfo->role_map.role.ap) 6236 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6237 else if (wl_rinfo->role_map.role.p2p_go) 6238 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6239 else if (wl_rinfo->role_map.role.p2p_gc) 6240 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6241 else 6242 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6243 } 6244 6245 /* if no client_joined, don't care P2P-GO/AP role */ 6246 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 6247 if (!client_joined) { 6248 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 6249 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 6250 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6251 wl_rinfo->connect_cnt = 1; 6252 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 6253 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 6254 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6255 wl_rinfo->connect_cnt = 0; 6256 } 6257 } 6258 } 6259 6260 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6261 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 6262 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 6263 6264 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6265 } 6266 6267 static void _update_wl_info_v1(struct rtw89_dev *rtwdev) 6268 { 6269 struct rtw89_btc *btc = &rtwdev->btc; 6270 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6271 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 6272 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1; 6273 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6274 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 6275 u8 cnt_2g = 0, cnt_5g = 0, phy; 6276 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 6277 bool b2g = false, b5g = false, client_joined = false; 6278 u8 i; 6279 6280 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 6281 6282 for (i = 0; i < RTW89_PORT_NUM; i++) { 6283 if (!wl_linfo[i].active) 6284 continue; 6285 6286 cnt_active++; 6287 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role; 6288 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid; 6289 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy; 6290 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band; 6291 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 6292 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0; 6293 6294 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 6295 6296 phy = wl_linfo[i].phy; 6297 6298 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) { 6299 wl_dinfo->role[phy] = wl_linfo[i].role; 6300 wl_dinfo->op_band[phy] = wl_linfo[i].band; 6301 _update_dbcc_band(rtwdev, phy); 6302 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 6303 } 6304 6305 if (wl_linfo[i].connected == MLME_NO_LINK) { 6306 continue; 6307 } else if (wl_linfo[i].connected == MLME_LINKING) { 6308 cnt_connecting++; 6309 } else { 6310 cnt_connect++; 6311 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6312 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 6313 wl_linfo[i].client_cnt > 1) 6314 client_joined = true; 6315 } 6316 6317 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 6318 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch; 6319 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw; 6320 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1; 6321 6322 /* only care 2 roles + BT coex */ 6323 if (wl_linfo[i].band != RTW89_BAND_2G) { 6324 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 6325 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 6326 cnt_5g++; 6327 b5g = true; 6328 } else { 6329 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 6330 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 6331 cnt_2g++; 6332 b2g = true; 6333 } 6334 } 6335 6336 wl_rinfo->connect_cnt = cnt_connect; 6337 6338 /* Be careful to change the following sequence!! */ 6339 if (cnt_connect == 0) { 6340 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6341 wl_rinfo->role_map.role.none = 1; 6342 } else if (!b2g && b5g) { 6343 wl_rinfo->link_mode = BTC_WLINK_5G; 6344 } else if (wl_rinfo->role_map.role.nan) { 6345 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 6346 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 6347 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6348 } else if (b2g && b5g && cnt_connect == 2) { 6349 if (rtwdev->dbcc_en) { 6350 switch (wl_dinfo->role[RTW89_PHY_0]) { 6351 case RTW89_WIFI_ROLE_STATION: 6352 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6353 break; 6354 case RTW89_WIFI_ROLE_P2P_GO: 6355 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6356 break; 6357 case RTW89_WIFI_ROLE_P2P_CLIENT: 6358 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6359 break; 6360 case RTW89_WIFI_ROLE_AP: 6361 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6362 break; 6363 default: 6364 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6365 break; 6366 } 6367 } else { 6368 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 6369 } 6370 } else if (!b5g && cnt_connect == 2) { 6371 if (wl_rinfo->role_map.role.station && 6372 (wl_rinfo->role_map.role.p2p_go || 6373 wl_rinfo->role_map.role.p2p_gc || 6374 wl_rinfo->role_map.role.ap)) { 6375 if (wl_2g_ch[0] == wl_2g_ch[1]) 6376 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 6377 else 6378 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6379 } else { 6380 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6381 } 6382 } else if (!b5g && cnt_connect == 1) { 6383 if (wl_rinfo->role_map.role.station) 6384 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6385 else if (wl_rinfo->role_map.role.ap) 6386 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6387 else if (wl_rinfo->role_map.role.p2p_go) 6388 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6389 else if (wl_rinfo->role_map.role.p2p_gc) 6390 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6391 else 6392 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6393 } 6394 6395 /* if no client_joined, don't care P2P-GO/AP role */ 6396 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 6397 if (!client_joined) { 6398 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 6399 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 6400 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6401 wl_rinfo->connect_cnt = 1; 6402 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 6403 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 6404 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6405 wl_rinfo->connect_cnt = 0; 6406 } 6407 } 6408 } 6409 6410 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6411 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 6412 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 6413 6414 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6415 } 6416 6417 static void _update_wl_info_v2(struct rtw89_dev *rtwdev) 6418 { 6419 struct rtw89_btc *btc = &rtwdev->btc; 6420 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6421 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 6422 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2; 6423 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6424 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0; 6425 u8 cnt_2g = 0, cnt_5g = 0, phy; 6426 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {}; 6427 bool b2g = false, b5g = false, client_joined = false; 6428 u8 i; 6429 6430 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 6431 6432 for (i = 0; i < RTW89_PORT_NUM; i++) { 6433 if (!wl_linfo[i].active) 6434 continue; 6435 6436 cnt_active++; 6437 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role; 6438 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid; 6439 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy; 6440 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band; 6441 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa; 6442 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0; 6443 6444 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid; 6445 6446 phy = wl_linfo[i].phy; 6447 6448 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) { 6449 wl_dinfo->role[phy] = wl_linfo[i].role; 6450 wl_dinfo->op_band[phy] = wl_linfo[i].band; 6451 _update_dbcc_band(rtwdev, phy); 6452 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 6453 } 6454 6455 if (wl_linfo[i].connected == MLME_NO_LINK) { 6456 continue; 6457 } else if (wl_linfo[i].connected == MLME_LINKING) { 6458 cnt_connecting++; 6459 } else { 6460 cnt_connect++; 6461 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6462 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 6463 wl_linfo[i].client_cnt > 1) 6464 client_joined = true; 6465 } 6466 6467 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role); 6468 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch; 6469 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw; 6470 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1; 6471 6472 /* only care 2 roles + BT coex */ 6473 if (wl_linfo[i].band != RTW89_BAND_2G) { 6474 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1) 6475 wl_5g_ch[cnt_5g] = wl_linfo[i].ch; 6476 cnt_5g++; 6477 b5g = true; 6478 } else { 6479 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1) 6480 wl_2g_ch[cnt_2g] = wl_linfo[i].ch; 6481 cnt_2g++; 6482 b2g = true; 6483 } 6484 } 6485 6486 wl_rinfo->connect_cnt = cnt_connect; 6487 6488 /* Be careful to change the following sequence!! */ 6489 if (cnt_connect == 0) { 6490 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6491 wl_rinfo->role_map.role.none = 1; 6492 } else if (!b2g && b5g) { 6493 wl_rinfo->link_mode = BTC_WLINK_5G; 6494 } else if (wl_rinfo->role_map.role.nan) { 6495 wl_rinfo->link_mode = BTC_WLINK_2G_NAN; 6496 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) { 6497 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6498 } else if (b2g && b5g && cnt_connect == 2) { 6499 if (rtwdev->dbcc_en) { 6500 switch (wl_dinfo->role[RTW89_PHY_0]) { 6501 case RTW89_WIFI_ROLE_STATION: 6502 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6503 break; 6504 case RTW89_WIFI_ROLE_P2P_GO: 6505 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6506 break; 6507 case RTW89_WIFI_ROLE_P2P_CLIENT: 6508 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6509 break; 6510 case RTW89_WIFI_ROLE_AP: 6511 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6512 break; 6513 default: 6514 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6515 break; 6516 } 6517 } else { 6518 wl_rinfo->link_mode = BTC_WLINK_25G_MCC; 6519 } 6520 } else if (!b5g && cnt_connect == 2) { 6521 if (wl_rinfo->role_map.role.station && 6522 (wl_rinfo->role_map.role.p2p_go || 6523 wl_rinfo->role_map.role.p2p_gc || 6524 wl_rinfo->role_map.role.ap)) { 6525 if (wl_2g_ch[0] == wl_2g_ch[1]) 6526 wl_rinfo->link_mode = BTC_WLINK_2G_SCC; 6527 else 6528 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6529 } else { 6530 wl_rinfo->link_mode = BTC_WLINK_2G_MCC; 6531 } 6532 } else if (!b5g && cnt_connect == 1) { 6533 if (wl_rinfo->role_map.role.station) 6534 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6535 else if (wl_rinfo->role_map.role.ap) 6536 wl_rinfo->link_mode = BTC_WLINK_2G_AP; 6537 else if (wl_rinfo->role_map.role.p2p_go) 6538 wl_rinfo->link_mode = BTC_WLINK_2G_GO; 6539 else if (wl_rinfo->role_map.role.p2p_gc) 6540 wl_rinfo->link_mode = BTC_WLINK_2G_GC; 6541 else 6542 wl_rinfo->link_mode = BTC_WLINK_OTHER; 6543 } 6544 6545 /* if no client_joined, don't care P2P-GO/AP role */ 6546 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) { 6547 if (!client_joined) { 6548 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC || 6549 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) { 6550 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 6551 wl_rinfo->connect_cnt = 1; 6552 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO || 6553 wl_rinfo->link_mode == BTC_WLINK_2G_AP) { 6554 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 6555 wl_rinfo->connect_cnt = 0; 6556 } 6557 } 6558 } 6559 6560 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6561 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n", 6562 cnt_connect, cnt_connecting, wl_rinfo->link_mode); 6563 6564 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6565 } 6566 6567 #define BTC_CHK_HANG_MAX 3 6568 #define BTC_SCB_INV_VALUE GENMASK(31, 0) 6569 6570 static u8 _get_role_link_mode(u8 role) 6571 { 6572 switch (role) { 6573 case RTW89_WIFI_ROLE_STATION: 6574 return BTC_WLINK_2G_STA; 6575 case RTW89_WIFI_ROLE_P2P_GO: 6576 return BTC_WLINK_2G_GO; 6577 case RTW89_WIFI_ROLE_P2P_CLIENT: 6578 return BTC_WLINK_2G_GC; 6579 case RTW89_WIFI_ROLE_AP: 6580 return BTC_WLINK_2G_AP; 6581 default: 6582 return BTC_WLINK_OTHER; 6583 } 6584 } 6585 6586 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1, 6587 const struct rtw89_btc_chdef *r2) 6588 { 6589 if (r1->chan != r2->chan) { /* primary ch is different */ 6590 return false; 6591 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 && 6592 r2->bw == RTW89_CHANNEL_WIDTH_40) { 6593 if (r1->offset != r2->offset) 6594 return false; 6595 } 6596 return true; 6597 } 6598 6599 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch, 6600 u8 *phy, u8 *role, u8 link_cnt) 6601 { 6602 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 6603 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7; 6604 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8; 6605 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false; 6606 u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, dbcc_2g_phy, pta_req_band; 6607 6608 /* find out the 2G-PHY by connect-id ->ch */ 6609 for (j = 0; j < link_cnt; j++) { 6610 if (ch[j].center_ch <= 14) { 6611 is_2g_ch_exist = true; 6612 break; 6613 } 6614 } 6615 6616 /* If no any 2G-port exist, it's impossible because 5G-exclude */ 6617 if (!is_2g_ch_exist) 6618 return BTC_WLINK_5G; 6619 6620 dbcc_2g_cid = j; 6621 dbcc_2g_phy = phy[dbcc_2g_cid]; 6622 6623 if (dbcc_2g_phy == RTW89_PHY_1) 6624 pta_req_band = RTW89_PHY_1; 6625 else 6626 pta_req_band = RTW89_PHY_0; 6627 6628 if (rtwdev->btc.ver->fwlrole == 7) { 6629 rinfo_v7->dbcc_2g_phy = dbcc_2g_phy; 6630 } else if (rtwdev->btc.ver->fwlrole == 8) { 6631 rinfo_v8->dbcc_2g_phy = dbcc_2g_phy; 6632 rinfo_v8->pta_req_band = pta_req_band; 6633 } 6634 6635 /* connect_cnt <= 2 */ 6636 if (link_cnt < BTC_TDMA_WLROLE_MAX) 6637 return (_get_role_link_mode((role[dbcc_2g_cid]))); 6638 6639 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */ 6640 for (k = 0; k < link_cnt; k++) { 6641 if (k == dbcc_2g_cid) 6642 continue; 6643 6644 if (phy[k] == dbcc_2g_phy) { 6645 is_multi_role_in_2g_phy = true; 6646 dbcc_2g_cid2 = k; 6647 break; 6648 } 6649 } 6650 6651 /* Single-role in 2G-PHY */ 6652 if (!is_multi_role_in_2g_phy) 6653 return (_get_role_link_mode(role[dbcc_2g_cid])); 6654 6655 /* 2-role in 2G-PHY */ 6656 if (ch[dbcc_2g_cid2].center_ch > 14) 6657 return BTC_WLINK_25G_MCC; 6658 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2])) 6659 return BTC_WLINK_2G_SCC; 6660 else 6661 return BTC_WLINK_2G_MCC; 6662 } 6663 6664 static void _update_role_link_mode(struct rtw89_dev *rtwdev, 6665 bool client_joined, u32 noa) 6666 { 6667 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8; 6668 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7; 6669 u8 role_ver = rtwdev->btc.ver->fwlrole; 6670 u32 type = BTC_WLMROLE_NONE, dur = 0; 6671 u8 link_mode, connect_cnt; 6672 u32 wl_role; 6673 6674 if (role_ver == 7) { 6675 wl_role = rinfo_v7->role_map; 6676 link_mode = rinfo_v7->link_mode; 6677 connect_cnt = rinfo_v7->connect_cnt; 6678 } else if (role_ver == 8) { 6679 wl_role = rinfo_v8->role_map; 6680 link_mode = rinfo_v8->link_mode; 6681 connect_cnt = rinfo_v8->connect_cnt; 6682 } else { 6683 return; 6684 } 6685 6686 /* if no client_joined, don't care P2P-GO/AP role */ 6687 if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 6688 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) { 6689 if (link_mode == BTC_WLINK_2G_SCC) { 6690 if (role_ver == 7) { 6691 rinfo_v7->link_mode = BTC_WLINK_2G_STA; 6692 rinfo_v7->connect_cnt--; 6693 } else if (role_ver == 8) { 6694 rinfo_v8->link_mode = BTC_WLINK_2G_STA; 6695 rinfo_v8->connect_cnt--; 6696 } 6697 } else if (link_mode == BTC_WLINK_2G_GO || 6698 link_mode == BTC_WLINK_2G_AP) { 6699 if (role_ver == 7) { 6700 rinfo_v7->link_mode = BTC_WLINK_NOLINK; 6701 rinfo_v7->connect_cnt--; 6702 } else if (role_ver == 8) { 6703 rinfo_v8->link_mode = BTC_WLINK_NOLINK; 6704 rinfo_v8->connect_cnt--; 6705 } 6706 } 6707 } 6708 6709 /* Identify 2-Role type */ 6710 if (connect_cnt >= 2 && 6711 (link_mode == BTC_WLINK_2G_SCC || 6712 link_mode == BTC_WLINK_2G_MCC || 6713 link_mode == BTC_WLINK_25G_MCC || 6714 link_mode == BTC_WLINK_5G)) { 6715 if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 6716 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) 6717 type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO; 6718 else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) 6719 type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC; 6720 else 6721 type = BTC_WLMROLE_STA_STA; 6722 6723 dur = noa; 6724 } 6725 6726 if (role_ver == 7) { 6727 rinfo_v7->mrole_type = type; 6728 rinfo_v7->mrole_noa_duration = dur; 6729 } else if (role_ver == 8) { 6730 rinfo_v8->mrole_type = type; 6731 rinfo_v8->mrole_noa_duration = dur; 6732 } 6733 } 6734 6735 static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid) 6736 { 6737 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER]; 6738 struct rtw89_btc *btc = &rtwdev->btc; 6739 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 6740 struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7; 6741 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; 6742 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info; 6743 struct rtw89_btc_wl_active_role_v7 *act_role = NULL; 6744 u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_NUM, phy_dbcc; 6745 bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false; 6746 u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6747 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6748 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 6749 u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0; 6750 u32 noa_duration = 0; 6751 6752 memset(wl_rinfo, 0, sizeof(*wl_rinfo)); 6753 6754 for (i = 0; i < RTW89_PORT_NUM; i++) { 6755 if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_NUM) 6756 continue; 6757 6758 act_role = &wl_rinfo->active_role[i]; 6759 act_role->role = wl_linfo[i].role; 6760 6761 /* check if role connect? */ 6762 if (wl_linfo[i].connected == MLME_NO_LINK) { 6763 act_role->connected = 0; 6764 continue; 6765 } else if (wl_linfo[i].connected == MLME_LINKING) { 6766 continue; 6767 } 6768 6769 cnt++; 6770 act_role->connected = 1; 6771 act_role->pid = wl_linfo[i].pid; 6772 act_role->phy = wl_linfo[i].phy; 6773 act_role->band = wl_linfo[i].band; 6774 act_role->ch = wl_linfo[i].ch; 6775 act_role->bw = wl_linfo[i].bw; 6776 act_role->noa = wl_linfo[i].noa; 6777 act_role->noa_dur = wl_linfo[i].noa_duration; 6778 cid_ch[cnt - 1] = wl_linfo[i].chdef; 6779 cid_phy[cnt - 1] = wl_linfo[i].phy; 6780 cid_role[cnt - 1] = wl_linfo[i].role; 6781 wl_rinfo->role_map |= BIT(wl_linfo[i].role); 6782 6783 if (rid == i) 6784 phy_now = act_role->phy; 6785 6786 if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6787 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) { 6788 if (wl_linfo[i].client_cnt > 1) 6789 client_joined = true; 6790 if (client_cnt_last[i] < wl_linfo[i].client_cnt && 6791 wl_linfo[i].chdef.band == RTW89_BAND_2G) 6792 client_inc_2g = true; 6793 act_role->client_cnt = wl_linfo[i].client_cnt; 6794 } else { 6795 act_role->client_cnt = 0; 6796 } 6797 6798 if (act_role->noa && act_role->noa_dur > 0) 6799 noa_duration = act_role->noa_dur; 6800 6801 if (rtwdev->dbcc_en) { 6802 phy_dbcc = wl_linfo[i].phy; 6803 wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role); 6804 wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band; 6805 } 6806 6807 if (wl_linfo[i].chdef.band != RTW89_BAND_2G) { 6808 cnt_5g++; 6809 b5g = true; 6810 } else { 6811 if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO || 6812 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) && 6813 client_joined) || 6814 wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT) 6815 wl_rinfo->p2p_2g = 1; 6816 6817 if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) || 6818 (wl_linfo[i].mode & BIT(BTC_WL_MODE_11G))) 6819 wl->bg_mode = 1; 6820 else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE)) 6821 wl->he_mode = true; 6822 6823 cnt_2g++; 6824 b2g = true; 6825 } 6826 6827 if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100) 6828 wl->is_5g_hi_channel = 1; 6829 else 6830 wl->is_5g_hi_channel = 0; 6831 } 6832 6833 wl_rinfo->connect_cnt = cnt; 6834 wl->client_cnt_inc_2g = client_inc_2g; 6835 6836 if (cnt == 0) { 6837 mode = BTC_WLINK_NOLINK; 6838 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE); 6839 } else if (!b2g && b5g) { 6840 mode = BTC_WLINK_5G; 6841 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) { 6842 mode = BTC_WLINK_2G_NAN; 6843 } else if (cnt > BTC_TDMA_WLROLE_MAX) { 6844 mode = BTC_WLINK_OTHER; 6845 } else if (rtwdev->dbcc_en) { 6846 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt); 6847 6848 /* correct 2G-located PHY band for gnt ctrl */ 6849 if (dbcc_2g_phy < RTW89_PHY_NUM) 6850 wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G; 6851 } else if (b2g && b5g && cnt == 2) { 6852 mode = BTC_WLINK_25G_MCC; 6853 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */ 6854 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1])) 6855 mode = BTC_WLINK_2G_SCC; 6856 else 6857 mode = BTC_WLINK_2G_MCC; 6858 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */ 6859 mode = _get_role_link_mode(cid_role[0]); 6860 } else { 6861 mode = BTC_WLINK_NOLINK; 6862 } 6863 6864 wl_rinfo->link_mode = mode; 6865 _update_role_link_mode(rtwdev, client_joined, noa_duration); 6866 6867 /* todo DBCC related event */ 6868 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now); 6869 rtw89_debug(rtwdev, RTW89_DBG_BTC, 6870 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g); 6871 6872 if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) { 6873 wl_rinfo->dbcc_chg = 1; 6874 wl_rinfo->dbcc_en = rtwdev->dbcc_en; 6875 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++; 6876 } 6877 6878 if (rtwdev->dbcc_en) { 6879 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy; 6880 6881 if (dbcc_2g_phy == RTW89_PHY_1) 6882 mac = RTW89_MAC_1; 6883 6884 _update_dbcc_band(rtwdev, RTW89_PHY_0); 6885 _update_dbcc_band(rtwdev, RTW89_PHY_1); 6886 } 6887 _wl_req_mac(rtwdev, mac); 6888 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 6889 } 6890 6891 static u8 _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type) 6892 { 6893 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 6894 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; 6895 u8 mode = BTC_WLINK_NOLINK; 6896 6897 switch (type) { 6898 case RTW89_MR_WTYPE_NONE: /* no-link */ 6899 mode = BTC_WLINK_NOLINK; 6900 break; 6901 case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */ 6902 case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */ 6903 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) { 6904 mode = BTC_WLINK_5G; 6905 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) { 6906 mode = BTC_WLINK_2G_GO; 6907 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) { 6908 if (wl->role_info_v8.p2p_2g) 6909 mode = BTC_WLINK_2G_GC; 6910 else 6911 mode = BTC_WLINK_2G_STA; 6912 } 6913 break; 6914 case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */ 6915 case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */ 6916 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) { 6917 mode = BTC_WLINK_5G; 6918 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ || 6919 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) { 6920 mode = BTC_WLINK_25G_MCC; 6921 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ) { 6922 mode = BTC_WLINK_2G_MCC; 6923 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ) { 6924 mode = BTC_WLINK_2G_SCC; 6925 } 6926 break; 6927 case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */ 6928 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) 6929 mode = BTC_WLINK_5G; 6930 else if (wl->role_info_v8.p2p_2g) 6931 mode = BTC_WLINK_2G_GC; 6932 else 6933 mode = BTC_WLINK_2G_STA; 6934 break; 6935 case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */ 6936 case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2 */ 6937 /* driver may doze 1-link to 6938 * 2G+5G -> TDMA slot switch by E2G/E5G 6939 * 5G only -> TDMA slot switch by E5G 6940 */ 6941 mode = BTC_WLINK_25G_MCC; 6942 break; 6943 case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */ 6944 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) { 6945 mode = BTC_WLINK_5G; 6946 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) { 6947 mode = BTC_WLINK_2G_GO; 6948 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) { 6949 if (wl->role_info_v8.p2p_2g) 6950 mode = BTC_WLINK_2G_GC; 6951 else 6952 mode = BTC_WLINK_2G_STA; 6953 } 6954 break; 6955 } 6956 return mode; 6957 } 6958 6959 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev) 6960 { 6961 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 6962 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 6963 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info; 6964 struct rtw89_mr_chanctx_info qinfo; 6965 u8 track_band = RTW89_PHY_0; 6966 u8 rf_band = RTW89_BAND_2G; 6967 u8 i, type; 6968 6969 /* parse MLO info form PHL API for each HW-band */ 6970 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) { 6971 memset(&qinfo, 0, sizeof(qinfo)); 6972 6973 rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo); 6974 mlo_info->wmode[i] = qinfo.wmode; 6975 mlo_info->ch_type[i] = qinfo.ctxtype; 6976 mlo_info->wtype = qinfo.wtype; 6977 6978 if (mlo_info->ch_type[i] == RTW89_MR_CTX1_5GHZ || 6979 mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ || 6980 mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ_6GHZ) 6981 mlo_info->hwb_rf_band[i] = RTW89_BAND_5G; 6982 else if (mlo_info->ch_type[i] == RTW89_MR_CTX1_6GHZ || 6983 mlo_info->ch_type[i] == RTW89_MR_CTX2_6GHZ) 6984 mlo_info->hwb_rf_band[i] = RTW89_BAND_6G; 6985 else /* check if "2G-included" or unknown in each HW-band */ 6986 mlo_info->hwb_rf_band[i] = RTW89_BAND_2G; 6987 } 6988 6989 mlo_info->link_status = rtwdev->mlo_dbcc_mode; 6990 type = mlo_info->wtype; 6991 6992 if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R || 6993 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R || 6994 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R || 6995 mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD || 6996 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD || 6997 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD) 6998 mlo_info->mlo_en = 1; 6999 else 7000 mlo_info->mlo_en = 0; 7001 7002 if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE && 7003 mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN && 7004 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE && 7005 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN) 7006 mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */ 7007 else 7008 mlo_info->dual_hw_band_en = 0; 7009 7010 if (mlo_info->link_status == MLO_2_PLUS_0_2RF || 7011 mlo_info->link_status == MLO_0_PLUS_2_2RF || 7012 mlo_info->link_status == MLO_2_PLUS_2_2RF) 7013 mlo_info->mlo_adie = 2; 7014 else 7015 mlo_info->mlo_adie = 1; 7016 7017 switch (mlo_info->link_status) { 7018 default: 7019 case MLO_2_PLUS_0_1RF: /* 2+0 */ 7020 case MLO_2_PLUS_0_2RF: 7021 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0; 7022 track_band = RTW89_MAC_0; 7023 rf_band = mlo_info->hwb_rf_band[RTW89_MAC_0]; 7024 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7025 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7026 7027 wl_rinfo->pta_req_band = RTW89_MAC_0; 7028 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7029 wl_rinfo->dbcc_en = 0; 7030 break; 7031 case MLO_0_PLUS_2_1RF: /* 0+2 */ 7032 case MLO_0_PLUS_2_2RF: 7033 mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2; 7034 track_band = RTW89_MAC_1; 7035 rf_band = mlo_info->hwb_rf_band[RTW89_MAC_1]; 7036 mlo_info->path_rf_band[BTC_RF_S0] = rf_band; 7037 mlo_info->path_rf_band[BTC_RF_S1] = rf_band; 7038 7039 wl_rinfo->pta_req_band = RTW89_MAC_1; 7040 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; 7041 wl_rinfo->dbcc_en = 0; 7042 break; 7043 case MLO_1_PLUS_1_1RF: /* 1+1 */ 7044 case MLO_1_PLUS_1_2RF: /* 1+1 */ 7045 case MLO_2_PLUS_2_2RF: /* 2+2 */ 7046 case DBCC_LEGACY: /* DBCC 1+1 */ 7047 if (mlo_info->link_status == MLO_2_PLUS_2_2RF) 7048 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2; 7049 else 7050 mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1; 7051 7052 if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) 7053 track_band = RTW89_MAC_0; 7054 else 7055 track_band = RTW89_MAC_1; 7056 7057 mlo_info->path_rf_band[BTC_RF_S0] = 7058 mlo_info->hwb_rf_band[RTW89_MAC_0]; 7059 mlo_info->path_rf_band[BTC_RF_S1] = 7060 mlo_info->hwb_rf_band[RTW89_MAC_1]; 7061 7062 /* Check ch count from ch_type @ 2.4G HW-band, and modify type */ 7063 if (mlo_info->ch_type[track_band] == RTW89_MR_CTX1_2GHZ) 7064 type = RTW89_MR_WTYPE_NONMLD; /* only 1-role at 2G */ 7065 else 7066 type = RTW89_MR_WTYPE_NONMLD_NONMLD; 7067 7068 if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) { 7069 wl_rinfo->pta_req_band = RTW89_MAC_0; 7070 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0; 7071 } else { 7072 wl_rinfo->pta_req_band = RTW89_MAC_1; 7073 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1; 7074 } 7075 7076 if (mlo_info->wmode[RTW89_MAC_0] == RTW89_MR_WMODE_NONE && 7077 mlo_info->wmode[RTW89_MAC_1] == RTW89_MR_WMODE_NONE) 7078 wl_rinfo->dbcc_en = 0; 7079 else 7080 wl_rinfo->dbcc_en = 1; 7081 break; 7082 } 7083 7084 wl_rinfo->link_mode = _update_wl_link_mode(rtwdev, track_band, type); 7085 7086 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d", 7087 __func__, id_to_linkmode(wl_rinfo->link_mode), 7088 wl_rinfo->pta_req_band); 7089 } 7090 7091 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev) 7092 { 7093 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7094 struct rtw89_btc_wl_rlink *rlink = NULL; 7095 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 7096 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7097 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7098 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {}; 7099 bool b2g = false, b5g = false, outloop = false; 7100 u8 mode = BTC_WLINK_NOLINK; 7101 u8 cnt_2g = 0, cnt_5g = 0; 7102 u8 i, j, cnt = 0; 7103 7104 for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) { 7105 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 7106 rlink = &wl_rinfo->rlink[i][j]; 7107 7108 if (!rlink->active || !rlink->connected) 7109 continue; 7110 7111 if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) { 7112 outloop = true; 7113 break; 7114 } 7115 7116 cid_ch[cnt] = wl->rlink_info[i][j].chdef; 7117 cid_phy[cnt] = rlink->phy; 7118 cid_role[cnt] = rlink->role; 7119 cnt++; 7120 7121 if (rlink->rf_band != RTW89_BAND_2G) { 7122 cnt_5g++; 7123 b5g = true; 7124 } else { 7125 cnt_2g++; 7126 b2g = true; 7127 } 7128 } 7129 if (outloop) 7130 break; 7131 } 7132 7133 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7134 "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g); 7135 7136 wl_rinfo->dbcc_en = rtwdev->dbcc_en; 7137 /* Be careful to change the following sequence!! */ 7138 if (cnt == 0) { 7139 mode = BTC_WLINK_NOLINK; 7140 } else if (!b2g && b5g) { 7141 mode = BTC_WLINK_5G; 7142 } else if (wl_rinfo->dbcc_en) { 7143 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt); 7144 } else if (b2g && b5g) { 7145 mode = BTC_WLINK_25G_MCC; 7146 } else if (!b5g && cnt >= 2) { 7147 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1])) 7148 mode = BTC_WLINK_2G_SCC; 7149 else 7150 mode = BTC_WLINK_2G_MCC; 7151 } else if (!b5g) { /* cnt_connect = 1 */ 7152 mode = _get_role_link_mode(cid_role[0]); 7153 } 7154 7155 wl_rinfo->link_mode = mode; 7156 } 7157 7158 static void _modify_role_link_mode(struct rtw89_dev *rtwdev) 7159 { 7160 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl; 7161 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 7162 u8 go_cleint_exist = wl->go_client_exist; 7163 u8 link_mode = wl_rinfo->link_mode; 7164 u32 role_map = wl_rinfo->role_map; 7165 u8 noa_exist = wl->noa_exist; 7166 u32 mrole = BTC_WLMROLE_NONE; 7167 7168 /* if no client_joined, don't care P2P-GO/AP role */ 7169 if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 7170 (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) { 7171 if (link_mode == BTC_WLINK_2G_SCC) { 7172 wl_rinfo->link_mode = BTC_WLINK_2G_STA; 7173 } else if (link_mode == BTC_WLINK_2G_GO || 7174 link_mode == BTC_WLINK_2G_AP) { 7175 wl_rinfo->link_mode = BTC_WLINK_NOLINK; 7176 } 7177 } 7178 7179 /* Identify 2-Role type */ 7180 if (link_mode == BTC_WLINK_2G_SCC || 7181 link_mode == BTC_WLINK_2G_MCC || 7182 link_mode == BTC_WLINK_25G_MCC || 7183 link_mode == BTC_WLINK_5G) { 7184 if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) || 7185 (role_map & BIT(RTW89_WIFI_ROLE_AP))) { 7186 if (noa_exist) 7187 mrole = BTC_WLMROLE_STA_GO_NOA; 7188 else 7189 mrole = BTC_WLMROLE_STA_GO; 7190 } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) { 7191 if (noa_exist) 7192 mrole = BTC_WLMROLE_STA_GC_NOA; 7193 else 7194 mrole = BTC_WLMROLE_STA_GC; 7195 } else { 7196 mrole = BTC_WLMROLE_STA_STA; 7197 } 7198 } 7199 7200 wl_rinfo->mrole_type = mrole; 7201 7202 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7203 "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__, 7204 id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type); 7205 } 7206 7207 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id, 7208 enum btc_role_state state) 7209 { 7210 struct rtw89_btc_wl_rlink *rlink = NULL; 7211 struct rtw89_btc_wl_link_info *wl_linfo; 7212 struct rtw89_btc *btc = &rtwdev->btc; 7213 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7214 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8; 7215 bool client_joined = false, noa_exist = false, p2p_exist = false; 7216 bool is_5g_hi_channel = false, bg_mode = false, dbcc_en_ori; 7217 u8 i, j, link_mode_ori; 7218 u32 role_map = 0; 7219 7220 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM) 7221 return; 7222 7223 /* Extract wl->link_info[role_id][rlink_id] to wl->role_info 7224 * role_id: role index 7225 * rlink_id: rlink index (= HW-band index) 7226 * pid: port_index 7227 */ 7228 7229 wl_linfo = &wl->rlink_info[role_id][rlink_id]; 7230 rlink = &wl_rinfo->rlink[role_id][rlink_id]; 7231 7232 rlink->role = wl_linfo->role; 7233 rlink->active = wl_linfo->active; /* Doze or not */ 7234 rlink->pid = wl_linfo->pid; 7235 rlink->phy = wl_linfo->phy; 7236 rlink->rf_band = wl_linfo->band; 7237 rlink->ch = wl_linfo->ch; 7238 rlink->bw = wl_linfo->bw; 7239 rlink->noa = wl_linfo->noa; 7240 rlink->noa_dur = wl_linfo->noa_duration / 1000; 7241 rlink->client_cnt = wl_linfo->client_cnt; 7242 rlink->mode = wl_linfo->mode; 7243 7244 switch (wl_linfo->connected) { 7245 case MLME_NO_LINK: 7246 rlink->connected = 0; 7247 break; 7248 case MLME_LINKED: 7249 rlink->connected = 1; 7250 break; 7251 default: 7252 return; 7253 } 7254 7255 for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) { 7256 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { 7257 rlink = &wl_rinfo->rlink[i][j]; 7258 7259 if (!rlink->active || !rlink->connected) 7260 continue; 7261 7262 role_map |= BIT(rlink->role); 7263 7264 /* only one noa-role exist */ 7265 if (rlink->noa && rlink->noa_dur > 0) 7266 noa_exist = true; 7267 7268 /* for WL 5G-Rx interfered with BT issue */ 7269 if (rlink->rf_band == RTW89_BAND_5G) { 7270 if (rlink->ch >= 100) 7271 is_5g_hi_channel = true; 7272 7273 continue; 7274 } 7275 7276 /* only if client connect for p2p-Go/AP */ 7277 if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO || 7278 rlink->role == RTW89_WIFI_ROLE_AP) && 7279 rlink->client_cnt > 1) { 7280 p2p_exist = true; 7281 client_joined = true; 7282 } 7283 7284 /* Identify if P2P-Go (GO/GC/AP) exist at 2G band */ 7285 if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT) 7286 p2p_exist = true; 7287 7288 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) || 7289 (rlink->mode & BIT(BTC_WL_MODE_11G))) 7290 bg_mode = true; 7291 } 7292 } 7293 7294 link_mode_ori = wl_rinfo->link_mode; 7295 wl->is_5g_hi_channel = is_5g_hi_channel; 7296 wl->bg_mode = bg_mode; 7297 wl->go_client_exist = client_joined; 7298 wl->noa_exist = noa_exist; 7299 wl_rinfo->p2p_2g = p2p_exist; 7300 wl_rinfo->role_map = role_map; 7301 7302 dbcc_en_ori = wl_rinfo->dbcc_en; 7303 7304 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) { 7305 /* for MLO-supported, link-mode from driver directly */ 7306 _update_wl_mlo_info(rtwdev); 7307 } else { 7308 /* for non-MLO-supported, link-mode by BTC */ 7309 _update_wl_non_mlo_info(rtwdev); 7310 } 7311 7312 _modify_role_link_mode(rtwdev); 7313 7314 if (link_mode_ori != wl_rinfo->link_mode) 7315 wl->link_mode_chg = true; 7316 7317 if (wl_rinfo->dbcc_en != dbcc_en_ori) { 7318 wl->dbcc_chg = true; 7319 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++; 7320 } 7321 } 7322 7323 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work) 7324 { 7325 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7326 coex_act1_work.work); 7327 struct rtw89_btc *btc = &rtwdev->btc; 7328 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7329 struct rtw89_btc_cx *cx = &btc->cx; 7330 struct rtw89_btc_wl_info *wl = &cx->wl; 7331 7332 lockdep_assert_wiphy(wiphy); 7333 7334 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 7335 dm->cnt_notify[BTC_NCNT_TIMER]++; 7336 if (wl->status.map._4way) 7337 wl->status.map._4way = false; 7338 if (wl->status.map.connecting) 7339 wl->status.map.connecting = false; 7340 7341 _run_coex(rtwdev, BTC_RSN_ACT1_WORK); 7342 } 7343 7344 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work) 7345 { 7346 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7347 coex_bt_devinfo_work.work); 7348 struct rtw89_btc *btc = &rtwdev->btc; 7349 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7350 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 7351 7352 lockdep_assert_wiphy(wiphy); 7353 7354 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 7355 dm->cnt_notify[BTC_NCNT_TIMER]++; 7356 a2dp->play_latency = 0; 7357 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK); 7358 } 7359 7360 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work) 7361 { 7362 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7363 coex_rfk_chk_work.work); 7364 struct rtw89_btc *btc = &rtwdev->btc; 7365 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7366 struct rtw89_btc_cx *cx = &btc->cx; 7367 struct rtw89_btc_wl_info *wl = &cx->wl; 7368 7369 lockdep_assert_wiphy(wiphy); 7370 7371 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__); 7372 dm->cnt_notify[BTC_NCNT_TIMER]++; 7373 if (wl->rfk_info.state != BTC_WRFK_STOP) { 7374 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7375 "[BTC], %s(): RFK timeout\n", __func__); 7376 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++; 7377 dm->error.map.wl_rfk_timeout = true; 7378 wl->rfk_info.state = BTC_WRFK_STOP; 7379 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 7380 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK); 7381 } 7382 } 7383 7384 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update) 7385 { 7386 const struct rtw89_chip_info *chip = rtwdev->chip; 7387 struct rtw89_btc *btc = &rtwdev->btc; 7388 struct rtw89_btc_cx *cx = &btc->cx; 7389 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7390 u32 val; 7391 bool status_change = false; 7392 7393 if (!chip->scbd) 7394 return; 7395 7396 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__); 7397 7398 val = _read_scbd(rtwdev); 7399 if (val == BTC_SCB_INV_VALUE) { 7400 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7401 "[BTC], %s(): return by invalid scbd value\n", 7402 __func__); 7403 return; 7404 } 7405 7406 if (!(val & BTC_BSCB_ON)) 7407 bt->enable.now = 0; 7408 else 7409 bt->enable.now = 1; 7410 7411 if (bt->enable.now != bt->enable.last) 7412 status_change = true; 7413 7414 /* reset bt info if bt re-enable */ 7415 if (bt->enable.now && !bt->enable.last) { 7416 _reset_btc_var(rtwdev, BTC_RESET_BTINFO); 7417 cx->cnt_bt[BTC_BCNT_REENABLE]++; 7418 bt->enable.now = 1; 7419 } 7420 7421 bt->enable.last = bt->enable.now; 7422 bt->scbd = val; 7423 bt->mbx_avl = !!(val & BTC_BSCB_ACT); 7424 7425 if (bt->whql_test != !!(val & BTC_BSCB_WHQL)) 7426 status_change = true; 7427 7428 bt->whql_test = !!(val & BTC_BSCB_WHQL); 7429 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE; 7430 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT); 7431 7432 bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) + 7433 !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4; 7434 7435 /* if rfk run 1->0 */ 7436 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN)) 7437 status_change = true; 7438 7439 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN); 7440 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ); 7441 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA); 7442 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT); 7443 if (bt->run_patch_code != !!(val & BTC_BSCB_PATCH_CODE)) 7444 status_change = true; 7445 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE); 7446 7447 if (!only_update && status_change) 7448 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD); 7449 } 7450 7451 #define BTC_BTINFO_PWR_LEN 5 7452 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 7453 { 7454 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt; 7455 struct rtw89_btc_bt_link_info *b = &bt->link_info; 7456 7457 if (len != BTC_BTINFO_PWR_LEN) 7458 return; 7459 7460 if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) { 7461 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7462 "[BTC], %s return by info duplicate!\n", __func__); 7463 return; 7464 } 7465 7466 memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX); 7467 memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc)); 7468 } 7469 7470 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev) 7471 { 7472 struct rtw89_btc *btc = &rtwdev->btc; 7473 struct rtw89_btc_cx *cx = &btc->cx; 7474 struct rtw89_btc_bt_info *bt = &cx->bt; 7475 7476 _update_bt_scbd(rtwdev, true); 7477 7478 cx->cnt_wl[BTC_WCNT_RFK_REQ]++; 7479 7480 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) && 7481 !bt->rfk_info.map.timeout) { 7482 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++; 7483 } else { 7484 cx->cnt_wl[BTC_WCNT_RFK_GO]++; 7485 return true; 7486 } 7487 return false; 7488 } 7489 7490 static 7491 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) 7492 { 7493 struct rtw89_btc *btc = &rtwdev->btc; 7494 const struct rtw89_btc_ver *ver = btc->ver; 7495 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7496 struct rtw89_btc_cx *cx = &btc->cx; 7497 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7498 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7499 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 7500 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 7501 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 7502 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 7503 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 7504 u8 mode, igno_bt, always_freerun; 7505 7506 lockdep_assert_wiphy(rtwdev->hw->wiphy); 7507 7508 dm->run_reason = reason; 7509 _update_dm_step(rtwdev, reason); 7510 _update_btc_state_map(rtwdev); 7511 7512 if (ver->fwlrole == 0) 7513 mode = wl_rinfo->link_mode; 7514 else if (ver->fwlrole == 1) 7515 mode = wl_rinfo_v1->link_mode; 7516 else if (ver->fwlrole == 2) 7517 mode = wl_rinfo_v2->link_mode; 7518 else if (ver->fwlrole == 7) 7519 mode = wl_rinfo_v7->link_mode; 7520 else if (ver->fwlrole == 8) 7521 mode = wl_rinfo_v8->link_mode; 7522 else 7523 return; 7524 7525 if (ver->fcxctrl == 7) { 7526 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 7527 always_freerun = btc->ctrl.ctrl_v7.always_freerun; 7528 } else { 7529 igno_bt = btc->ctrl.ctrl.igno_bt; 7530 always_freerun = btc->ctrl.ctrl.always_freerun; 7531 } 7532 7533 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n", 7534 __func__, reason, mode); 7535 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n", 7536 __func__, dm->wl_only, dm->bt_only); 7537 7538 /* Be careful to change the following function sequence!! */ 7539 if (btc->manual_ctrl) { 7540 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7541 "[BTC], %s(): return for Manual CTRL!!\n", 7542 __func__); 7543 return; 7544 } 7545 7546 if (igno_bt && 7547 (reason == BTC_RSN_UPDATE_BT_INFO || 7548 reason == BTC_RSN_UPDATE_BT_SCBD)) { 7549 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7550 "[BTC], %s(): return for Stop Coex DM!!\n", 7551 __func__); 7552 return; 7553 } 7554 7555 if (!wl->status.map.init_ok) { 7556 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7557 "[BTC], %s(): return for WL init fail!!\n", 7558 __func__); 7559 return; 7560 } 7561 7562 if (wl->status.map.rf_off_pre == wl->status.map.rf_off && 7563 wl->status.map.lps_pre == wl->status.map.lps) { 7564 if (reason == BTC_RSN_NTFY_POWEROFF || 7565 reason == BTC_RSN_NTFY_RADIO_STATE) { 7566 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7567 "[BTC], %s(): return for WL rf off state no change!!\n", 7568 __func__); 7569 return; 7570 } 7571 if (wl->status.map.rf_off == 1 || 7572 wl->status.map.lps == BTC_LPS_RF_OFF) { 7573 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7574 "[BTC], %s(): return for WL rf off state!!\n", 7575 __func__); 7576 return; 7577 } 7578 } 7579 7580 dm->freerun = false; 7581 dm->cnt_dm[BTC_DCNT_RUN]++; 7582 dm->fddt_train = BTC_FDDT_DISABLE; 7583 bt->scan_rx_low_pri = false; 7584 igno_bt = false; 7585 7586 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ 7587 7588 if (always_freerun) { 7589 _action_freerun(rtwdev); 7590 igno_bt = true; 7591 goto exit; 7592 } 7593 7594 if (dm->wl_only) { 7595 _action_wl_only(rtwdev); 7596 igno_bt = true; 7597 goto exit; 7598 } 7599 7600 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) { 7601 _action_wl_off(rtwdev, mode); 7602 igno_bt = true; 7603 goto exit; 7604 } 7605 7606 if (reason == BTC_RSN_NTFY_INIT) { 7607 _action_wl_init(rtwdev); 7608 goto exit; 7609 } 7610 7611 if (!cx->bt.enable.now && !cx->other.type) { 7612 _action_bt_off(rtwdev); 7613 goto exit; 7614 } 7615 7616 if (cx->bt.whql_test) { 7617 _action_bt_whql(rtwdev); 7618 goto exit; 7619 } 7620 7621 if (wl->rfk_info.state != BTC_WRFK_STOP) { 7622 _action_wl_rfk(rtwdev); 7623 goto exit; 7624 } 7625 7626 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) { 7627 _action_wl_scan(rtwdev); 7628 bt->scan_rx_low_pri = true; 7629 goto exit; 7630 } 7631 7632 switch (mode) { 7633 case BTC_WLINK_NOLINK: 7634 _action_wl_nc(rtwdev); 7635 break; 7636 case BTC_WLINK_2G_STA: 7637 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) 7638 bt->scan_rx_low_pri = true; 7639 _action_wl_2g_sta(rtwdev); 7640 break; 7641 case BTC_WLINK_2G_AP: 7642 bt->scan_rx_low_pri = true; 7643 _action_wl_2g_ap(rtwdev); 7644 break; 7645 case BTC_WLINK_2G_GO: 7646 bt->scan_rx_low_pri = true; 7647 _action_wl_2g_go(rtwdev); 7648 break; 7649 case BTC_WLINK_2G_GC: 7650 bt->scan_rx_low_pri = true; 7651 _action_wl_2g_gc(rtwdev); 7652 break; 7653 case BTC_WLINK_2G_SCC: 7654 bt->scan_rx_low_pri = true; 7655 if (ver->fwlrole == 0) 7656 _action_wl_2g_scc(rtwdev); 7657 else if (ver->fwlrole == 1) 7658 _action_wl_2g_scc_v1(rtwdev); 7659 else if (ver->fwlrole == 2 || ver->fwlrole == 7) 7660 _action_wl_2g_scc_v2(rtwdev); 7661 else if (ver->fwlrole == 8) 7662 _action_wl_2g_scc_v8(rtwdev); 7663 break; 7664 case BTC_WLINK_2G_MCC: 7665 bt->scan_rx_low_pri = true; 7666 _action_wl_2g_mcc(rtwdev); 7667 break; 7668 case BTC_WLINK_25G_MCC: 7669 bt->scan_rx_low_pri = true; 7670 _action_wl_25g_mcc(rtwdev); 7671 break; 7672 case BTC_WLINK_5G: 7673 _action_wl_5g(rtwdev); 7674 break; 7675 case BTC_WLINK_2G_NAN: 7676 _action_wl_2g_nan(rtwdev); 7677 break; 7678 default: 7679 _action_wl_other(rtwdev); 7680 break; 7681 } 7682 7683 exit: 7684 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__); 7685 if (ver->fcxctrl == 7) 7686 btc->ctrl.ctrl_v7.igno_bt = igno_bt; 7687 else 7688 btc->ctrl.ctrl.igno_bt = igno_bt; 7689 _action_common(rtwdev); 7690 } 7691 7692 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev) 7693 { 7694 struct rtw89_btc *btc = &rtwdev->btc; 7695 7696 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 7697 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++; 7698 } 7699 7700 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev) 7701 { 7702 struct rtw89_btc *btc = &rtwdev->btc; 7703 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7704 7705 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__); 7706 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++; 7707 7708 btc->cx.wl.status.map.rf_off = 1; 7709 btc->cx.wl.status.map.busy = 0; 7710 wl->status.map.lps = BTC_LPS_OFF; 7711 7712 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 7713 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF); 7714 7715 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0); 7716 7717 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off; 7718 } 7719 7720 static void _set_init_info(struct rtw89_dev *rtwdev) 7721 { 7722 const struct rtw89_chip_info *chip = rtwdev->chip; 7723 struct rtw89_btc *btc = &rtwdev->btc; 7724 const struct rtw89_btc_ver *ver = btc->ver; 7725 struct rtw89_btc_dm *dm = &btc->dm; 7726 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7727 7728 if (ver->fcxinit == 7) { 7729 dm->init_info.init_v7.wl_only = (u8)dm->wl_only; 7730 dm->init_info.init_v7.bt_only = (u8)dm->bt_only; 7731 dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok; 7732 dm->init_info.init_v7.cx_other = btc->cx.other.type; 7733 dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch; 7734 dm->init_info.init_v7.module = btc->mdinfo.md_v7; 7735 } else { 7736 dm->init_info.init.wl_only = (u8)dm->wl_only; 7737 dm->init_info.init.bt_only = (u8)dm->bt_only; 7738 dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok; 7739 dm->init_info.init.dbcc_en = rtwdev->dbcc_en; 7740 dm->init_info.init.cx_other = btc->cx.other.type; 7741 dm->init_info.init.wl_guard_ch = chip->afh_guard_ch; 7742 dm->init_info.init.module = btc->mdinfo.md; 7743 } 7744 } 7745 7746 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode) 7747 { 7748 struct rtw89_btc *btc = &rtwdev->btc; 7749 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 7750 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7751 const struct rtw89_chip_info *chip = rtwdev->chip; 7752 const struct rtw89_btc_ver *ver = btc->ver; 7753 7754 _reset_btc_var(rtwdev, BTC_RESET_ALL); 7755 btc->dm.run_reason = BTC_RSN_NONE; 7756 btc->dm.run_action = BTC_ACT_NONE; 7757 if (ver->fcxctrl == 7) 7758 btc->ctrl.ctrl_v7.igno_bt = true; 7759 else 7760 btc->ctrl.ctrl.igno_bt = true; 7761 7762 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7763 "[BTC], %s(): mode=%d\n", __func__, mode); 7764 7765 wl->coex_mode = mode; 7766 dm->cnt_notify[BTC_NCNT_INIT_COEX]++; 7767 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0; 7768 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0; 7769 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0; 7770 7771 chip->ops->btc_set_rfe(rtwdev); 7772 chip->ops->btc_init_cfg(rtwdev); 7773 7774 if (!wl->status.map.init_ok) { 7775 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7776 "[BTC], %s(): return for WL init fail!!\n", 7777 __func__); 7778 dm->error.map.init = true; 7779 return; 7780 } 7781 7782 _write_scbd(rtwdev, 7783 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true); 7784 _update_bt_scbd(rtwdev, true); 7785 if (rtw89_mac_get_ctrl_path(rtwdev)) { 7786 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7787 "[BTC], %s(): PTA owner warning!!\n", 7788 __func__); 7789 dm->error.map.pta_owner = true; 7790 } 7791 7792 _set_init_info(rtwdev); 7793 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR); 7794 btc_fw_set_monreg(rtwdev); 7795 rtw89_btc_fw_set_slots(rtwdev); 7796 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT); 7797 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL); 7798 7799 _run_coex(rtwdev, BTC_RSN_NTFY_INIT); 7800 } 7801 7802 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 7803 { 7804 struct rtw89_btc *btc = &rtwdev->btc; 7805 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7806 7807 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7808 "[BTC], %s(): phy_idx=%d, band=%d\n", 7809 __func__, phy_idx, band); 7810 7811 if (phy_idx >= RTW89_PHY_NUM) 7812 return; 7813 7814 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++; 7815 wl->status.map.scan = true; 7816 wl->scan_info.band[phy_idx] = band; 7817 wl->scan_info.phy_map |= BIT(phy_idx); 7818 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 7819 7820 if (rtwdev->dbcc_en) { 7821 wl->dbcc_info.scan_band[phy_idx] = band; 7822 _update_dbcc_band(rtwdev, phy_idx); 7823 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 7824 } 7825 7826 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START); 7827 } 7828 7829 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) 7830 { 7831 struct rtw89_btc *btc = &rtwdev->btc; 7832 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7833 7834 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7835 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx); 7836 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++; 7837 7838 wl->status.map.scan = false; 7839 wl->scan_info.phy_map &= ~BIT(phy_idx); 7840 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); 7841 7842 if (rtwdev->dbcc_en) { 7843 _update_dbcc_band(rtwdev, phy_idx); 7844 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 7845 } 7846 7847 btc->dm.tdma_instant_excute = 1; 7848 7849 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); 7850 } 7851 7852 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) 7853 { 7854 struct rtw89_btc *btc = &rtwdev->btc; 7855 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 7856 7857 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7858 "[BTC], %s(): phy_idx=%d, band=%d\n", 7859 __func__, phy_idx, band); 7860 7861 if (phy_idx >= RTW89_PHY_NUM) 7862 return; 7863 7864 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; 7865 7866 if (rtwdev->dbcc_en) { 7867 wl->dbcc_info.scan_band[phy_idx] = band; 7868 _update_dbcc_band(rtwdev, phy_idx); 7869 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); 7870 } 7871 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND); 7872 } 7873 7874 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev, 7875 enum btc_pkt_type pkt_type) 7876 { 7877 struct rtw89_btc *btc = &rtwdev->btc; 7878 struct rtw89_btc_cx *cx = &btc->cx; 7879 struct rtw89_btc_wl_info *wl = &cx->wl; 7880 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info; 7881 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 7882 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 7883 u32 cnt; 7884 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD; 7885 bool delay_work = false; 7886 7887 switch (pkt_type) { 7888 case PACKET_DHCP: 7889 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP]; 7890 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7891 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt); 7892 wl->status.map.connecting = true; 7893 delay_work = true; 7894 break; 7895 case PACKET_EAPOL: 7896 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 7897 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7898 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt); 7899 wl->status.map._4way = true; 7900 delay_work = true; 7901 if (hfp->exist || hid->exist) 7902 delay /= 2; 7903 break; 7904 case PACKET_EAPOL_END: 7905 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL]; 7906 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7907 "[BTC], %s(): EAPOL_End cnt=%d\n", 7908 __func__, cnt); 7909 wl->status.map._4way = false; 7910 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 7911 break; 7912 case PACKET_ARP: 7913 cnt = ++cx->cnt_wl[BTC_WCNT_ARP]; 7914 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7915 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt); 7916 return; 7917 case PACKET_ICMP: 7918 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7919 "[BTC], %s(): ICMP pkt\n", __func__); 7920 return; 7921 default: 7922 rtw89_debug(rtwdev, RTW89_DBG_BTC, 7923 "[BTC], %s(): unknown packet type %d\n", 7924 __func__, pkt_type); 7925 return; 7926 } 7927 7928 if (delay_work) { 7929 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work); 7930 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 7931 &rtwdev->coex_act1_work, delay); 7932 } 7933 7934 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++; 7935 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET); 7936 } 7937 7938 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7939 { 7940 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7941 btc.eapol_notify_work); 7942 7943 lockdep_assert_wiphy(wiphy); 7944 7945 rtw89_leave_ps_mode(rtwdev); 7946 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL); 7947 } 7948 7949 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7950 { 7951 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7952 btc.arp_notify_work); 7953 7954 lockdep_assert_wiphy(wiphy); 7955 7956 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP); 7957 } 7958 7959 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7960 { 7961 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7962 btc.dhcp_notify_work); 7963 7964 lockdep_assert_wiphy(wiphy); 7965 7966 rtw89_leave_ps_mode(rtwdev); 7967 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP); 7968 } 7969 7970 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work) 7971 { 7972 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 7973 btc.icmp_notify_work); 7974 7975 lockdep_assert_wiphy(wiphy); 7976 7977 rtw89_leave_ps_mode(rtwdev); 7978 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP); 7979 } 7980 7981 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi) 7982 { 7983 const struct rtw89_chip_info *chip = rtwdev->chip; 7984 struct rtw89_btc *btc = &rtwdev->btc; 7985 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 7986 u8 *rssi_st, rssi_th, rssi_level = 0; 7987 u8 i; 7988 7989 /* for rssi locate in which {40, 36, 31, 28} 7990 * if rssi >= 40% (-60dBm) --> rssi_level = 4 7991 * if 36% <= rssi < 40% --> rssi_level = 3 7992 * if 31% <= rssi < 36% --> rssi_level = 2 7993 * if 28% <= rssi < 31% --> rssi_level = 1 7994 * if rssi < 28% --> rssi_level = 0 7995 */ 7996 7997 /* check if rssi across bt_rssi_thres boundary */ 7998 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) { 7999 rssi_th = chip->bt_rssi_thres[i]; 8000 rssi_st = &bt->link_info.rssi_state[i]; 8001 8002 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th); 8003 8004 if (BTC_RSSI_HIGH(*rssi_st)) { 8005 rssi_level = BTC_BT_RSSI_THMAX - i; 8006 break; 8007 } 8008 } 8009 return rssi_level; 8010 } 8011 8012 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev) 8013 { 8014 u8 mode = rtwdev->btc.cx.wl.role_info.link_mode; 8015 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a; 8016 8017 if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) { 8018 zb_tbl0 = 0xffffffff; 8019 zb_tbl1 = 0xffffffff; 8020 } else if (mode == BTC_WLINK_25G_MCC) { 8021 zb_tbl0 = 0xffffffff; /* for E5G slot */ 8022 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */ 8023 } 8024 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0); 8025 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1); 8026 } 8027 8028 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4) 8029 8030 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) 8031 { 8032 const struct rtw89_chip_info *chip = rtwdev->chip; 8033 struct rtw89_btc *btc = &rtwdev->btc; 8034 struct rtw89_btc_cx *cx = &btc->cx; 8035 struct rtw89_btc_bt_info *bt = &cx->bt; 8036 struct rtw89_btc_bt_link_info *b = &bt->link_info; 8037 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc; 8038 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc; 8039 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc; 8040 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc; 8041 union btc_btinfo btinfo; 8042 8043 if (buf[BTC_BTINFO_L1] != 6) 8044 return; 8045 8046 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) { 8047 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8048 "[BTC], %s(): return by bt-info duplicate!!\n", 8049 __func__); 8050 cx->cnt_bt[BTC_BCNT_INFOSAME]++; 8051 return; 8052 } 8053 8054 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX); 8055 8056 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8057 "[BTC], %s(): bt_info[2]=0x%02x\n", 8058 __func__, bt->raw_info[2]); 8059 8060 b->profile_cnt.last = b->profile_cnt.now; 8061 b->profile_cnt.now = 0; 8062 hid->type = 0; 8063 8064 /* parse raw info low-Byte2 */ 8065 btinfo.val = bt->raw_info[BTC_BTINFO_L2]; 8066 b->status.map.connect = btinfo.lb2.connect; 8067 b->status.map.sco_busy = btinfo.lb2.sco_busy; 8068 b->status.map.acl_busy = btinfo.lb2.acl_busy; 8069 b->status.map.inq_pag = btinfo.lb2.inq_pag; 8070 bt->inq_pag.now = btinfo.lb2.inq_pag; 8071 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last); 8072 8073 hfp->exist = btinfo.lb2.hfp; 8074 b->profile_cnt.now += (u8)hfp->exist; 8075 hid->exist = btinfo.lb2.hid; 8076 b->profile_cnt.now += (u8)hid->exist; 8077 a2dp->exist = btinfo.lb2.a2dp; 8078 b->profile_cnt.now += (u8)a2dp->exist; 8079 pan->exist = btinfo.lb2.pan; 8080 b->profile_cnt.now += (u8)pan->exist; 8081 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); 8082 8083 /* parse raw info low-Byte3 */ 8084 btinfo.val = bt->raw_info[BTC_BTINFO_L3]; 8085 if (btinfo.lb3.retry != 0) 8086 cx->cnt_bt[BTC_BCNT_RETRY]++; 8087 b->cqddr = btinfo.lb3.cqddr; 8088 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq); 8089 bt->inq = btinfo.lb3.inq; 8090 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag); 8091 bt->pag = btinfo.lb3.pag; 8092 8093 b->status.map.mesh_busy = btinfo.lb3.mesh_busy; 8094 /* parse raw info high-Byte0 */ 8095 btinfo.val = bt->raw_info[BTC_BTINFO_H0]; 8096 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/ 8097 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi); 8098 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi); 8099 btc->dm.trx_info.bt_rssi = bt->rssi_level; 8100 8101 /* parse raw info high-Byte1 */ 8102 btinfo.val = bt->raw_info[BTC_BTINFO_H1]; 8103 b->status.map.ble_connect = btinfo.hb1.ble_connect; 8104 if (btinfo.hb1.ble_connect) { 8105 if (hid->exist) 8106 hid->type |= BTC_HID_BLE; 8107 else if (btinfo.hb1.voice) 8108 hid->type |= BTC_HID_RCU_VOICE; 8109 else 8110 hid->type |= BTC_HID_RCU; 8111 } 8112 8113 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); 8114 bt->reinit = btinfo.hb1.reinit; 8115 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now); 8116 b->relink.now = btinfo.hb1.relink; 8117 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl); 8118 bt->igno_wl = btinfo.hb1.igno_wl; 8119 8120 if (bt->igno_wl && !cx->wl.status.map.rf_off) 8121 _set_bt_ignore_wlan_act(rtwdev, false); 8122 8123 bt->ble_scan_en = btinfo.hb1.ble_scan; 8124 8125 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); 8126 b->role_sw = btinfo.hb1.role_sw; 8127 8128 b->multi_link.now = btinfo.hb1.multi_link; 8129 8130 /* parse raw info high-Byte2 */ 8131 btinfo.val = bt->raw_info[BTC_BTINFO_H2]; 8132 pan->active = !!btinfo.hb2.pan_active; 8133 8134 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); 8135 b->afh_update = btinfo.hb2.afh_update; 8136 a2dp->active = btinfo.hb2.a2dp_active; 8137 b->slave_role = btinfo.hb2.slave; 8138 hid->slot_info = btinfo.hb2.hid_slot; 8139 hid->pair_cnt = btinfo.hb2.hid_cnt; 8140 if (!b->status.map.ble_connect || hid->pair_cnt > 1) 8141 hid->type |= (hid->slot_info == BTC_HID_218 ? 8142 BTC_HID_218 : BTC_HID_418); 8143 /* parse raw info high-Byte3 */ 8144 btinfo.val = bt->raw_info[BTC_BTINFO_H3]; 8145 a2dp->bitpool = btinfo.hb3.a2dp_bitpool; 8146 8147 if (b->tx_3m != (u32)btinfo.hb3.tx_3m) 8148 cx->cnt_bt[BTC_BCNT_RATECHG]++; 8149 b->tx_3m = (u32)btinfo.hb3.tx_3m; 8150 8151 a2dp->sink = btinfo.hb3.a2dp_sink; 8152 8153 if (!a2dp->exist_last && a2dp->exist) { 8154 a2dp->vendor_id = 0; 8155 a2dp->flush_time = 0; 8156 a2dp->play_latency = 1; 8157 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 8158 &rtwdev->coex_bt_devinfo_work, 8159 RTW89_COEX_BT_DEVINFO_WORK_PERIOD); 8160 } 8161 8162 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); 8163 } 8164 8165 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, 8166 struct rtw89_vif_link *rtwvif_link, 8167 struct rtw89_sta_link *rtwsta_link, 8168 enum btc_role_state state) 8169 { 8170 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, 8171 rtwvif_link->chanctx_idx); 8172 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); 8173 struct ieee80211_bss_conf *bss_conf; 8174 struct ieee80211_link_sta *link_sta; 8175 struct rtw89_btc *btc = &rtwdev->btc; 8176 const struct rtw89_btc_ver *ver = btc->ver; 8177 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8178 struct rtw89_btc_wl_link_info r = {0}; 8179 struct rtw89_btc_wl_link_info *wlinfo = NULL; 8180 u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type; 8181 8182 rcu_read_lock(); 8183 8184 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); 8185 8186 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); 8187 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8188 "[BTC], role is STA=%d\n", 8189 vif->type == NL80211_IFTYPE_STATION); 8190 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); 8191 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", 8192 chan->band_type, chan->channel, chan->band_width); 8193 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", 8194 state == BTC_ROLE_MSTS_STA_CONN_END); 8195 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8196 "[BTC], bcn_period=%d dtim_period=%d\n", 8197 bss_conf->beacon_int, bss_conf->dtim_period); 8198 8199 if (rtwsta_link) { 8200 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); 8201 8202 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", 8203 rtwsta_link->mac_id); 8204 8205 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8206 "[BTC], STA support HE=%d VHT=%d HT=%d\n", 8207 link_sta->he_cap.has_he, 8208 link_sta->vht_cap.vht_supported, 8209 link_sta->ht_cap.ht_supported); 8210 if (link_sta->he_cap.has_he) 8211 mode |= BIT(BTC_WL_MODE_HE); 8212 if (link_sta->vht_cap.vht_supported) 8213 mode |= BIT(BTC_WL_MODE_VHT); 8214 if (link_sta->ht_cap.ht_supported) 8215 mode |= BIT(BTC_WL_MODE_HT); 8216 8217 r.mode = mode; 8218 } 8219 8220 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { 8221 rcu_read_unlock(); 8222 return; 8223 } 8224 8225 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8226 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); 8227 8228 r.role = rtwvif_link->wifi_role; 8229 r.phy = rtwvif_link->phy_idx; 8230 r.pid = rtwvif_link->port; 8231 r.active = true; 8232 r.connected = MLME_LINKED; 8233 r.bcn_period = bss_conf->beacon_int; 8234 r.dtim_period = bss_conf->dtim_period; 8235 r.band = chan->band_type; 8236 r.ch = chan->channel; 8237 r.bw = chan->band_width; 8238 r.chdef.band = chan->band_type; 8239 r.chdef.center_ch = chan->channel; 8240 r.chdef.bw = chan->band_width; 8241 r.chdef.chan = chan->primary_channel; 8242 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); 8243 8244 rcu_read_unlock(); 8245 8246 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) 8247 r.mac_id = rtwsta_link->mac_id; 8248 8249 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; 8250 8251 wlinfo = &wl->link_info[r.pid]; 8252 8253 if (ver->fwlrole == 0) { 8254 *wlinfo = r; 8255 _update_wl_info(rtwdev); 8256 } else if (ver->fwlrole == 1) { 8257 *wlinfo = r; 8258 _update_wl_info_v1(rtwdev); 8259 } else if (ver->fwlrole == 2) { 8260 *wlinfo = r; 8261 _update_wl_info_v2(rtwdev); 8262 } else if (ver->fwlrole == 7) { 8263 *wlinfo = r; 8264 _update_wl_info_v7(rtwdev, r.pid); 8265 } else if (ver->fwlrole == 8) { 8266 rlink_id = rtwvif_link->mac_idx; 8267 wlinfo = &wl->rlink_info[r.pid][rlink_id]; 8268 *wlinfo = r; 8269 link_mode_ori = wl->role_info_v8.link_mode; 8270 pta_req_mac_ori = wl->pta_req_mac; 8271 _update_wl_info_v8(rtwdev, r.pid, rlink_id, state); 8272 8273 if (wl->role_info_v8.link_mode != link_mode_ori) { 8274 wl->role_info_v8.link_mode_chg = 1; 8275 if (ver->fcxinit == 7) 8276 wa_type = btc->mdinfo.md_v7.wa_type; 8277 else 8278 wa_type = btc->mdinfo.md.wa_type; 8279 8280 if (wa_type & BTC_WA_HFP_ZB) 8281 _update_zb_coex_tbl(rtwdev); 8282 } 8283 8284 if (wl->pta_req_mac != pta_req_mac_ori) 8285 wl->pta_reg_mac_chg = 1; 8286 } 8287 8288 if (wlinfo->role == RTW89_WIFI_ROLE_STATION && 8289 wlinfo->connected == MLME_NO_LINK) 8290 btc->dm.leak_ap = 0; 8291 8292 if (state == BTC_ROLE_MSTS_STA_CONN_START) 8293 wl->status.map.connecting = 1; 8294 else 8295 wl->status.map.connecting = 0; 8296 8297 if (state == BTC_ROLE_MSTS_STA_DIS_CONN || 8298 state == BTC_ROLE_MSTS_STA_CONN_END) 8299 wl->status.map._4way = false; 8300 8301 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); 8302 } 8303 8304 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state) 8305 { 8306 const struct rtw89_chip_info *chip = rtwdev->chip; 8307 struct rtw89_btc *btc = &rtwdev->btc; 8308 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8309 u32 val; 8310 8311 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n", 8312 __func__, rf_state); 8313 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++; 8314 8315 switch (rf_state) { 8316 case BTC_RFCTRL_WL_OFF: 8317 wl->status.map.rf_off = 1; 8318 wl->status.map.lps = BTC_LPS_OFF; 8319 wl->status.map.busy = 0; 8320 break; 8321 case BTC_RFCTRL_FW_CTRL: 8322 wl->status.map.rf_off = 0; 8323 wl->status.map.lps = BTC_LPS_RF_OFF; 8324 wl->status.map.busy = 0; 8325 break; 8326 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */ 8327 wl->status.map.rf_off = 0; 8328 wl->status.map.lps = BTC_LPS_RF_ON; 8329 wl->status.map.busy = 0; 8330 break; 8331 case BTC_RFCTRL_WL_ON: 8332 default: 8333 wl->status.map.rf_off = 0; 8334 wl->status.map.lps = BTC_LPS_OFF; 8335 break; 8336 } 8337 8338 if (rf_state == BTC_RFCTRL_WL_ON) { 8339 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true); 8340 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG; 8341 _write_scbd(rtwdev, val, true); 8342 _update_bt_scbd(rtwdev, true); 8343 chip->ops->btc_init_cfg(rtwdev); 8344 } else { 8345 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false); 8346 if (rf_state == BTC_RFCTRL_FW_CTRL) 8347 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false); 8348 else if (rf_state == BTC_RFCTRL_WL_OFF) 8349 _write_scbd(rtwdev, BTC_WSCB_ALL, false); 8350 else 8351 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false); 8352 8353 if (rf_state == BTC_RFCTRL_LPS_WL_ON && 8354 wl->status.map.lps_pre != BTC_LPS_OFF) 8355 _update_bt_scbd(rtwdev, true); 8356 } 8357 8358 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0; 8359 btc->dm.tdma_instant_excute = 1; 8360 8361 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE); 8362 wl->status.map.rf_off_pre = wl->status.map.rf_off; 8363 wl->status.map.lps_pre = wl->status.map.lps; 8364 } 8365 8366 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path, 8367 enum btc_wl_rfk_type type, 8368 enum btc_wl_rfk_state state) 8369 { 8370 struct rtw89_btc *btc = &rtwdev->btc; 8371 struct rtw89_btc_cx *cx = &btc->cx; 8372 struct rtw89_btc_wl_info *wl = &cx->wl; 8373 bool result = BTC_WRFK_REJECT; 8374 8375 wl->rfk_info.type = type; 8376 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path); 8377 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path); 8378 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path); 8379 8380 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8381 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n", 8382 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map, 8383 type, state); 8384 8385 switch (state) { 8386 case BTC_WRFK_START: 8387 result = _chk_wl_rfk_request(rtwdev); 8388 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP; 8389 8390 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result); 8391 8392 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++; 8393 break; 8394 case BTC_WRFK_ONESHOT_START: 8395 case BTC_WRFK_ONESHOT_STOP: 8396 if (wl->rfk_info.state == BTC_WRFK_STOP) { 8397 result = BTC_WRFK_REJECT; 8398 } else { 8399 result = BTC_WRFK_ALLOW; 8400 wl->rfk_info.state = state; 8401 } 8402 break; 8403 case BTC_WRFK_STOP: 8404 result = BTC_WRFK_ALLOW; 8405 wl->rfk_info.state = BTC_WRFK_STOP; 8406 8407 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false); 8408 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work); 8409 break; 8410 default: 8411 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8412 "[BTC], %s() warning state=%d\n", __func__, state); 8413 break; 8414 } 8415 8416 if (result == BTC_WRFK_ALLOW) { 8417 if (wl->rfk_info.state == BTC_WRFK_START || 8418 wl->rfk_info.state == BTC_WRFK_STOP) 8419 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK); 8420 8421 if (wl->rfk_info.state == BTC_WRFK_START) 8422 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 8423 &rtwdev->coex_rfk_chk_work, 8424 RTW89_COEX_RFK_CHK_WORK_PERIOD); 8425 } 8426 8427 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8428 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n", 8429 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result); 8430 8431 return result == BTC_WRFK_ALLOW; 8432 } 8433 8434 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, 8435 enum btc_wl_rfk_type type, 8436 enum btc_wl_rfk_state state) 8437 { 8438 u8 band; 8439 bool allow; 8440 int ret; 8441 8442 lockdep_assert_wiphy(rtwdev->hw->wiphy); 8443 8444 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map); 8445 8446 rtw89_debug(rtwdev, RTW89_DBG_RFK, 8447 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n", 8448 band == RTW89_BAND_2G ? "2G" : 8449 band == RTW89_BAND_5G ? "5G" : "6G", 8450 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)), 8451 type, 8452 FIELD_GET(BTC_RFK_PATH_MAP, phy_map), 8453 state == BTC_WRFK_STOP ? "RFK_STOP" : 8454 state == BTC_WRFK_START ? "RFK_START" : 8455 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" : 8456 "ONE-SHOT_STOP"); 8457 8458 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) { 8459 _ntfy_wl_rfk(rtwdev, phy_map, type, state); 8460 return; 8461 } 8462 8463 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false, 8464 rtwdev, phy_map, type, state); 8465 if (ret) { 8466 rtw89_warn(rtwdev, "RFK notify timeout\n"); 8467 rtwdev->is_bt_iqk_timeout = true; 8468 } 8469 } 8470 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk); 8471 8472 struct rtw89_btc_wl_sta_iter_data { 8473 struct rtw89_dev *rtwdev; 8474 u8 busy_all; 8475 u8 dir_all; 8476 u8 rssi_map_all; 8477 bool is_sta_change; 8478 bool is_traffic_change; 8479 }; 8480 8481 static 8482 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, 8483 struct rtw89_sta_link *rtwsta_link, 8484 struct rtw89_btc_wl_sta_iter_data *iter_data) 8485 { 8486 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 8487 struct rtw89_dev *rtwdev = iter_data->rtwdev; 8488 struct rtw89_btc *btc = &rtwdev->btc; 8489 struct rtw89_btc_dm *dm = &btc->dm; 8490 const struct rtw89_btc_ver *ver = btc->ver; 8491 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8492 struct rtw89_btc_wl_link_info *link_info = NULL; 8493 struct rtw89_traffic_stats *link_info_t = NULL; 8494 struct rtw89_traffic_stats *stats = &rtwvif->stats; 8495 const struct rtw89_chip_info *chip = rtwdev->chip; 8496 struct rtw89_btc_wl_role_info *r; 8497 struct rtw89_btc_wl_role_info_v1 *r1; 8498 u32 last_tx_rate, last_rx_rate; 8499 u16 last_tx_lvl, last_rx_lvl; 8500 u8 port = rtwvif_link->port; 8501 u8 rssi; 8502 u8 busy = 0; 8503 u8 dir = 0; 8504 u8 rssi_map = 0; 8505 u8 i = 0; 8506 bool is_sta_change = false, is_traffic_change = false; 8507 8508 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; 8509 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); 8510 8511 if (btc->ver->fwlrole != 8) 8512 link_info = &wl->link_info[port]; 8513 else 8514 link_info = &wl->rlink_info[port][rtwvif_link->mac_idx]; 8515 8516 link_info->stat.traffic = *stats; 8517 link_info_t = &link_info->stat.traffic; 8518 8519 if (link_info->connected == MLME_NO_LINK) { 8520 link_info->rx_rate_drop_cnt = 0; 8521 return; 8522 } 8523 8524 link_info->stat.rssi = rssi; 8525 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) { 8526 link_info->rssi_state[i] = 8527 _update_rssi_state(rtwdev, 8528 link_info->rssi_state[i], 8529 link_info->stat.rssi, 8530 chip->wl_rssi_thres[i]); 8531 if (BTC_RSSI_LOW(link_info->rssi_state[i])) 8532 rssi_map |= BIT(i); 8533 8534 if (btc->ant_type == BTC_ANT_DEDICATED && 8535 BTC_RSSI_CHANGE(link_info->rssi_state[i])) 8536 is_sta_change = true; 8537 } 8538 iter_data->rssi_map_all |= rssi_map; 8539 8540 last_tx_rate = link_info_t->tx_rate; 8541 last_rx_rate = link_info_t->rx_rate; 8542 last_tx_lvl = (u16)link_info_t->tx_tfc_lv; 8543 last_rx_lvl = (u16)link_info_t->rx_tfc_lv; 8544 8545 if (stats->tx_tfc_lv != RTW89_TFC_IDLE || 8546 stats->rx_tfc_lv != RTW89_TFC_IDLE) 8547 busy = 1; 8548 8549 if (stats->tx_tfc_lv > stats->rx_tfc_lv) 8550 dir = RTW89_TFC_UL; 8551 else 8552 dir = RTW89_TFC_DL; 8553 8554 link_info = &wl->link_info[port]; 8555 if (link_info->busy != busy || link_info->dir != dir) { 8556 is_sta_change = true; 8557 link_info->busy = busy; 8558 link_info->dir = dir; 8559 } 8560 8561 iter_data->busy_all |= busy; 8562 iter_data->dir_all |= BIT(dir); 8563 8564 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && 8565 last_rx_rate > RTW89_HW_RATE_CCK2 && 8566 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) 8567 link_info->rx_rate_drop_cnt++; 8568 8569 if (last_tx_rate != rtwsta_link->ra_report.hw_rate || 8570 last_rx_rate != rtwsta_link->rx_hw_rate || 8571 last_tx_lvl != link_info_t->tx_tfc_lv || 8572 last_rx_lvl != link_info_t->rx_tfc_lv) 8573 is_traffic_change = true; 8574 8575 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; 8576 link_info_t->rx_rate = rtwsta_link->rx_hw_rate; 8577 8578 if (link_info->role == RTW89_WIFI_ROLE_STATION || 8579 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { 8580 dm->trx_info.tx_rate = link_info_t->tx_rate; 8581 dm->trx_info.rx_rate = link_info_t->rx_rate; 8582 } 8583 8584 if (ver->fwlrole == 0) { 8585 r = &wl->role_info; 8586 r->active_role[port].tx_lvl = stats->tx_tfc_lv; 8587 r->active_role[port].rx_lvl = stats->rx_tfc_lv; 8588 r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate; 8589 r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate; 8590 } else if (ver->fwlrole == 1) { 8591 r1 = &wl->role_info_v1; 8592 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; 8593 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; 8594 r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate; 8595 r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate; 8596 } 8597 8598 dm->trx_info.tx_lvl = stats->tx_tfc_lv; 8599 dm->trx_info.rx_lvl = stats->rx_tfc_lv; 8600 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; 8601 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; 8602 dm->trx_info.tx_tp = link_info_t->tx_throughput; 8603 dm->trx_info.rx_tp = link_info_t->rx_throughput; 8604 8605 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */ 8606 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx && 8607 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) || 8608 (dm->wl_pre_agc_rb != dm->wl_pre_agc && 8609 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND)) 8610 iter_data->is_sta_change = true; 8611 8612 if (is_sta_change) 8613 iter_data->is_sta_change = true; 8614 8615 if (is_traffic_change) 8616 iter_data->is_traffic_change = true; 8617 } 8618 8619 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) 8620 { 8621 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 8622 struct rtw89_btc_wl_sta_iter_data *iter_data = 8623 (struct rtw89_btc_wl_sta_iter_data *)data; 8624 struct rtw89_vif_link *rtwvif_link; 8625 struct rtw89_sta_link *rtwsta_link; 8626 unsigned int link_id; 8627 8628 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { 8629 rtwvif_link = rtwsta_link->rtwvif_link; 8630 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); 8631 } 8632 } 8633 8634 #define BTC_NHM_CHK_INTVL 20 8635 8636 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) 8637 { 8638 struct rtw89_btc *btc = &rtwdev->btc; 8639 struct rtw89_btc_dm *dm = &btc->dm; 8640 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8641 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev}; 8642 u8 i; 8643 8644 ieee80211_iterate_stations_atomic(rtwdev->hw, 8645 rtw89_btc_ntfy_wl_sta_iter, 8646 &data); 8647 8648 wl->rssi_level = 0; 8649 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++; 8650 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) { 8651 /* set RSSI level 4 ~ 0 if rssi bit map match */ 8652 if (data.rssi_map_all & BIT(i - 1)) { 8653 wl->rssi_level = i; 8654 break; 8655 } 8656 } 8657 8658 if (dm->trx_info.wl_rssi != wl->rssi_level) 8659 dm->trx_info.wl_rssi = wl->rssi_level; 8660 8661 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n", 8662 __func__, !!wl->status.map.busy); 8663 8664 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy)); 8665 8666 if (data.is_traffic_change) 8667 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE); 8668 if (data.is_sta_change) { 8669 wl->status.map.busy = data.busy_all; 8670 wl->status.map.traffic_dir = data.dir_all; 8671 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA); 8672 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >= 8673 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) { 8674 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 8675 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 8676 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] < 8677 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) { 8678 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] = 8679 btc->dm.cnt_notify[BTC_NCNT_WL_STA]; 8680 } 8681 } 8682 8683 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) 8684 { 8685 struct rtw89_btc *btc = &rtwdev->btc; 8686 const struct rtw89_btc_ver *ver = btc->ver; 8687 8688 switch (func) { 8689 case BTF_EVNT_RPT: 8690 case BTF_EVNT_BT_INFO: 8691 case BTF_EVNT_BT_SCBD: 8692 case BTF_EVNT_BT_REG: 8693 case BTF_EVNT_CX_RUNINFO: 8694 case BTF_EVNT_BT_PSD: 8695 return func; 8696 case BTF_EVNT_BT_DEV_INFO: 8697 if (ver->fwc2hfunc == 0) 8698 return BTF_EVNT_BUF_OVERFLOW; 8699 else 8700 return BTF_EVNT_BT_DEV_INFO; 8701 case BTF_EVNT_BT_LEAUDIO_INFO: 8702 if (ver->fwc2hfunc == 0) 8703 return BTF_EVNT_C2H_LOOPBACK; 8704 else if (ver->fwc2hfunc == 1) 8705 return BTF_EVNT_BUF_OVERFLOW; 8706 else if (ver->fwc2hfunc == 2) 8707 return func; 8708 else if (ver->fwc2hfunc == 3) 8709 return BTF_EVNT_BUF_OVERFLOW; 8710 else 8711 return BTF_EVNT_MAX; 8712 case BTF_EVNT_BUF_OVERFLOW: 8713 if (ver->fwc2hfunc == 0) 8714 return BTF_EVNT_MAX; 8715 else if (ver->fwc2hfunc == 1) 8716 return BTF_EVNT_C2H_LOOPBACK; 8717 else if (ver->fwc2hfunc == 2) 8718 return func; 8719 else if (ver->fwc2hfunc == 3) 8720 return BTF_EVNT_C2H_LOOPBACK; 8721 else 8722 return BTF_EVNT_MAX; 8723 case BTF_EVNT_C2H_LOOPBACK: 8724 if (ver->fwc2hfunc == 2) 8725 return func; 8726 else if (ver->fwc2hfunc == 3) 8727 return BTF_EVNT_BT_LEAUDIO_INFO; 8728 else 8729 return BTF_EVNT_MAX; 8730 case BTF_EVNT_BT_QUERY_TXPWR: 8731 if (ver->fwc2hfunc == 3) 8732 return func; 8733 else 8734 return BTF_EVNT_MAX; 8735 case BTF_EVNT_MAX: 8736 default: 8737 return BTF_EVNT_MAX; 8738 } 8739 } 8740 8741 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, 8742 u32 len, u8 class, u8 func) 8743 { 8744 struct rtw89_btc *btc = &rtwdev->btc; 8745 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 8746 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN]; 8747 8748 len -= RTW89_C2H_HEADER_LEN; 8749 8750 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8751 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n", 8752 __func__, len, class, func); 8753 8754 if (class != BTFC_FW_EVENT) 8755 return; 8756 8757 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); 8758 pfwinfo->cnt_c2h++; 8759 8760 switch (func) { 8761 case BTF_EVNT_BUF_OVERFLOW: 8762 pfwinfo->event[func]++; 8763 break; 8764 case BTF_EVNT_RPT: 8765 pfwinfo->event[func]++; 8766 /* Don't need rtw89_leave_ps_mode() */ 8767 btc_fw_event(rtwdev, func, buf, len); 8768 break; 8769 case BTF_EVNT_BT_INFO: 8770 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8771 "[BTC], handle C2H BT INFO with data %8ph\n", buf); 8772 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++; 8773 _update_bt_info(rtwdev, buf, len); 8774 break; 8775 case BTF_EVNT_BT_SCBD: 8776 rtw89_debug(rtwdev, RTW89_DBG_BTC, 8777 "[BTC], handle C2H BT SCBD with data %8ph\n", buf); 8778 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++; 8779 _update_bt_scbd(rtwdev, false); 8780 break; 8781 case BTF_EVNT_BT_PSD: 8782 break; 8783 case BTF_EVNT_BT_REG: 8784 btc->dbg.rb_done = true; 8785 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf)); 8786 8787 break; 8788 case BTF_EVNT_C2H_LOOPBACK: 8789 btc->dbg.rb_done = true; 8790 btc->dbg.rb_val = buf[0]; 8791 break; 8792 case BTF_EVNT_CX_RUNINFO: 8793 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++; 8794 break; 8795 case BTF_EVNT_BT_QUERY_TXPWR: 8796 btc->cx.cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]++; 8797 _update_bt_txpwr_info(rtwdev, buf, len); 8798 } 8799 } 8800 8801 #define BTC_CX_FW_OFFLOAD 0 8802 8803 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8804 { 8805 union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; 8806 const struct rtw89_chip_info *chip = rtwdev->chip; 8807 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 8808 struct rtw89_hal *hal = &rtwdev->hal; 8809 struct rtw89_btc *btc = &rtwdev->btc; 8810 struct rtw89_btc_dm *dm = &btc->dm; 8811 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 8812 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 8813 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0; 8814 u8 cv, rfe, iso, ant_num, ant_single_pos; 8815 char *p = buf, *end = buf + bufsz; 8816 8817 if (!(dm->coex_info_map & BTC_COEX_INFO_CX)) 8818 return 0; 8819 8820 p += scnprintf(p, end - p, 8821 "\n========== [BTC COEX INFO (%s)] ==========\n", 8822 chip_id_str(chip->chip_id)); 8823 8824 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION); 8825 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION); 8826 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION); 8827 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION); 8828 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ", 8829 "[coex_version]", ver_main, ver_sub, ver_hotfix, 8830 id_branch); 8831 8832 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 8833 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex); 8834 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex); 8835 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex); 8836 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)", 8837 ver_main, ver_sub, ver_hotfix, id_branch); 8838 8839 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired); 8840 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired); 8841 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired); 8842 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ", 8843 (wl->ver_info.fw_coex >= chip->wlcx_desired ? 8844 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix); 8845 8846 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n", 8847 bt->ver_info.fw_coex, 8848 (bt->ver_info.fw_coex >= ver->bt_desired ? 8849 "Match" : "Mismatch"), ver->bt_desired); 8850 8851 if (bt->enable.now && bt->ver_info.fw == 0) 8852 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true); 8853 else 8854 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false); 8855 8856 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw); 8857 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw); 8858 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw); 8859 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw); 8860 p += scnprintf(p, end - p, 8861 " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n", 8862 "[sub_module]", 8863 ver_main, ver_sub, ver_hotfix, id_branch, 8864 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM"); 8865 8866 if (ver->fcxinit == 7) { 8867 cv = md->md_v7.kt_ver; 8868 rfe = md->md_v7.rfe_type; 8869 iso = md->md_v7.ant.isolation; 8870 ant_num = md->md_v7.ant.num; 8871 ant_single_pos = md->md_v7.ant.single_pos; 8872 } else { 8873 cv = md->md.cv; 8874 rfe = md->md.rfe_type; 8875 iso = md->md.ant.isolation; 8876 ant_num = md->md.ant.num; 8877 ant_single_pos = md->md.ant.single_pos; 8878 } 8879 8880 p += scnprintf(p, end - p, 8881 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s", 8882 "[hw_info]", cv, rfe, iso, ant_num, 8883 ant_num > 1 ? "" : 8884 ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, "); 8885 8886 p += scnprintf(p, end - p, 8887 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", 8888 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, 8889 hal->rx_nss); 8890 8891 return p - buf; 8892 } 8893 8894 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8895 { 8896 struct rtw89_btc *btc = &rtwdev->btc; 8897 struct rtw89_btc_wl_link_info *plink = NULL; 8898 struct rtw89_traffic_stats *t; 8899 char *p = buf, *end = buf + bufsz; 8900 u8 i, j; 8901 8902 for (i = 0; i < btc->ver->max_role_num; i++) { 8903 for (j = 0; j < RTW89_MAC_NUM; j++) { 8904 if (btc->ver->fwlrole == 8) 8905 plink = &btc->cx.wl.rlink_info[i][j]; 8906 else 8907 plink = &btc->cx.wl.link_info[i]; 8908 8909 if (!plink->active) 8910 continue; 8911 8912 p += scnprintf(p, end - p, 8913 " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d", 8914 plink->pid, plink->role, plink->phy, 8915 id_to_mlme_state(plink->connected), 8916 plink->client_cnt - 1, plink->mode, 8917 plink->ch, plink->bw); 8918 8919 if (plink->connected == MLME_NO_LINK) 8920 continue; 8921 8922 p += scnprintf(p, end - p, 8923 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n", 8924 plink->mac_id, plink->tx_time, plink->tx_retry); 8925 8926 p += scnprintf(p, end - p, 8927 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ", 8928 plink->pid, 110 - plink->stat.rssi, 8929 plink->stat.rssi, plink->busy, 8930 plink->dir == RTW89_TFC_UL ? "UL" : "DL"); 8931 8932 t = &plink->stat.traffic; 8933 8934 p += scnprintf(p, end - p, 8935 "tx[rate:%d/busy_level:%d], ", 8936 t->tx_rate, t->tx_tfc_lv); 8937 8938 p += scnprintf(p, end - p, 8939 "rx[rate:%d/busy_level:%d/drop:%d]\n", 8940 t->rx_rate, 8941 t->rx_tfc_lv, plink->rx_rate_drop_cnt); 8942 } 8943 } 8944 return p - buf; 8945 } 8946 8947 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 8948 { 8949 struct rtw89_btc *btc = &rtwdev->btc; 8950 const struct rtw89_btc_ver *ver = btc->ver; 8951 struct rtw89_btc_cx *cx = &btc->cx; 8952 struct rtw89_btc_wl_info *wl = &cx->wl; 8953 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info; 8954 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1; 8955 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2; 8956 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7; 8957 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8; 8958 char *p = buf, *end = buf + bufsz; 8959 u8 mode; 8960 8961 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL)) 8962 return 0; 8963 8964 p += scnprintf(p, end - p, "========== [WL Status] ==========\n"); 8965 8966 if (ver->fwlrole == 0) 8967 mode = wl_rinfo->link_mode; 8968 else if (ver->fwlrole == 1) 8969 mode = wl_rinfo_v1->link_mode; 8970 else if (ver->fwlrole == 2) 8971 mode = wl_rinfo_v2->link_mode; 8972 else if (ver->fwlrole == 7) 8973 mode = wl_rinfo_v7->link_mode; 8974 else if (ver->fwlrole == 8) 8975 mode = wl_rinfo_v8->link_mode; 8976 else 8977 goto out; 8978 8979 p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]", 8980 id_to_linkmode(mode)); 8981 8982 p += scnprintf(p, end - p, 8983 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ", 8984 wl->status.map.rf_off, wl->status.map.lps, 8985 wl->status.map.scan ? "Y" : "N", 8986 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map); 8987 8988 p += scnprintf(p, end - p, 8989 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n", 8990 wl->status.map.connecting ? "Y" : "N", 8991 wl->status.map.roaming ? "Y" : "N", 8992 wl->status.map._4way ? "Y" : "N", 8993 wl->status.map.init_ok ? "Y" : "N"); 8994 8995 p += _show_wl_role_info(rtwdev, p, end - p); 8996 8997 out: 8998 return p - buf; 8999 } 9000 9001 enum btc_bt_a2dp_type { 9002 BTC_A2DP_LEGACY = 0, 9003 BTC_A2DP_TWS_SNIFF = 1, 9004 BTC_A2DP_TWS_RELAY = 2, 9005 }; 9006 9007 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9008 { 9009 struct rtw89_btc *btc = &rtwdev->btc; 9010 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; 9011 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc; 9012 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; 9013 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 9014 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; 9015 char *p = buf, *end = buf + bufsz; 9016 9017 if (hfp.exist) { 9018 p += scnprintf(p, end - p, 9019 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d", 9020 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"), 9021 bt_linfo->sut_pwr_level[0], 9022 bt_linfo->golden_rx_shift[0]); 9023 } 9024 9025 if (hid.exist) { 9026 p += scnprintf(p, end - p, 9027 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n", 9028 "[HID]", 9029 hid.type & BTC_HID_218 ? "2/18," : "", 9030 hid.type & BTC_HID_418 ? "4/18," : "", 9031 hid.type & BTC_HID_BLE ? "BLE," : "", 9032 hid.type & BTC_HID_RCU ? "RCU," : "", 9033 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "", 9034 hid.pair_cnt, bt_linfo->sut_pwr_level[1], 9035 bt_linfo->golden_rx_shift[1]); 9036 } 9037 9038 if (a2dp.exist) { 9039 p += scnprintf(p, end - p, 9040 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ", 9041 "[A2DP]", 9042 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS", 9043 a2dp.bitpool, a2dp.flush_time); 9044 9045 p += scnprintf(p, end - p, 9046 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n", 9047 a2dp.vendor_id, a2dp.device_name, 9048 bt_linfo->sut_pwr_level[2], 9049 bt_linfo->golden_rx_shift[2]); 9050 } 9051 9052 if (pan.exist) { 9053 p += scnprintf(p, end - p, 9054 " %-15s : sut_pwr:%d, golden-rx:%d\n", 9055 "[PAN]", 9056 bt_linfo->sut_pwr_level[3], 9057 bt_linfo->golden_rx_shift[3]); 9058 } 9059 9060 return p - buf; 9061 } 9062 9063 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9064 { 9065 struct rtw89_btc *btc = &rtwdev->btc; 9066 const struct rtw89_btc_ver *ver = btc->ver; 9067 struct rtw89_btc_cx *cx = &btc->cx; 9068 struct rtw89_btc_bt_info *bt = &cx->bt; 9069 struct rtw89_btc_wl_info *wl = &cx->wl; 9070 u32 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex); 9071 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; 9072 union rtw89_btc_module_info *md = &btc->mdinfo; 9073 s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm; 9074 s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm; 9075 char *p = buf, *end = buf + bufsz; 9076 u8 *afh = bt_linfo->afh_map; 9077 u8 *afh_le = bt_linfo->afh_map_le; 9078 u8 bt_pos; 9079 9080 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT)) 9081 return 0; 9082 9083 if (ver->fcxinit == 7) 9084 bt_pos = md->md_v7.bt_pos; 9085 else 9086 bt_pos = md->md.bt_pos; 9087 9088 p += scnprintf(p, end - p, "========== [BT Status] ==========\n"); 9089 9090 p += scnprintf(p, end - p, 9091 " %-15s : enable:%s, btg:%s%s, connect:%s, ", 9092 "[status]", bt->enable.now ? "Y" : "N", 9093 bt->btg_type ? "Y" : "N", 9094 (bt->enable.now && (bt->btg_type != bt_pos) ? 9095 "(efuse-mismatch!!)" : ""), 9096 (bt_linfo->status.map.connect ? "Y" : "N")); 9097 9098 p += scnprintf(p, end - p, 9099 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n", 9100 bt->igno_wl ? "Y" : "N", 9101 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val); 9102 9103 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ", 9104 "[profile]", 9105 (bt_linfo->profile_cnt.now == 0) ? "None," : "", 9106 bt_linfo->hfp_desc.exist ? "HFP," : "", 9107 bt_linfo->hid_desc.exist ? "HID," : "", 9108 bt_linfo->a2dp_desc.exist ? 9109 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "", 9110 bt_linfo->pan_desc.exist ? "PAN," : ""); 9111 9112 p += scnprintf(p, end - p, 9113 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n", 9114 bt_linfo->multi_link.now ? "Y" : "N", 9115 bt_linfo->slave_role ? "Slave" : "Master", 9116 bt_linfo->status.map.ble_connect ? "Y" : "N", 9117 bt_linfo->cqddr ? "Y" : "N", 9118 bt_linfo->a2dp_desc.active ? "Y" : "N", 9119 bt_linfo->pan_desc.active ? "Y" : "N"); 9120 9121 p += scnprintf(p, end - p, 9122 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s", 9123 "[link]", bt_linfo->rssi - 100, 9124 bt->rssi_level, 9125 bt_linfo->tx_3m ? 3 : 2, 9126 bt_linfo->status.map.inq_pag ? " inq-page!!" : "", 9127 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "", 9128 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : ""); 9129 9130 p += scnprintf(p, end - p, 9131 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ", 9132 bt_linfo->relink.now ? " ReLink!!" : "", 9133 afh[0], afh[1], afh[2], afh[3], afh[4], 9134 afh[5], afh[6], afh[7], afh[8], afh[9]); 9135 9136 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 9137 p += scnprintf(p, end - p, 9138 "LE[%02x%02x_%02x_%02x%02x]", 9139 afh_le[0], afh_le[1], afh_le[2], 9140 afh_le[3], afh_le[4]); 9141 9142 p += scnprintf(p, end - p, "wl_ch_map[en:%d/ch:%d/bw:%d]\n", 9143 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw); 9144 9145 p += scnprintf(p, end - p, 9146 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ", 9147 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY], 9148 cx->cnt_bt[BTC_BCNT_RELINK], 9149 cx->cnt_bt[BTC_BCNT_RATECHG], 9150 cx->cnt_bt[BTC_BCNT_REINIT], 9151 cx->cnt_bt[BTC_BCNT_REENABLE]); 9152 9153 p += scnprintf(p, end - p, 9154 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n", 9155 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH], 9156 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ], 9157 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]); 9158 9159 p += _show_bt_profile_info(rtwdev, p, end - p); 9160 9161 p += scnprintf(p, end - p, 9162 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n", 9163 "[bt_info]", bt->raw_info[2], bt->raw_info[3], 9164 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6], 9165 bt->raw_info[7], 9166 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply", 9167 cx->cnt_bt[BTC_BCNT_INFOUPDATE], 9168 cx->cnt_bt[BTC_BCNT_INFOSAME]); 9169 9170 p += scnprintf(p, end - p, 9171 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)", 9172 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX], 9173 cx->cnt_bt[BTC_BCNT_HIPRI_TX], 9174 cx->cnt_bt[BTC_BCNT_LOPRI_RX], 9175 cx->cnt_bt[BTC_BCNT_LOPRI_TX], 9176 cx->cnt_bt[BTC_BCNT_POLUT]); 9177 9178 if (!bt->scan_info_update) { 9179 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true); 9180 p += scnprintf(p, end - p, "\n"); 9181 } else { 9182 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false); 9183 if (ver->fcxbtscan == 1) { 9184 p += scnprintf(p, end - p, 9185 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)", 9186 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win), 9187 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl), 9188 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win), 9189 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl), 9190 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win), 9191 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl), 9192 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win), 9193 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl)); 9194 } else if (ver->fcxbtscan == 2) { 9195 p += scnprintf(p, end - p, 9196 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)", 9197 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win), 9198 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl), 9199 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win), 9200 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl), 9201 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win), 9202 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl)); 9203 } 9204 p += scnprintf(p, end - p, "\n"); 9205 } 9206 9207 if (ver_main >= 9 && bt_linfo->profile_cnt.now) 9208 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, true); 9209 else 9210 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, false); 9211 9212 if (cx->cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]) { 9213 p += scnprintf(p, end - p, 9214 " %-15s : br_index:0x%x, le_index:0x%x", 9215 "[bt_txpwr_lvl]", 9216 bt->link_info.bt_txpwr_desc.br_gain_index, 9217 bt->link_info.bt_txpwr_desc.le_gain_index); 9218 p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm); 9219 p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm); 9220 } else { 9221 p += scnprintf(p, end - p, 9222 " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]", 9223 "[bt_txpwr_lvl]", 9224 bt->link_info.bt_txpwr_desc.br_dbm, 9225 bt->link_info.bt_txpwr_desc.le_dbm); 9226 } 9227 p += scnprintf(p, end - p, "\n"); 9228 9229 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect) 9230 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true); 9231 else 9232 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false); 9233 9234 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect) 9235 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true); 9236 else 9237 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false); 9238 9239 if (bt_linfo->a2dp_desc.exist && 9240 (bt_linfo->a2dp_desc.flush_time == 0 || 9241 bt_linfo->a2dp_desc.vendor_id == 0 || 9242 bt_linfo->a2dp_desc.play_latency == 1)) 9243 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true); 9244 else 9245 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false); 9246 9247 return p - buf; 9248 } 9249 9250 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e 9251 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e 9252 #define CASE_BTC_POLICY_STR(e) \ 9253 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e 9254 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e 9255 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e 9256 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e 9257 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e 9258 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e 9259 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e 9260 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e 9261 9262 static const char *id_to_polut(u32 id) 9263 { 9264 switch (id) { 9265 CASE_BTC_POLUT_STR(NONE); 9266 CASE_BTC_POLUT_STR(GNT_BT_TX); 9267 CASE_BTC_POLUT_STR(GNT_BT_RX); 9268 CASE_BTC_POLUT_STR(GNT_WL); 9269 CASE_BTC_POLUT_STR(BT); 9270 CASE_BTC_POLUT_STR(ALL); 9271 default: 9272 return "unknown"; 9273 } 9274 } 9275 9276 static const char *id_to_regtype(u32 id) 9277 { 9278 switch (id) { 9279 CASE_BTC_REGTYPE_STR(MAC); 9280 CASE_BTC_REGTYPE_STR(BB); 9281 CASE_BTC_REGTYPE_STR(RF); 9282 CASE_BTC_REGTYPE_STR(BT_RF); 9283 CASE_BTC_REGTYPE_STR(BT_MODEM); 9284 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE); 9285 CASE_BTC_REGTYPE_STR(BT_VENDOR); 9286 CASE_BTC_REGTYPE_STR(BT_LE); 9287 default: 9288 return "unknown"; 9289 } 9290 } 9291 9292 static const char *id_to_gdbg(u32 id) 9293 { 9294 switch (id) { 9295 CASE_BTC_GDBG_STR(GNT_BT); 9296 CASE_BTC_GDBG_STR(GNT_WL); 9297 CASE_BTC_GDBG_STR(BCN_EARLY); 9298 CASE_BTC_GDBG_STR(WL_NULL0); 9299 CASE_BTC_GDBG_STR(WL_NULL1); 9300 CASE_BTC_GDBG_STR(WL_RXISR); 9301 CASE_BTC_GDBG_STR(TDMA_ENTRY); 9302 CASE_BTC_GDBG_STR(A2DP_EMPTY); 9303 CASE_BTC_GDBG_STR(BT_RETRY); 9304 CASE_BTC_GDBG_STR(BT_RELINK); 9305 CASE_BTC_GDBG_STR(SLOT_WL); 9306 CASE_BTC_GDBG_STR(SLOT_BT); 9307 CASE_BTC_GDBG_STR(WL_ERR); 9308 CASE_BTC_GDBG_STR(WL_OK); 9309 CASE_BTC_GDBG_STR(SLOT_B2W); 9310 CASE_BTC_GDBG_STR(SLOT_W1); 9311 CASE_BTC_GDBG_STR(SLOT_W2); 9312 CASE_BTC_GDBG_STR(SLOT_W2B); 9313 CASE_BTC_GDBG_STR(SLOT_B1); 9314 CASE_BTC_GDBG_STR(SLOT_B2); 9315 CASE_BTC_GDBG_STR(SLOT_B3); 9316 CASE_BTC_GDBG_STR(SLOT_B4); 9317 CASE_BTC_GDBG_STR(SLOT_LK); 9318 CASE_BTC_GDBG_STR(SLOT_E2G); 9319 CASE_BTC_GDBG_STR(SLOT_E5G); 9320 CASE_BTC_GDBG_STR(SLOT_EBT); 9321 CASE_BTC_GDBG_STR(SLOT_WLK); 9322 CASE_BTC_GDBG_STR(SLOT_B1FDD); 9323 CASE_BTC_GDBG_STR(BT_CHANGE); 9324 CASE_BTC_GDBG_STR(WL_CCA); 9325 CASE_BTC_GDBG_STR(BT_LEAUDIO); 9326 CASE_BTC_GDBG_STR(USER_DEF); 9327 default: 9328 return "unknown"; 9329 } 9330 } 9331 9332 static const char *steps_to_str(u16 step) 9333 { 9334 switch (step) { 9335 CASE_BTC_RSN_STR(NONE); 9336 CASE_BTC_RSN_STR(NTFY_INIT); 9337 CASE_BTC_RSN_STR(NTFY_SWBAND); 9338 CASE_BTC_RSN_STR(NTFY_WL_STA); 9339 CASE_BTC_RSN_STR(NTFY_RADIO_STATE); 9340 CASE_BTC_RSN_STR(UPDATE_BT_SCBD); 9341 CASE_BTC_RSN_STR(NTFY_WL_RFK); 9342 CASE_BTC_RSN_STR(UPDATE_BT_INFO); 9343 CASE_BTC_RSN_STR(NTFY_SCAN_START); 9344 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH); 9345 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET); 9346 CASE_BTC_RSN_STR(NTFY_POWEROFF); 9347 CASE_BTC_RSN_STR(NTFY_ROLE_INFO); 9348 CASE_BTC_RSN_STR(CMD_SET_COEX); 9349 CASE_BTC_RSN_STR(ACT1_WORK); 9350 CASE_BTC_RSN_STR(BT_DEVINFO_WORK); 9351 CASE_BTC_RSN_STR(RFK_CHK_WORK); 9352 9353 CASE_BTC_ACT_STR(NONE); 9354 CASE_BTC_ACT_STR(WL_ONLY); 9355 CASE_BTC_ACT_STR(WL_5G); 9356 CASE_BTC_ACT_STR(WL_OTHER); 9357 CASE_BTC_ACT_STR(WL_IDLE); 9358 CASE_BTC_ACT_STR(WL_NC); 9359 CASE_BTC_ACT_STR(WL_RFK); 9360 CASE_BTC_ACT_STR(WL_INIT); 9361 CASE_BTC_ACT_STR(WL_OFF); 9362 CASE_BTC_ACT_STR(FREERUN); 9363 CASE_BTC_ACT_STR(BT_WHQL); 9364 CASE_BTC_ACT_STR(BT_RFK); 9365 CASE_BTC_ACT_STR(BT_OFF); 9366 CASE_BTC_ACT_STR(BT_IDLE); 9367 CASE_BTC_ACT_STR(BT_HFP); 9368 CASE_BTC_ACT_STR(BT_HID); 9369 CASE_BTC_ACT_STR(BT_A2DP); 9370 CASE_BTC_ACT_STR(BT_A2DPSINK); 9371 CASE_BTC_ACT_STR(BT_PAN); 9372 CASE_BTC_ACT_STR(BT_A2DP_HID); 9373 CASE_BTC_ACT_STR(BT_A2DP_PAN); 9374 CASE_BTC_ACT_STR(BT_PAN_HID); 9375 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID); 9376 CASE_BTC_ACT_STR(WL_25G_MCC); 9377 CASE_BTC_ACT_STR(WL_2G_MCC); 9378 CASE_BTC_ACT_STR(WL_2G_SCC); 9379 CASE_BTC_ACT_STR(WL_2G_AP); 9380 CASE_BTC_ACT_STR(WL_2G_GO); 9381 CASE_BTC_ACT_STR(WL_2G_GC); 9382 CASE_BTC_ACT_STR(WL_2G_NAN); 9383 9384 CASE_BTC_POLICY_STR(OFF_BT); 9385 CASE_BTC_POLICY_STR(OFF_WL); 9386 CASE_BTC_POLICY_STR(OFF_EQ0); 9387 CASE_BTC_POLICY_STR(OFF_EQ1); 9388 CASE_BTC_POLICY_STR(OFF_EQ2); 9389 CASE_BTC_POLICY_STR(OFF_EQ3); 9390 CASE_BTC_POLICY_STR(OFF_EQ4); 9391 CASE_BTC_POLICY_STR(OFF_EQ5); 9392 CASE_BTC_POLICY_STR(OFF_BWB0); 9393 CASE_BTC_POLICY_STR(OFF_BWB1); 9394 CASE_BTC_POLICY_STR(OFF_BWB2); 9395 CASE_BTC_POLICY_STR(OFF_BWB3); 9396 CASE_BTC_POLICY_STR(OFF_WL2); 9397 CASE_BTC_POLICY_STR(OFFB_BWB0); 9398 CASE_BTC_POLICY_STR(OFFE_DEF); 9399 CASE_BTC_POLICY_STR(OFFE_DEF2); 9400 CASE_BTC_POLICY_STR(OFFE_2GBWISOB); 9401 CASE_BTC_POLICY_STR(OFFE_2GISOB); 9402 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB); 9403 CASE_BTC_POLICY_STR(OFFE_WL); 9404 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2); 9405 CASE_BTC_POLICY_STR(FIX_TD3030); 9406 CASE_BTC_POLICY_STR(FIX_TD5050); 9407 CASE_BTC_POLICY_STR(FIX_TD2030); 9408 CASE_BTC_POLICY_STR(FIX_TD4010); 9409 CASE_BTC_POLICY_STR(FIX_TD7010); 9410 CASE_BTC_POLICY_STR(FIX_TD2060); 9411 CASE_BTC_POLICY_STR(FIX_TD3060); 9412 CASE_BTC_POLICY_STR(FIX_TD2080); 9413 CASE_BTC_POLICY_STR(FIX_TDW1B1); 9414 CASE_BTC_POLICY_STR(FIX_TD4010ISO); 9415 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL); 9416 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL); 9417 CASE_BTC_POLICY_STR(PFIX_TD3030); 9418 CASE_BTC_POLICY_STR(PFIX_TD5050); 9419 CASE_BTC_POLICY_STR(PFIX_TD2030); 9420 CASE_BTC_POLICY_STR(PFIX_TD2060); 9421 CASE_BTC_POLICY_STR(PFIX_TD3070); 9422 CASE_BTC_POLICY_STR(PFIX_TD2080); 9423 CASE_BTC_POLICY_STR(PFIX_TDW1B1); 9424 CASE_BTC_POLICY_STR(AUTO_TD50B1); 9425 CASE_BTC_POLICY_STR(AUTO_TD60B1); 9426 CASE_BTC_POLICY_STR(AUTO_TD20B1); 9427 CASE_BTC_POLICY_STR(AUTO_TDW1B1); 9428 CASE_BTC_POLICY_STR(PAUTO_TD50B1); 9429 CASE_BTC_POLICY_STR(PAUTO_TD60B1); 9430 CASE_BTC_POLICY_STR(PAUTO_TD20B1); 9431 CASE_BTC_POLICY_STR(PAUTO_TDW1B1); 9432 CASE_BTC_POLICY_STR(AUTO2_TD3050); 9433 CASE_BTC_POLICY_STR(AUTO2_TD3070); 9434 CASE_BTC_POLICY_STR(AUTO2_TD5050); 9435 CASE_BTC_POLICY_STR(AUTO2_TD6060); 9436 CASE_BTC_POLICY_STR(AUTO2_TD2080); 9437 CASE_BTC_POLICY_STR(AUTO2_TDW1B4); 9438 CASE_BTC_POLICY_STR(PAUTO2_TD3050); 9439 CASE_BTC_POLICY_STR(PAUTO2_TD3070); 9440 CASE_BTC_POLICY_STR(PAUTO2_TD5050); 9441 CASE_BTC_POLICY_STR(PAUTO2_TD6060); 9442 CASE_BTC_POLICY_STR(PAUTO2_TD2080); 9443 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4); 9444 default: 9445 return "unknown step"; 9446 } 9447 } 9448 9449 static const char *id_to_slot(u32 id) 9450 { 9451 switch (id) { 9452 CASE_BTC_SLOT_STR(OFF); 9453 CASE_BTC_SLOT_STR(B2W); 9454 CASE_BTC_SLOT_STR(W1); 9455 CASE_BTC_SLOT_STR(W2); 9456 CASE_BTC_SLOT_STR(W2B); 9457 CASE_BTC_SLOT_STR(B1); 9458 CASE_BTC_SLOT_STR(B2); 9459 CASE_BTC_SLOT_STR(B3); 9460 CASE_BTC_SLOT_STR(B4); 9461 CASE_BTC_SLOT_STR(LK); 9462 CASE_BTC_SLOT_STR(BLK); 9463 CASE_BTC_SLOT_STR(E2G); 9464 CASE_BTC_SLOT_STR(E5G); 9465 CASE_BTC_SLOT_STR(EBT); 9466 CASE_BTC_SLOT_STR(ENULL); 9467 CASE_BTC_SLOT_STR(WLK); 9468 CASE_BTC_SLOT_STR(W1FDD); 9469 CASE_BTC_SLOT_STR(B1FDD); 9470 default: 9471 return "unknown"; 9472 } 9473 } 9474 9475 static const char *id_to_evt(u32 id) 9476 { 9477 switch (id) { 9478 CASE_BTC_EVT_STR(TDMA_ENTRY); 9479 CASE_BTC_EVT_STR(WL_TMR); 9480 CASE_BTC_EVT_STR(B1_TMR); 9481 CASE_BTC_EVT_STR(B2_TMR); 9482 CASE_BTC_EVT_STR(B3_TMR); 9483 CASE_BTC_EVT_STR(B4_TMR); 9484 CASE_BTC_EVT_STR(W2B_TMR); 9485 CASE_BTC_EVT_STR(B2W_TMR); 9486 CASE_BTC_EVT_STR(BCN_EARLY); 9487 CASE_BTC_EVT_STR(A2DP_EMPTY); 9488 CASE_BTC_EVT_STR(LK_END); 9489 CASE_BTC_EVT_STR(RX_ISR); 9490 CASE_BTC_EVT_STR(RX_FC0); 9491 CASE_BTC_EVT_STR(RX_FC1); 9492 CASE_BTC_EVT_STR(BT_RELINK); 9493 CASE_BTC_EVT_STR(BT_RETRY); 9494 CASE_BTC_EVT_STR(E2G); 9495 CASE_BTC_EVT_STR(E5G); 9496 CASE_BTC_EVT_STR(EBT); 9497 CASE_BTC_EVT_STR(ENULL); 9498 CASE_BTC_EVT_STR(DRV_WLK); 9499 CASE_BTC_EVT_STR(BCN_OK); 9500 CASE_BTC_EVT_STR(BT_CHANGE); 9501 CASE_BTC_EVT_STR(EBT_EXTEND); 9502 CASE_BTC_EVT_STR(E2G_NULL1); 9503 CASE_BTC_EVT_STR(B1FDD_TMR); 9504 default: 9505 return "unknown"; 9506 } 9507 } 9508 9509 static const char *id_to_mode(u8 id) 9510 { 9511 switch (id) { 9512 CASE_BTC_INIT(NORMAL); 9513 CASE_BTC_INIT(WL); 9514 CASE_BTC_INIT(BT); 9515 CASE_BTC_INIT(WLOFF); 9516 default: 9517 return "unknown"; 9518 } 9519 } 9520 9521 static const char *id_to_ant(u32 id) 9522 { 9523 switch (id) { 9524 CASE_BTC_ANTPATH_STR(WPOWERON); 9525 CASE_BTC_ANTPATH_STR(WINIT); 9526 CASE_BTC_ANTPATH_STR(WONLY); 9527 CASE_BTC_ANTPATH_STR(WOFF); 9528 CASE_BTC_ANTPATH_STR(W2G); 9529 CASE_BTC_ANTPATH_STR(W5G); 9530 CASE_BTC_ANTPATH_STR(W25G); 9531 CASE_BTC_ANTPATH_STR(FREERUN); 9532 CASE_BTC_ANTPATH_STR(WRFK); 9533 CASE_BTC_ANTPATH_STR(BRFK); 9534 CASE_BTC_ANTPATH_STR(MAX); 9535 default: 9536 return "unknown"; 9537 } 9538 } 9539 9540 static 9541 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data, 9542 u8 len, u8 seg_len, u8 start_idx, u8 ring_len) 9543 { 9544 char *p = buf, *end = buf + bufsz; 9545 u8 cur_index; 9546 u8 i; 9547 9548 for (i = 0; i < len ; i++) { 9549 if ((i % seg_len) == 0) 9550 p += scnprintf(p, end - p, " %-15s : ", prefix); 9551 cur_index = (start_idx + i) % ring_len; 9552 if (i % 3 == 0) 9553 p += scnprintf(p, end - p, "-> %-20s", 9554 steps_to_str(*(data + cur_index))); 9555 else if (i % 3 == 1) 9556 p += scnprintf(p, end - p, "-> %-15s", 9557 steps_to_str(*(data + cur_index))); 9558 else 9559 p += scnprintf(p, end - p, "-> %-13s", 9560 steps_to_str(*(data + cur_index))); 9561 if (i == (len - 1) || (i % seg_len) == (seg_len - 1)) 9562 p += scnprintf(p, end - p, "\n"); 9563 } 9564 9565 return p - buf; 9566 } 9567 9568 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9569 { 9570 struct rtw89_btc *btc = &rtwdev->btc; 9571 struct rtw89_btc_dm *dm = &btc->dm; 9572 char *p = buf, *end = buf + bufsz; 9573 u8 start_idx; 9574 u8 len; 9575 9576 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos; 9577 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0; 9578 9579 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len, 9580 6, start_idx, ARRAY_SIZE(dm->dm_step.step)); 9581 9582 return p - buf; 9583 } 9584 9585 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9586 { 9587 struct rtw89_btc *btc = &rtwdev->btc; 9588 const struct rtw89_btc_ver *ver = btc->ver; 9589 struct rtw89_btc_dm *dm = &btc->dm; 9590 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 9591 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 9592 char *p = buf, *end = buf + bufsz; 9593 u8 igno_bt; 9594 9595 if (!(dm->coex_info_map & BTC_COEX_INFO_DM)) 9596 return 0; 9597 9598 p += scnprintf(p, end - p, 9599 "========== [Mechanism Status %s] ==========\n", 9600 (btc->manual_ctrl ? "(Manual)" : "(Auto)")); 9601 9602 p += scnprintf(p, end - p, 9603 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n", 9604 "[status]", 9605 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated", 9606 steps_to_str(dm->run_reason), 9607 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT), 9608 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)), 9609 id_to_mode(wl->coex_mode), 9610 dm->cnt_dm[BTC_DCNT_RUN]); 9611 9612 p += _show_dm_step(rtwdev, p, end - p); 9613 9614 if (ver->fcxctrl == 7) 9615 igno_bt = btc->ctrl.ctrl_v7.igno_bt; 9616 else 9617 igno_bt = btc->ctrl.ctrl.igno_bt; 9618 9619 p += scnprintf(p, end - p, 9620 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ", 9621 "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt, 9622 dm->freerun, btc->lps, dm->wl_mimo_ps); 9623 9624 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n", 9625 dm->leak_ap, 9626 (BTC_CX_FW_OFFLOAD ? "Y" : "N"), 9627 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ? 9628 "" : "(Mismatch!!)")); 9629 9630 if (dm->rf_trx_para.wl_tx_power == 0xff) 9631 p += scnprintf(p, end - p, 9632 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ", 9633 "[trx_ctrl]", wl->rssi_level, 9634 dm->trx_para_level); 9635 9636 else 9637 p += scnprintf(p, end - p, 9638 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ", 9639 "[trx_ctrl]", wl->rssi_level, 9640 dm->trx_para_level, 9641 dm->rf_trx_para.wl_tx_power); 9642 9643 p += scnprintf(p, end - p, 9644 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n", 9645 dm->rf_trx_para.wl_rx_gain, 9646 dm->rf_trx_para.bt_tx_power, 9647 dm->rf_trx_para.bt_rx_gain, 9648 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx); 9649 9650 p += scnprintf(p, end - p, 9651 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n", 9652 "[dm_ctrl]", dm->wl_tx_limit.enable, 9653 dm->wl_tx_limit.tx_time, 9654 dm->wl_tx_limit.tx_retry, btc->bt_req_len, 9655 bt->scan_rx_low_pri); 9656 9657 return p - buf; 9658 } 9659 9660 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9661 { 9662 struct rtw89_btc *btc = &rtwdev->btc; 9663 const struct rtw89_btc_ver *ver = btc->ver; 9664 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9665 union rtw89_btc_fbtc_cysta_info *pcysta; 9666 char *p = buf, *end = buf + bufsz; 9667 u32 except_cnt, exception_map; 9668 9669 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo; 9670 if (ver->fcxcysta == 2) { 9671 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2; 9672 except_cnt = le32_to_cpu(pcysta->v2.except_cnt); 9673 exception_map = le32_to_cpu(pcysta->v2.exception); 9674 } else if (ver->fcxcysta == 3) { 9675 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3; 9676 except_cnt = le32_to_cpu(pcysta->v3.except_cnt); 9677 exception_map = le32_to_cpu(pcysta->v3.except_map); 9678 } else if (ver->fcxcysta == 4) { 9679 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4; 9680 except_cnt = pcysta->v4.except_cnt; 9681 exception_map = le32_to_cpu(pcysta->v4.except_map); 9682 } else if (ver->fcxcysta == 5) { 9683 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5; 9684 except_cnt = pcysta->v5.except_cnt; 9685 exception_map = le32_to_cpu(pcysta->v5.except_map); 9686 } else if (ver->fcxcysta == 7) { 9687 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7; 9688 except_cnt = pcysta->v7.except_cnt; 9689 exception_map = le32_to_cpu(pcysta->v7.except_map); 9690 } else { 9691 return 0; 9692 } 9693 9694 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 && 9695 !pfwinfo->len_mismch && !pfwinfo->fver_mismch) 9696 return 0; 9697 9698 p += scnprintf(p, end - p, " %-15s : ", "[error]"); 9699 9700 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) { 9701 p += scnprintf(p, end - p, 9702 "overflow-cnt: %d, ", 9703 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]); 9704 } 9705 9706 if (pfwinfo->len_mismch) { 9707 p += scnprintf(p, end - p, 9708 "len-mismatch: 0x%x, ", 9709 pfwinfo->len_mismch); 9710 } 9711 9712 if (pfwinfo->fver_mismch) { 9713 p += scnprintf(p, end - p, 9714 "fver-mismatch: 0x%x, ", 9715 pfwinfo->fver_mismch); 9716 } 9717 9718 /* cycle statistics exceptions */ 9719 if (exception_map || except_cnt) { 9720 p += scnprintf(p, end - p, 9721 "exception-type: 0x%x, exception-cnt = %d", 9722 exception_map, except_cnt); 9723 } 9724 p += scnprintf(p, end - p, "\n"); 9725 9726 return p - buf; 9727 } 9728 9729 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9730 { 9731 struct rtw89_btc *btc = &rtwdev->btc; 9732 const struct rtw89_btc_ver *ver = btc->ver; 9733 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9734 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 9735 struct rtw89_btc_fbtc_tdma *t = NULL; 9736 char *p = buf, *end = buf + bufsz; 9737 9738 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo; 9739 if (!pcinfo->valid) 9740 return 0; 9741 9742 if (ver->fcxtdma == 1) 9743 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1; 9744 else 9745 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma; 9746 9747 p += scnprintf(p, end - p, 9748 " %-15s : ", "[tdma_policy]"); 9749 p += scnprintf(p, end - p, 9750 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ", 9751 (u32)t->type, 9752 t->rxflctrl, t->txpause); 9753 9754 p += scnprintf(p, end - p, 9755 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ", 9756 t->wtgle_n, t->leak_n, t->ext_ctrl); 9757 9758 p += scnprintf(p, end - p, 9759 "policy_type:%d", 9760 (u32)btc->policy_type); 9761 9762 p += scnprintf(p, end - p, "\n"); 9763 9764 return p - buf; 9765 } 9766 9767 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9768 { 9769 struct rtw89_btc *btc = &rtwdev->btc; 9770 struct rtw89_btc_dm *dm = &btc->dm; 9771 char *p = buf, *end = buf + bufsz; 9772 u16 dur, cxtype; 9773 u32 tbl; 9774 u8 i = 0; 9775 9776 for (i = 0; i < CXST_MAX; i++) { 9777 if (btc->ver->fcxslots == 1) { 9778 dur = le16_to_cpu(dm->slot_now.v1[i].dur); 9779 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl); 9780 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype); 9781 } else if (btc->ver->fcxslots == 7) { 9782 dur = le16_to_cpu(dm->slot_now.v7[i].dur); 9783 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl); 9784 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype); 9785 } else { 9786 return 0; 9787 } 9788 9789 if (i % 5 == 0) 9790 p += scnprintf(p, end - p, 9791 " %-15s : %5s[%03d/0x%x/%d]", 9792 "[slot_list]", 9793 id_to_slot((u32)i), 9794 dur, tbl, cxtype); 9795 else 9796 p += scnprintf(p, end - p, 9797 ", %5s[%03d/0x%x/%d]", 9798 id_to_slot((u32)i), 9799 dur, tbl, cxtype); 9800 9801 if (i % 5 == 4) 9802 p += scnprintf(p, end - p, "\n"); 9803 } 9804 9805 return p - buf; 9806 } 9807 9808 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9809 { 9810 struct rtw89_btc *btc = &rtwdev->btc; 9811 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9812 struct rtw89_btc_dm *dm = &btc->dm; 9813 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 9814 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 9815 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL; 9816 union rtw89_btc_fbtc_rxflct r; 9817 u16 cycle, c_begin, c_end, store_index; 9818 char *p = buf, *end = buf + bufsz; 9819 u8 i, cnt = 0, slot_pair; 9820 9821 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9822 if (!pcinfo->valid) 9823 return 0; 9824 9825 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2; 9826 p += scnprintf(p, end - p, 9827 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 9828 "[cycle_cnt]", 9829 le16_to_cpu(pcysta_le32->cycles), 9830 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]), 9831 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]), 9832 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]), 9833 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK])); 9834 9835 for (i = 0; i < CXST_MAX; i++) { 9836 if (!le32_to_cpu(pcysta_le32->slot_cnt[i])) 9837 continue; 9838 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i), 9839 le32_to_cpu(pcysta_le32->slot_cnt[i])); 9840 } 9841 9842 if (dm->tdma_now.rxflctrl) { 9843 p += scnprintf(p, end - p, ", leak_rx:%d", 9844 le32_to_cpu(pcysta_le32->leakrx_cnt)); 9845 } 9846 9847 if (le32_to_cpu(pcysta_le32->collision_cnt)) { 9848 p += scnprintf(p, end - p, ", collision:%d", 9849 le32_to_cpu(pcysta_le32->collision_cnt)); 9850 } 9851 9852 if (le32_to_cpu(pcysta_le32->skip_cnt)) { 9853 p += scnprintf(p, end - p, ", skip:%d", 9854 le32_to_cpu(pcysta_le32->skip_cnt)); 9855 } 9856 p += scnprintf(p, end - p, "\n"); 9857 9858 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9859 "[cycle_time]", 9860 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]), 9861 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]), 9862 le16_to_cpu(pcysta_le32->tavg_lk) / 1000, 9863 le16_to_cpu(pcysta_le32->tavg_lk) % 1000); 9864 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 9865 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]), 9866 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]), 9867 le16_to_cpu(pcysta_le32->tmax_lk) / 1000, 9868 le16_to_cpu(pcysta_le32->tmax_lk) % 1000); 9869 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n", 9870 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]), 9871 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT])); 9872 9873 if (le16_to_cpu(pcysta_le32->cycles) <= 1) 9874 goto out; 9875 9876 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 9877 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 9878 9879 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair) 9880 c_begin = 1; 9881 else 9882 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1; 9883 9884 c_end = le16_to_cpu(pcysta_le32->cycles); 9885 9886 for (cycle = c_begin; cycle <= c_end; cycle++) { 9887 cnt++; 9888 store_index = ((cycle - 1) % slot_pair) * 2; 9889 9890 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1) 9891 p += scnprintf(p, end - p, 9892 " %-15s : ->b%02d->w%02d", 9893 "[cycle_step]", 9894 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 9895 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 9896 else 9897 p += scnprintf(p, end - p, 9898 "->b%02d->w%02d", 9899 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]), 9900 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1])); 9901 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end) 9902 p += scnprintf(p, end - p, "\n"); 9903 } 9904 9905 if (a2dp->exist) { 9906 p += scnprintf(p, end - p, 9907 " %-15s : a2dp_ept:%d, a2dp_late:%d", 9908 "[a2dp_t_sta]", 9909 le16_to_cpu(pcysta_le32->a2dpept), 9910 le16_to_cpu(pcysta_le32->a2dpeptto)); 9911 9912 p += scnprintf(p, end - p, 9913 ", avg_t:%d, max_t:%d", 9914 le16_to_cpu(pcysta_le32->tavg_a2dpept), 9915 le16_to_cpu(pcysta_le32->tmax_a2dpept)); 9916 r.val = dm->tdma_now.rxflctrl; 9917 9918 if (r.type && r.tgln_n) { 9919 p += scnprintf(p, end - p, 9920 ", cycle[PSTDMA:%d/TDMA:%d], ", 9921 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]), 9922 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF])); 9923 9924 p += scnprintf(p, end - p, 9925 "avg_t[PSTDMA:%d/TDMA:%d], ", 9926 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]), 9927 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF])); 9928 9929 p += scnprintf(p, end - p, 9930 "max_t[PSTDMA:%d/TDMA:%d]", 9931 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]), 9932 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF])); 9933 } 9934 p += scnprintf(p, end - p, "\n"); 9935 } 9936 9937 out: 9938 return p - buf; 9939 } 9940 9941 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 9942 { 9943 struct rtw89_btc *btc = &rtwdev->btc; 9944 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 9945 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 9946 struct rtw89_btc_dm *dm = &btc->dm; 9947 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx; 9948 struct rtw89_btc_fbtc_cysta_v3 *pcysta; 9949 struct rtw89_btc_rpt_cmn_info *pcinfo; 9950 u8 i, cnt = 0, slot_pair, divide_cnt; 9951 u16 cycle, c_begin, c_end, store_index; 9952 char *p = buf, *end = buf + bufsz; 9953 9954 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 9955 if (!pcinfo->valid) 9956 return 0; 9957 9958 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3; 9959 p += scnprintf(p, end - p, 9960 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 9961 "[cycle_cnt]", 9962 le16_to_cpu(pcysta->cycles), 9963 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 9964 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 9965 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 9966 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 9967 9968 for (i = 0; i < CXST_MAX; i++) { 9969 if (!le32_to_cpu(pcysta->slot_cnt[i])) 9970 continue; 9971 9972 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 9973 le32_to_cpu(pcysta->slot_cnt[i])); 9974 } 9975 9976 if (dm->tdma_now.rxflctrl) 9977 p += scnprintf(p, end - p, ", leak_rx:%d", 9978 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 9979 9980 if (le32_to_cpu(pcysta->collision_cnt)) 9981 p += scnprintf(p, end - p, ", collision:%d", 9982 le32_to_cpu(pcysta->collision_cnt)); 9983 9984 if (le32_to_cpu(pcysta->skip_cnt)) 9985 p += scnprintf(p, end - p, ", skip:%d", 9986 le32_to_cpu(pcysta->skip_cnt)); 9987 9988 p += scnprintf(p, end - p, "\n"); 9989 9990 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 9991 "[cycle_time]", 9992 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 9993 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 9994 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 9995 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 9996 p += scnprintf(p, end - p, 9997 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 9998 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 9999 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 10000 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 10001 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 10002 p += scnprintf(p, end - p, 10003 ", maxdiff_t[wl:%d/bt:%d]\n", 10004 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 10005 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 10006 10007 cycle = le16_to_cpu(pcysta->cycles); 10008 if (cycle <= 1) 10009 goto out; 10010 10011 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 10012 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 10013 10014 if (cycle <= slot_pair) 10015 c_begin = 1; 10016 else 10017 c_begin = cycle - slot_pair + 1; 10018 10019 c_end = cycle; 10020 10021 if (a2dp->exist) 10022 divide_cnt = 3; 10023 else 10024 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 10025 10026 for (cycle = c_begin; cycle <= c_end; cycle++) { 10027 cnt++; 10028 store_index = ((cycle - 1) % slot_pair) * 2; 10029 10030 if (cnt % divide_cnt == 1) 10031 p += scnprintf(p, end - p, " %-15s : ", 10032 "[cycle_step]"); 10033 10034 p += scnprintf(p, end - p, "->b%02d", 10035 le16_to_cpu(pcysta->slot_step_time[store_index])); 10036 if (a2dp->exist) { 10037 a2dp_trx = &pcysta->a2dp_trx[store_index]; 10038 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 10039 a2dp_trx->empty_cnt, 10040 a2dp_trx->retry_cnt, 10041 a2dp_trx->tx_rate ? 3 : 2, 10042 a2dp_trx->tx_cnt, 10043 a2dp_trx->ack_cnt, 10044 a2dp_trx->nack_cnt); 10045 } 10046 p += scnprintf(p, end - p, "->w%02d", 10047 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 10048 if (a2dp->exist) { 10049 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 10050 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 10051 a2dp_trx->empty_cnt, 10052 a2dp_trx->retry_cnt, 10053 a2dp_trx->tx_rate ? 3 : 2, 10054 a2dp_trx->tx_cnt, 10055 a2dp_trx->ack_cnt, 10056 a2dp_trx->nack_cnt); 10057 } 10058 if (cnt % divide_cnt == 0 || cnt == c_end) 10059 p += scnprintf(p, end - p, "\n"); 10060 } 10061 10062 if (a2dp->exist) { 10063 p += scnprintf(p, end - p, 10064 " %-15s : a2dp_ept:%d, a2dp_late:%d", 10065 "[a2dp_t_sta]", 10066 le16_to_cpu(pcysta->a2dp_ept.cnt), 10067 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 10068 10069 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 10070 le16_to_cpu(pcysta->a2dp_ept.tavg), 10071 le16_to_cpu(pcysta->a2dp_ept.tmax)); 10072 10073 p += scnprintf(p, end - p, "\n"); 10074 } 10075 10076 out: 10077 return p - buf; 10078 } 10079 10080 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10081 { 10082 struct rtw89_btc *btc = &rtwdev->btc; 10083 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 10084 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10085 struct rtw89_btc_dm *dm = &btc->dm; 10086 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 10087 struct rtw89_btc_fbtc_cysta_v4 *pcysta; 10088 struct rtw89_btc_rpt_cmn_info *pcinfo; 10089 u8 i, cnt = 0, slot_pair, divide_cnt; 10090 u16 cycle, c_begin, c_end, store_index; 10091 char *p = buf, *end = buf + bufsz; 10092 10093 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 10094 if (!pcinfo->valid) 10095 return 0; 10096 10097 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4; 10098 p += scnprintf(p, end - p, 10099 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 10100 "[cycle_cnt]", 10101 le16_to_cpu(pcysta->cycles), 10102 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 10103 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 10104 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 10105 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 10106 10107 for (i = 0; i < CXST_MAX; i++) { 10108 if (!le16_to_cpu(pcysta->slot_cnt[i])) 10109 continue; 10110 10111 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 10112 le16_to_cpu(pcysta->slot_cnt[i])); 10113 } 10114 10115 if (dm->tdma_now.rxflctrl) 10116 p += scnprintf(p, end - p, ", leak_rx:%d", 10117 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 10118 10119 if (pcysta->collision_cnt) 10120 p += scnprintf(p, end - p, ", collision:%d", 10121 pcysta->collision_cnt); 10122 10123 if (le16_to_cpu(pcysta->skip_cnt)) 10124 p += scnprintf(p, end - p, ", skip:%d", 10125 le16_to_cpu(pcysta->skip_cnt)); 10126 10127 p += scnprintf(p, end - p, "\n"); 10128 10129 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 10130 "[cycle_time]", 10131 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 10132 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 10133 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 10134 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 10135 p += scnprintf(p, end - p, 10136 ", max_t[wl:%d/bt:%d/lk:%d.%03d]", 10137 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 10138 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 10139 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 10140 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 10141 p += scnprintf(p, end - p, 10142 ", maxdiff_t[wl:%d/bt:%d]\n", 10143 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]), 10144 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT])); 10145 10146 cycle = le16_to_cpu(pcysta->cycles); 10147 if (cycle <= 1) 10148 goto out; 10149 10150 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 10151 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 10152 10153 if (cycle <= slot_pair) 10154 c_begin = 1; 10155 else 10156 c_begin = cycle - slot_pair + 1; 10157 10158 c_end = cycle; 10159 10160 if (a2dp->exist) 10161 divide_cnt = 3; 10162 else 10163 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 10164 10165 for (cycle = c_begin; cycle <= c_end; cycle++) { 10166 cnt++; 10167 store_index = ((cycle - 1) % slot_pair) * 2; 10168 10169 if (cnt % divide_cnt == 1) 10170 p += scnprintf(p, end - p, " %-15s : ", 10171 "[cycle_step]"); 10172 10173 p += scnprintf(p, end - p, "->b%02d", 10174 le16_to_cpu(pcysta->slot_step_time[store_index])); 10175 if (a2dp->exist) { 10176 a2dp_trx = &pcysta->a2dp_trx[store_index]; 10177 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 10178 a2dp_trx->empty_cnt, 10179 a2dp_trx->retry_cnt, 10180 a2dp_trx->tx_rate ? 3 : 2, 10181 a2dp_trx->tx_cnt, 10182 a2dp_trx->ack_cnt, 10183 a2dp_trx->nack_cnt); 10184 } 10185 p += scnprintf(p, end - p, "->w%02d", 10186 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 10187 if (a2dp->exist) { 10188 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 10189 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 10190 a2dp_trx->empty_cnt, 10191 a2dp_trx->retry_cnt, 10192 a2dp_trx->tx_rate ? 3 : 2, 10193 a2dp_trx->tx_cnt, 10194 a2dp_trx->ack_cnt, 10195 a2dp_trx->nack_cnt); 10196 } 10197 if (cnt % divide_cnt == 0 || cnt == c_end) 10198 p += scnprintf(p, end - p, "\n"); 10199 } 10200 10201 if (a2dp->exist) { 10202 p += scnprintf(p, end - p, 10203 " %-15s : a2dp_ept:%d, a2dp_late:%d", 10204 "[a2dp_t_sta]", 10205 le16_to_cpu(pcysta->a2dp_ept.cnt), 10206 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 10207 10208 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 10209 le16_to_cpu(pcysta->a2dp_ept.tavg), 10210 le16_to_cpu(pcysta->a2dp_ept.tmax)); 10211 10212 p += scnprintf(p, end - p, "\n"); 10213 } 10214 10215 out: 10216 return p - buf; 10217 } 10218 10219 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10220 { 10221 struct rtw89_btc *btc = &rtwdev->btc; 10222 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc; 10223 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10224 struct rtw89_btc_dm *dm = &btc->dm; 10225 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx; 10226 struct rtw89_btc_fbtc_cysta_v5 *pcysta; 10227 struct rtw89_btc_rpt_cmn_info *pcinfo; 10228 u8 i, cnt = 0, slot_pair, divide_cnt; 10229 u16 cycle, c_begin, c_end, store_index; 10230 char *p = buf, *end = buf + bufsz; 10231 10232 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 10233 if (!pcinfo->valid) 10234 return 0; 10235 10236 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5; 10237 p += scnprintf(p, end - p, 10238 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]", 10239 "[cycle_cnt]", 10240 le16_to_cpu(pcysta->cycles), 10241 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 10242 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 10243 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 10244 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 10245 10246 for (i = 0; i < CXST_MAX; i++) { 10247 if (!le16_to_cpu(pcysta->slot_cnt[i])) 10248 continue; 10249 10250 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i), 10251 le16_to_cpu(pcysta->slot_cnt[i])); 10252 } 10253 10254 if (dm->tdma_now.rxflctrl) 10255 p += scnprintf(p, end - p, ", leak_rx:%d", 10256 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 10257 10258 if (pcysta->collision_cnt) 10259 p += scnprintf(p, end - p, ", collision:%d", 10260 pcysta->collision_cnt); 10261 10262 if (le16_to_cpu(pcysta->skip_cnt)) 10263 p += scnprintf(p, end - p, ", skip:%d", 10264 le16_to_cpu(pcysta->skip_cnt)); 10265 10266 p += scnprintf(p, end - p, "\n"); 10267 10268 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 10269 "[cycle_time]", 10270 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 10271 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 10272 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 10273 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 10274 p += scnprintf(p, end - p, 10275 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n", 10276 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 10277 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 10278 le16_to_cpu(pcysta->leak_slot.tmax) / 1000, 10279 le16_to_cpu(pcysta->leak_slot.tmax) % 1000); 10280 10281 cycle = le16_to_cpu(pcysta->cycles); 10282 if (cycle <= 1) 10283 goto out; 10284 10285 /* 1 cycle record 1 wl-slot and 1 bt-slot */ 10286 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 10287 10288 if (cycle <= slot_pair) 10289 c_begin = 1; 10290 else 10291 c_begin = cycle - slot_pair + 1; 10292 10293 c_end = cycle; 10294 10295 if (a2dp->exist) 10296 divide_cnt = 3; 10297 else 10298 divide_cnt = BTC_CYCLE_SLOT_MAX / 4; 10299 10300 if (c_begin > c_end) 10301 goto out; 10302 10303 for (cycle = c_begin; cycle <= c_end; cycle++) { 10304 cnt++; 10305 store_index = ((cycle - 1) % slot_pair) * 2; 10306 10307 if (cnt % divide_cnt == 1) 10308 p += scnprintf(p, end - p, " %-15s : ", 10309 "[cycle_step]"); 10310 10311 p += scnprintf(p, end - p, "->b%02d", 10312 le16_to_cpu(pcysta->slot_step_time[store_index])); 10313 if (a2dp->exist) { 10314 a2dp_trx = &pcysta->a2dp_trx[store_index]; 10315 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 10316 a2dp_trx->empty_cnt, 10317 a2dp_trx->retry_cnt, 10318 a2dp_trx->tx_rate ? 3 : 2, 10319 a2dp_trx->tx_cnt, 10320 a2dp_trx->ack_cnt, 10321 a2dp_trx->nack_cnt); 10322 } 10323 p += scnprintf(p, end - p, "->w%02d", 10324 le16_to_cpu(pcysta->slot_step_time[store_index + 1])); 10325 if (a2dp->exist) { 10326 a2dp_trx = &pcysta->a2dp_trx[store_index + 1]; 10327 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)", 10328 a2dp_trx->empty_cnt, 10329 a2dp_trx->retry_cnt, 10330 a2dp_trx->tx_rate ? 3 : 2, 10331 a2dp_trx->tx_cnt, 10332 a2dp_trx->ack_cnt, 10333 a2dp_trx->nack_cnt); 10334 } 10335 if (cnt % divide_cnt == 0 || cnt == c_end) 10336 p += scnprintf(p, end - p, "\n"); 10337 } 10338 10339 if (a2dp->exist) { 10340 p += scnprintf(p, end - p, 10341 " %-15s : a2dp_ept:%d, a2dp_late:%d", 10342 "[a2dp_t_sta]", 10343 le16_to_cpu(pcysta->a2dp_ept.cnt), 10344 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout)); 10345 10346 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 10347 le16_to_cpu(pcysta->a2dp_ept.tavg), 10348 le16_to_cpu(pcysta->a2dp_ept.tmax)); 10349 10350 p += scnprintf(p, end - p, "\n"); 10351 } 10352 10353 out: 10354 return p - buf; 10355 } 10356 10357 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10358 { 10359 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt; 10360 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc; 10361 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 10362 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL; 10363 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 10364 struct rtw89_btc_rpt_cmn_info *pcinfo; 10365 char *p = buf, *end = buf + bufsz; 10366 u16 cycle, c_begin, c_end, s_id; 10367 u8 i, cnt = 0, divide_cnt; 10368 u8 slot_pair; 10369 10370 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo; 10371 if (!pcinfo->valid) 10372 return 0; 10373 10374 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7; 10375 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]", 10376 le16_to_cpu(pcysta->cycles)); 10377 10378 for (i = 0; i < CXST_MAX; i++) { 10379 if (!le16_to_cpu(pcysta->slot_cnt[i])) 10380 continue; 10381 p += scnprintf(p, end - p, ", %s:%d", 10382 id_to_slot(i), 10383 le16_to_cpu(pcysta->slot_cnt[i])); 10384 } 10385 10386 if (dm->tdma_now.rxflctrl) 10387 p += scnprintf(p, end - p, ", leak_rx:%d", 10388 le32_to_cpu(pcysta->leak_slot.cnt_rximr)); 10389 10390 if (pcysta->collision_cnt) 10391 p += scnprintf(p, end - p, ", collision:%d", 10392 pcysta->collision_cnt); 10393 10394 if (pcysta->skip_cnt) 10395 p += scnprintf(p, end - p, ", skip:%d", 10396 le16_to_cpu(pcysta->skip_cnt)); 10397 10398 p += scnprintf(p, end - p, 10399 "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]", 10400 "[cycle_stat]", 10401 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]), 10402 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]), 10403 le16_to_cpu(pcysta->leak_slot.tavg) / 1000, 10404 le16_to_cpu(pcysta->leak_slot.tavg) % 1000); 10405 p += scnprintf(p, end - p, 10406 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]", 10407 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]), 10408 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]), 10409 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD], 10410 le16_to_cpu(pcysta->leak_slot.tamx) / 1000, 10411 le16_to_cpu(pcysta->leak_slot.tamx) % 1000); 10412 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]", 10413 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]), 10414 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]), 10415 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]), 10416 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK])); 10417 10418 if (a2dp->exist) { 10419 p += scnprintf(p, end - p, 10420 "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)", 10421 "[a2dp_stat]", 10422 le16_to_cpu(pcysta->a2dp_ept.cnt), 10423 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout), 10424 a2dp->no_empty_streak_2s, 10425 a2dp->no_empty_streak_max); 10426 10427 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d", 10428 le16_to_cpu(pcysta->a2dp_ept.tavg), 10429 le16_to_cpu(pcysta->a2dp_ept.tmax)); 10430 } 10431 10432 if (le16_to_cpu(pcysta->cycles) <= 1) 10433 goto out; 10434 10435 /* 1 cycle = 1 wl-slot + 1 bt-slot */ 10436 slot_pair = BTC_CYCLE_SLOT_MAX / 2; 10437 10438 if (le16_to_cpu(pcysta->cycles) <= slot_pair) 10439 c_begin = 1; 10440 else 10441 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1; 10442 10443 c_end = le16_to_cpu(pcysta->cycles); 10444 10445 if (a2dp->exist) 10446 divide_cnt = 2; 10447 else 10448 divide_cnt = 6; 10449 10450 if (c_begin > c_end) 10451 goto out; 10452 10453 for (cycle = c_begin; cycle <= c_end; cycle++) { 10454 cnt++; 10455 s_id = ((cycle - 1) % slot_pair) * 2; 10456 10457 if (cnt % divide_cnt == 1) { 10458 if (a2dp->exist) 10459 p += scnprintf(p, end - p, "\n\r %-15s : ", 10460 "[slotT_wermtan]"); 10461 else 10462 p += scnprintf(p, end - p, "\n\r %-15s : ", 10463 "[slotT_rxerr]"); 10464 } 10465 10466 p += scnprintf(p, end - p, "->b%d", 10467 le16_to_cpu(pcysta->slot_step_time[s_id])); 10468 10469 if (a2dp->exist) 10470 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 10471 pcysta->wl_rx_err_ratio[s_id], 10472 pcysta->a2dp_trx[s_id].empty_cnt, 10473 pcysta->a2dp_trx[s_id].retry_cnt, 10474 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2), 10475 pcysta->a2dp_trx[s_id].tx_cnt, 10476 pcysta->a2dp_trx[s_id].ack_cnt, 10477 pcysta->a2dp_trx[s_id].nack_cnt); 10478 else 10479 p += scnprintf(p, end - p, "(%d)", 10480 pcysta->wl_rx_err_ratio[s_id]); 10481 10482 p += scnprintf(p, end - p, "->w%d", 10483 le16_to_cpu(pcysta->slot_step_time[s_id + 1])); 10484 10485 if (a2dp->exist) 10486 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)", 10487 pcysta->wl_rx_err_ratio[s_id + 1], 10488 pcysta->a2dp_trx[s_id + 1].empty_cnt, 10489 pcysta->a2dp_trx[s_id + 1].retry_cnt, 10490 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2), 10491 pcysta->a2dp_trx[s_id + 1].tx_cnt, 10492 pcysta->a2dp_trx[s_id + 1].ack_cnt, 10493 pcysta->a2dp_trx[s_id + 1].nack_cnt); 10494 else 10495 p += scnprintf(p, end - p, "(%d)", 10496 pcysta->wl_rx_err_ratio[s_id + 1]); 10497 } 10498 10499 out: 10500 return p - buf; 10501 } 10502 10503 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10504 { 10505 struct rtw89_btc *btc = &rtwdev->btc; 10506 const struct rtw89_btc_ver *ver = btc->ver; 10507 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10508 struct rtw89_btc_rpt_cmn_info *pcinfo; 10509 union rtw89_btc_fbtc_cynullsta_info *ns; 10510 char *p = buf, *end = buf + bufsz; 10511 u8 i = 0; 10512 10513 if (!btc->dm.tdma_now.rxflctrl) 10514 return 0; 10515 10516 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo; 10517 if (!pcinfo->valid) 10518 return 0; 10519 10520 ns = &pfwinfo->rpt_fbtc_nullsta.finfo; 10521 if (ver->fcxnullsta == 1) { 10522 for (i = 0; i < 2; i++) { 10523 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); 10524 p += scnprintf(p, end - p, "null-%d", i); 10525 p += scnprintf(p, end - p, "[ok:%d/", 10526 le32_to_cpu(ns->v1.result[i][1])); 10527 p += scnprintf(p, end - p, "fail:%d/", 10528 le32_to_cpu(ns->v1.result[i][0])); 10529 p += scnprintf(p, end - p, "on_time:%d/", 10530 le32_to_cpu(ns->v1.result[i][2])); 10531 p += scnprintf(p, end - p, "retry:%d/", 10532 le32_to_cpu(ns->v1.result[i][3])); 10533 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 10534 le32_to_cpu(ns->v1.avg_t[i]) / 1000, 10535 le32_to_cpu(ns->v1.avg_t[i]) % 1000); 10536 p += scnprintf(p, end - p, "max_t:%d.%03d]", 10537 le32_to_cpu(ns->v1.max_t[i]) / 1000, 10538 le32_to_cpu(ns->v1.max_t[i]) % 1000); 10539 } 10540 } else if (ver->fcxnullsta == 7) { 10541 for (i = 0; i < 2; i++) { 10542 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); 10543 p += scnprintf(p, end - p, "null-%d", i); 10544 p += scnprintf(p, end - p, "[Tx:%d/", 10545 le32_to_cpu(ns->v7.result[i][4])); 10546 p += scnprintf(p, end - p, "[ok:%d/", 10547 le32_to_cpu(ns->v7.result[i][1])); 10548 p += scnprintf(p, end - p, "fail:%d/", 10549 le32_to_cpu(ns->v7.result[i][0])); 10550 p += scnprintf(p, end - p, "on_time:%d/", 10551 le32_to_cpu(ns->v7.result[i][2])); 10552 p += scnprintf(p, end - p, "retry:%d/", 10553 le32_to_cpu(ns->v7.result[i][3])); 10554 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 10555 le32_to_cpu(ns->v7.tavg[i]) / 1000, 10556 le32_to_cpu(ns->v7.tavg[i]) % 1000); 10557 p += scnprintf(p, end - p, "max_t:%d.%03d]", 10558 le32_to_cpu(ns->v7.tmax[i]) / 1000, 10559 le32_to_cpu(ns->v7.tmax[i]) % 1000); 10560 } 10561 } else { 10562 for (i = 0; i < 2; i++) { 10563 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]"); 10564 p += scnprintf(p, end - p, "null-%d", i); 10565 p += scnprintf(p, end - p, "[Tx:%d/", 10566 le32_to_cpu(ns->v2.result[i][4])); 10567 p += scnprintf(p, end - p, "[ok:%d/", 10568 le32_to_cpu(ns->v2.result[i][1])); 10569 p += scnprintf(p, end - p, "fail:%d/", 10570 le32_to_cpu(ns->v2.result[i][0])); 10571 p += scnprintf(p, end - p, "on_time:%d/", 10572 le32_to_cpu(ns->v2.result[i][2])); 10573 p += scnprintf(p, end - p, "retry:%d/", 10574 le32_to_cpu(ns->v2.result[i][3])); 10575 p += scnprintf(p, end - p, "avg_t:%d.%03d/", 10576 le32_to_cpu(ns->v2.avg_t[i]) / 1000, 10577 le32_to_cpu(ns->v2.avg_t[i]) % 1000); 10578 p += scnprintf(p, end - p, "max_t:%d.%03d]", 10579 le32_to_cpu(ns->v2.max_t[i]) / 1000, 10580 le32_to_cpu(ns->v2.max_t[i]) % 1000); 10581 } 10582 } 10583 10584 return p - buf; 10585 } 10586 10587 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10588 { 10589 struct rtw89_btc *btc = &rtwdev->btc; 10590 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10591 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10592 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL; 10593 const struct rtw89_btc_ver *ver = btc->ver; 10594 char *p = buf, *end = buf + bufsz; 10595 u8 type, val, cnt = 0, state = 0; 10596 bool outloop = false; 10597 u16 i, diff_t, n_start = 0, n_stop = 0; 10598 u16 pos_old, pos_new, trace_step; 10599 10600 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 10601 if (!pcinfo->valid) 10602 return 0; 10603 10604 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2; 10605 pos_old = le16_to_cpu(pstep->pos_old); 10606 pos_new = le16_to_cpu(pstep->pos_new); 10607 10608 if (pcinfo->req_fver != pstep->fver) 10609 return 0; 10610 10611 /* store step info by using ring instead of FIFO*/ 10612 do { 10613 switch (state) { 10614 case 0: 10615 if (ver->fcxctrl == 7 || ver->fcxctrl == 1) 10616 trace_step = 50; 10617 else 10618 trace_step = btc->ctrl.ctrl.trace_step; 10619 10620 n_start = pos_old; 10621 if (pos_new >= pos_old) 10622 n_stop = pos_new; 10623 else 10624 n_stop = trace_step - 1; 10625 10626 state = 1; 10627 break; 10628 case 1: 10629 for (i = n_start; i <= n_stop; i++) { 10630 type = pstep->step[i].type; 10631 val = pstep->step[i].val; 10632 diff_t = le16_to_cpu(pstep->step[i].difft); 10633 10634 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 10635 continue; 10636 10637 if (cnt % 10 == 0) 10638 p += scnprintf(p, end - p, 10639 " %-15s : ", "[steps]"); 10640 10641 p += scnprintf(p, end - p, 10642 "-> %s(%02d)(%02d)", 10643 (type == CXSTEP_SLOT ? "SLT" : 10644 "EVT"), (u32)val, diff_t); 10645 if (cnt % 10 == 9) 10646 p += scnprintf(p, end - p, "\n"); 10647 cnt++; 10648 } 10649 10650 state = 2; 10651 break; 10652 case 2: 10653 if (pos_new < pos_old && n_start != 0) { 10654 n_start = 0; 10655 n_stop = pos_new; 10656 state = 1; 10657 } else { 10658 outloop = true; 10659 } 10660 break; 10661 } 10662 } while (!outloop); 10663 10664 return p - buf; 10665 } 10666 10667 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10668 { 10669 struct rtw89_btc *btc = &rtwdev->btc; 10670 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10671 struct rtw89_btc_rpt_cmn_info *pcinfo; 10672 struct rtw89_btc_fbtc_steps_v3 *pstep; 10673 u32 i, n_begin, n_end, array_idx, cnt = 0; 10674 char *p = buf, *end = buf + bufsz; 10675 u8 type, val; 10676 u16 diff_t; 10677 10678 if ((pfwinfo->rpt_en_map & 10679 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0) 10680 return 0; 10681 10682 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo; 10683 if (!pcinfo->valid) 10684 return 0; 10685 10686 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3; 10687 if (pcinfo->req_fver != pstep->fver) 10688 return 0; 10689 10690 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP) 10691 n_begin = 1; 10692 else 10693 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1; 10694 10695 n_end = le32_to_cpu(pstep->cnt); 10696 10697 if (n_begin > n_end) 10698 return 0; 10699 10700 /* restore step info by using ring instead of FIFO */ 10701 for (i = n_begin; i <= n_end; i++) { 10702 array_idx = (i - 1) % FCXDEF_STEP; 10703 type = pstep->step[array_idx].type; 10704 val = pstep->step[array_idx].val; 10705 diff_t = le16_to_cpu(pstep->step[array_idx].difft); 10706 10707 if (type == CXSTEP_NONE || type >= CXSTEP_MAX) 10708 continue; 10709 10710 if (cnt % 10 == 0) 10711 p += scnprintf(p, end - p, " %-15s : ", "[steps]"); 10712 10713 p += scnprintf(p, end - p, "-> %s(%02d)", 10714 (type == CXSTEP_SLOT ? 10715 id_to_slot((u32)val) : 10716 id_to_evt((u32)val)), diff_t); 10717 10718 if (cnt % 10 == 9) 10719 p += scnprintf(p, end - p, "\n"); 10720 10721 cnt++; 10722 } 10723 10724 return p - buf; 10725 } 10726 10727 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10728 { 10729 struct rtw89_btc *btc = &rtwdev->btc; 10730 const struct rtw89_btc_ver *ver = btc->ver; 10731 char *p = buf, *end = buf + bufsz; 10732 10733 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM)) 10734 goto out; 10735 10736 p += _show_error(rtwdev, p, end - p); 10737 p += _show_fbtc_tdma(rtwdev, p, end - p); 10738 p += _show_fbtc_slots(rtwdev, p, end - p); 10739 10740 if (ver->fcxcysta == 2) 10741 p += _show_fbtc_cysta_v2(rtwdev, p, end - p); 10742 else if (ver->fcxcysta == 3) 10743 p += _show_fbtc_cysta_v3(rtwdev, p, end - p); 10744 else if (ver->fcxcysta == 4) 10745 p += _show_fbtc_cysta_v4(rtwdev, p, end - p); 10746 else if (ver->fcxcysta == 5) 10747 p += _show_fbtc_cysta_v5(rtwdev, p, end - p); 10748 else if (ver->fcxcysta == 7) 10749 p += _show_fbtc_cysta_v7(rtwdev, p, end - p); 10750 10751 p += _show_fbtc_nullsta(rtwdev, p, end - p); 10752 10753 if (ver->fcxstep == 2) 10754 p += _show_fbtc_step_v2(rtwdev, p, end - p); 10755 else if (ver->fcxstep == 3) 10756 p += _show_fbtc_step_v3(rtwdev, p, end - p); 10757 10758 out: 10759 return p - buf; 10760 } 10761 10762 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg) 10763 { 10764 const struct rtw89_chip_info *chip = rtwdev->chip; 10765 struct rtw89_mac_ax_gnt *gnt; 10766 u32 val, status; 10767 10768 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || 10769 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) { 10770 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val); 10771 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status); 10772 10773 gnt = &gnt_cfg->band[0]; 10774 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL); 10775 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA); 10776 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL); 10777 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA); 10778 10779 gnt = &gnt_cfg->band[1]; 10780 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL); 10781 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA); 10782 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL); 10783 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA); 10784 } else if (chip->chip_id == RTL8852C) { 10785 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL); 10786 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1); 10787 10788 gnt = &gnt_cfg->band[0]; 10789 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL); 10790 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0); 10791 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL); 10792 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0); 10793 10794 gnt = &gnt_cfg->band[1]; 10795 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL); 10796 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1); 10797 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL); 10798 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1); 10799 } else { 10800 return; 10801 } 10802 } 10803 10804 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10805 { 10806 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 10807 const struct rtw89_btc_ver *ver = rtwdev->btc.ver; 10808 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10809 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL; 10810 char *p = buf, *end = buf + bufsz; 10811 u8 *gpio_map, i; 10812 u32 en_map; 10813 10814 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo; 10815 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo; 10816 if (!pcinfo->valid) { 10817 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10818 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n", 10819 __func__); 10820 goto out; 10821 } 10822 10823 if (ver->fcxgpiodbg == 7) { 10824 en_map = le32_to_cpu(gdbg->v7.en_map); 10825 gpio_map = gdbg->v7.gpio_map; 10826 } else { 10827 en_map = le32_to_cpu(gdbg->v1.en_map); 10828 gpio_map = gdbg->v1.gpio_map; 10829 } 10830 10831 if (!en_map) 10832 goto out; 10833 10834 p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x", 10835 "[gpio_dbg]", en_map); 10836 10837 for (i = 0; i < BTC_DBG_MAX1; i++) { 10838 if (!(en_map & BIT(i))) 10839 continue; 10840 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i), 10841 gpio_map[i]); 10842 } 10843 p += scnprintf(p, end - p, "\n"); 10844 10845 out: 10846 return p - buf; 10847 } 10848 10849 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10850 { 10851 const struct rtw89_chip_info *chip = rtwdev->chip; 10852 struct rtw89_btc *btc = &rtwdev->btc; 10853 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10854 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10855 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL; 10856 struct rtw89_btc_cx *cx = &btc->cx; 10857 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10858 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 10859 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 10860 struct rtw89_mac_ax_gnt gnt; 10861 char *p = buf, *end = buf + bufsz; 10862 u8 i = 0, type = 0, cnt = 0; 10863 u32 val, offset; 10864 10865 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 10866 return 0; 10867 10868 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 10869 10870 p += scnprintf(p, end - p, 10871 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 10872 "[scoreboard]", wl->scbd, 10873 cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 10874 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 10875 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 10876 10877 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 10878 _get_gnt(rtwdev, &gnt_cfg); 10879 10880 gnt = gnt_cfg.band[0]; 10881 p += scnprintf(p, end - p, 10882 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ", 10883 "[gnt_status]", 10884 chip->chip_id == RTL8852C ? "HW" : 10885 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 10886 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 10887 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt); 10888 10889 gnt = gnt_cfg.band[1]; 10890 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 10891 gnt.gnt_wl_sw_en ? "SW" : "HW", 10892 gnt.gnt_wl, 10893 gnt.gnt_bt_sw_en ? "SW" : "HW", 10894 gnt.gnt_bt); 10895 10896 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 10897 if (!pcinfo->valid) { 10898 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10899 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 10900 __func__); 10901 goto out; 10902 } 10903 10904 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1; 10905 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10906 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 10907 __func__, pmreg->reg_num); 10908 10909 for (i = 0; i < pmreg->reg_num; i++) { 10910 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 10911 offset = le32_to_cpu(chip->mon_reg[i].offset); 10912 val = le32_to_cpu(pmreg->mreg_val[i]); 10913 10914 if (cnt % 6 == 0) 10915 p += scnprintf(p, end - p, 10916 " %-15s : %d_0x%04x=0x%08x", 10917 "[reg]", (u32)type, offset, val); 10918 else 10919 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 10920 (u32)type, 10921 offset, val); 10922 if (cnt % 6 == 5) 10923 p += scnprintf(p, end - p, "\n"); 10924 cnt++; 10925 10926 if (i >= pmreg->reg_num) 10927 p += scnprintf(p, end - p, "\n"); 10928 } 10929 10930 out: 10931 return p - buf; 10932 } 10933 10934 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 10935 { 10936 const struct rtw89_chip_info *chip = rtwdev->chip; 10937 struct rtw89_btc *btc = &rtwdev->btc; 10938 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 10939 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 10940 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL; 10941 struct rtw89_btc_cx *cx = &btc->cx; 10942 struct rtw89_btc_wl_info *wl = &btc->cx.wl; 10943 struct rtw89_btc_bt_info *bt = &btc->cx.bt; 10944 struct rtw89_mac_ax_coex_gnt gnt_cfg = {}; 10945 struct rtw89_mac_ax_gnt gnt; 10946 char *p = buf, *end = buf + bufsz; 10947 u8 i = 0, type = 0, cnt = 0; 10948 u32 val, offset; 10949 10950 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG)) 10951 return 0; 10952 10953 p += scnprintf(p, end - p, "========== [HW Status] ==========\n"); 10954 10955 p += scnprintf(p, end - p, 10956 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n", 10957 "[scoreboard]", wl->scbd, 10958 cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 10959 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 10960 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 10961 10962 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 10963 _get_gnt(rtwdev, &gnt_cfg); 10964 10965 gnt = gnt_cfg.band[0]; 10966 p += scnprintf(p, end - p, 10967 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s", 10968 "[gnt_status]", 10969 chip->chip_id == RTL8852C ? "HW" : 10970 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 10971 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl, 10972 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt, 10973 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 10974 10975 gnt = gnt_cfg.band[1]; 10976 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n", 10977 gnt.gnt_wl_sw_en ? "SW" : "HW", 10978 gnt.gnt_wl, 10979 gnt.gnt_bt_sw_en ? "SW" : "HW", 10980 gnt.gnt_bt); 10981 10982 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 10983 if (!pcinfo->valid) { 10984 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10985 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n", 10986 __func__); 10987 goto out; 10988 } 10989 10990 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2; 10991 rtw89_debug(rtwdev, RTW89_DBG_BTC, 10992 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n", 10993 __func__, pmreg->reg_num); 10994 10995 for (i = 0; i < pmreg->reg_num; i++) { 10996 type = (u8)le16_to_cpu(chip->mon_reg[i].type); 10997 offset = le32_to_cpu(chip->mon_reg[i].offset); 10998 val = le32_to_cpu(pmreg->mreg_val[i]); 10999 11000 if (cnt % 6 == 0) 11001 p += scnprintf(p, end - p, 11002 " %-15s : %d_0x%04x=0x%08x", 11003 "[reg]", (u32)type, offset, val); 11004 else 11005 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x", 11006 (u32)type, 11007 offset, val); 11008 if (cnt % 6 == 5) 11009 p += scnprintf(p, end - p, "\n"); 11010 cnt++; 11011 11012 if (i >= pmreg->reg_num) 11013 p += scnprintf(p, end - p, "\n"); 11014 } 11015 11016 out: 11017 return p - buf; 11018 } 11019 11020 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11021 { 11022 struct rtw89_btc *btc = &rtwdev->btc; 11023 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11024 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL; 11025 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11026 struct rtw89_btc_cx *cx = &btc->cx; 11027 struct rtw89_btc_wl_info *wl = &cx->wl; 11028 struct rtw89_btc_bt_info *bt = &cx->bt; 11029 struct rtw89_mac_ax_gnt *gnt = NULL; 11030 struct rtw89_btc_dm *dm = &btc->dm; 11031 char *p = buf, *end = buf + bufsz; 11032 u8 i, type, cnt = 0; 11033 u32 val, offset; 11034 11035 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG)) 11036 return 0; 11037 11038 p += scnprintf(p, end - p, "\n\r========== [HW Status] =========="); 11039 11040 p += scnprintf(p, end - p, 11041 "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)", 11042 "[scoreboard]", wl->scbd, 11043 cx->cnt_wl[BTC_WCNT_SCBDUPDATE], 11044 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD], 11045 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]); 11046 11047 /* To avoid I/O if WL LPS or power-off */ 11048 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev); 11049 11050 p += scnprintf(p, end - p, 11051 "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s", 11052 "[gnt_status]", 11053 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" : 11054 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT", 11055 wl->pta_req_mac, 11056 id_to_polut(wl->bt_polut_type[wl->pta_req_mac])); 11057 11058 gnt = &dm->gnt.band[RTW89_PHY_0]; 11059 11060 p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]", 11061 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl, 11062 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt); 11063 11064 if (rtwdev->dbcc_en) { 11065 gnt = &dm->gnt.band[RTW89_PHY_1]; 11066 p += scnprintf(p, end - p, 11067 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]", 11068 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl, 11069 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt); 11070 } 11071 11072 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo; 11073 if (!pcinfo->valid) 11074 goto out; 11075 11076 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7; 11077 11078 for (i = 0; i < pmreg->reg_num; i++) { 11079 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type); 11080 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset); 11081 val = le32_to_cpu(pmreg->mreg_val[i]); 11082 11083 if (cnt % 6 == 0) 11084 p += scnprintf(p, end - p, 11085 "\n\r %-15s : %s_0x%x=0x%x", "[reg]", 11086 id_to_regtype(type), offset, val); 11087 else 11088 p += scnprintf(p, end - p, ", %s_0x%x=0x%x", 11089 id_to_regtype(type), offset, val); 11090 cnt++; 11091 } 11092 11093 out: 11094 return p - buf; 11095 } 11096 11097 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11098 { 11099 struct rtw89_btc *btc = &rtwdev->btc; 11100 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11101 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11102 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL; 11103 struct rtw89_btc_cx *cx = &btc->cx; 11104 struct rtw89_btc_dm *dm = &btc->dm; 11105 struct rtw89_btc_wl_info *wl = &cx->wl; 11106 struct rtw89_btc_bt_info *bt = &cx->bt; 11107 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 11108 char *p = buf, *end = buf + bufsz; 11109 u8 i; 11110 11111 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11112 return 0; 11113 11114 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 11115 11116 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11117 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 11118 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1; 11119 11120 p += scnprintf(p, end - p, 11121 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 11122 "[summary]", pfwinfo->cnt_h2c, 11123 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt, 11124 pfwinfo->cnt_c2h, prptctrl->c2h_cnt); 11125 11126 p += scnprintf(p, end - p, 11127 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 11128 pfwinfo->event[BTF_EVNT_RPT], 11129 prptctrl->rpt_cnt, 11130 prptctrl->rpt_enable, dm->error.val); 11131 11132 if (dm->error.map.wl_fw_hang) 11133 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11134 p += scnprintf(p, end - p, "\n"); 11135 p += scnprintf(p, end - p, 11136 " %-15s : send_ok:%d, send_fail:%d, recv:%d", 11137 "[mailbox]", prptctrl->mb_send_ok_cnt, 11138 prptctrl->mb_send_fail_cnt, 11139 prptctrl->mb_recv_cnt); 11140 11141 p += scnprintf(p, end - p, 11142 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n", 11143 prptctrl->mb_a2dp_empty_cnt, 11144 prptctrl->mb_a2dp_flct_cnt, 11145 prptctrl->mb_a2dp_full_cnt); 11146 11147 p += scnprintf(p, end - p, 11148 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 11149 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11150 cx->cnt_wl[BTC_WCNT_RFK_GO], 11151 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11152 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 11153 11154 p += scnprintf(p, end - p, 11155 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 11156 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ], 11157 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO], 11158 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT], 11159 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT], 11160 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]); 11161 11162 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0) 11163 bt->rfk_info.map.timeout = 1; 11164 else 11165 bt->rfk_info.map.timeout = 0; 11166 11167 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 11168 } else { 11169 p += scnprintf(p, end - p, 11170 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 11171 "[summary]", pfwinfo->cnt_h2c, 11172 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 11173 pfwinfo->event[BTF_EVNT_RPT], 11174 btc->fwinfo.rpt_en_map); 11175 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 11176 } 11177 11178 for (i = 0; i < BTC_NCNT_NUM; i++) 11179 cnt_sum += dm->cnt_notify[i]; 11180 11181 p += scnprintf(p, end - p, 11182 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11183 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11184 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11185 11186 p += scnprintf(p, end - p, 11187 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 11188 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11189 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11190 cnt[BTC_NCNT_WL_STA]); 11191 11192 p += scnprintf(p, end - p, 11193 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 11194 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 11195 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 11196 cnt[BTC_NCNT_SPECIAL_PACKET]); 11197 11198 p += scnprintf(p, end - p, 11199 "timer=%d, control=%d, customerize=%d\n", 11200 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 11201 cnt[BTC_NCNT_CUSTOMERIZE]); 11202 11203 return p - buf; 11204 } 11205 11206 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11207 { 11208 struct rtw89_btc *btc = &rtwdev->btc; 11209 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11210 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl; 11211 struct rtw89_btc_rpt_cmn_info *pcinfo; 11212 struct rtw89_btc_cx *cx = &btc->cx; 11213 struct rtw89_btc_dm *dm = &btc->dm; 11214 struct rtw89_btc_wl_info *wl = &cx->wl; 11215 struct rtw89_btc_bt_info *bt = &cx->bt; 11216 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 11217 char *p = buf, *end = buf + bufsz; 11218 u8 i; 11219 11220 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11221 return 0; 11222 11223 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 11224 11225 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11226 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 11227 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4; 11228 11229 p += scnprintf(p, end - p, 11230 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ", 11231 "[summary]", pfwinfo->cnt_h2c, 11232 pfwinfo->cnt_h2c_fail, 11233 le32_to_cpu(prptctrl->rpt_info.cnt_h2c), 11234 pfwinfo->cnt_c2h, 11235 le32_to_cpu(prptctrl->rpt_info.cnt_c2h)); 11236 11237 p += scnprintf(p, end - p, 11238 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x", 11239 pfwinfo->event[BTF_EVNT_RPT], 11240 le32_to_cpu(prptctrl->rpt_info.cnt), 11241 le32_to_cpu(prptctrl->rpt_info.en), 11242 dm->error.val); 11243 11244 if (dm->error.map.wl_fw_hang) 11245 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11246 p += scnprintf(p, end - p, "\n"); 11247 p += scnprintf(p, end - p, 11248 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 11249 "[mailbox]", 11250 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 11251 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 11252 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 11253 11254 p += scnprintf(p, end - p, 11255 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 11256 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 11257 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 11258 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 11259 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 11260 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 11261 11262 p += scnprintf(p, end - p, 11263 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]", 11264 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11265 cx->cnt_wl[BTC_WCNT_RFK_GO], 11266 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11267 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 11268 11269 p += scnprintf(p, end - p, 11270 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n", 11271 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]), 11272 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]), 11273 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]), 11274 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]), 11275 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL])); 11276 11277 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0) 11278 bt->rfk_info.map.timeout = 1; 11279 else 11280 bt->rfk_info.map.timeout = 0; 11281 11282 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout; 11283 } else { 11284 p += scnprintf(p, end - p, 11285 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x", 11286 "[summary]", pfwinfo->cnt_h2c, 11287 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h, 11288 pfwinfo->event[BTF_EVNT_RPT], 11289 btc->fwinfo.rpt_en_map); 11290 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n"); 11291 } 11292 11293 for (i = 0; i < BTC_NCNT_NUM; i++) 11294 cnt_sum += dm->cnt_notify[i]; 11295 11296 p += scnprintf(p, end - p, 11297 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11298 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11299 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11300 11301 p += scnprintf(p, end - p, 11302 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n", 11303 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11304 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11305 cnt[BTC_NCNT_WL_STA]); 11306 11307 p += scnprintf(p, end - p, 11308 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 11309 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START], 11310 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND], 11311 cnt[BTC_NCNT_SPECIAL_PACKET]); 11312 11313 p += scnprintf(p, end - p, 11314 "timer=%d, control=%d, customerize=%d\n", 11315 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 11316 cnt[BTC_NCNT_CUSTOMERIZE]); 11317 11318 return p - buf; 11319 } 11320 11321 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11322 { 11323 struct rtw89_btc *btc = &rtwdev->btc; 11324 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11325 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl; 11326 struct rtw89_btc_rpt_cmn_info *pcinfo; 11327 struct rtw89_btc_cx *cx = &btc->cx; 11328 struct rtw89_btc_dm *dm = &btc->dm; 11329 struct rtw89_btc_wl_info *wl = &cx->wl; 11330 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 11331 char *p = buf, *end = buf + bufsz; 11332 u8 i; 11333 11334 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11335 return 0; 11336 11337 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 11338 11339 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11340 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 11341 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5; 11342 11343 p += scnprintf(p, end - p, 11344 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 11345 "[summary]", pfwinfo->cnt_h2c, 11346 pfwinfo->cnt_h2c_fail, 11347 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 11348 pfwinfo->cnt_c2h, 11349 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 11350 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 11351 11352 p += scnprintf(p, end - p, 11353 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 11354 pfwinfo->event[BTF_EVNT_RPT], 11355 le16_to_cpu(prptctrl->rpt_info.cnt), 11356 le32_to_cpu(prptctrl->rpt_info.en)); 11357 11358 if (dm->error.map.wl_fw_hang) 11359 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11360 p += scnprintf(p, end - p, "\n"); 11361 p += scnprintf(p, end - p, 11362 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 11363 "[mailbox]", 11364 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 11365 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 11366 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 11367 11368 p += scnprintf(p, end - p, 11369 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 11370 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 11371 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 11372 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 11373 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 11374 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 11375 11376 p += scnprintf(p, end - p, 11377 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 11378 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11379 cx->cnt_wl[BTC_WCNT_RFK_GO], 11380 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11381 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 11382 11383 p += scnprintf(p, end - p, 11384 ", bt_rfk[req:%d]", 11385 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 11386 11387 p += scnprintf(p, end - p, 11388 ", AOAC[RF_on:%d/RF_off:%d]", 11389 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 11390 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 11391 } else { 11392 p += scnprintf(p, end - p, 11393 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 11394 "[summary]", pfwinfo->cnt_h2c, 11395 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 11396 } 11397 11398 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 11399 pfwinfo->err[BTFRE_EXCEPTION]) { 11400 p += scnprintf(p, end - p, "\n"); 11401 p += scnprintf(p, end - p, 11402 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 11403 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 11404 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 11405 pfwinfo->fver_mismch, 11406 pfwinfo->err[BTFRE_EXCEPTION], 11407 wl->status.map.lps, wl->status.map.rf_off); 11408 } 11409 11410 for (i = 0; i < BTC_NCNT_NUM; i++) 11411 cnt_sum += dm->cnt_notify[i]; 11412 11413 p += scnprintf(p, end - p, "\n"); 11414 p += scnprintf(p, end - p, 11415 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11416 "[notify_cnt]", 11417 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11418 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11419 11420 p += scnprintf(p, end - p, 11421 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 11422 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11423 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11424 cnt[BTC_NCNT_WL_STA]); 11425 11426 p += scnprintf(p, end - p, "\n"); 11427 p += scnprintf(p, end - p, 11428 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 11429 "[notify_cnt]", 11430 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 11431 cnt[BTC_NCNT_SWITCH_BAND], 11432 cnt[BTC_NCNT_SPECIAL_PACKET]); 11433 11434 p += scnprintf(p, end - p, 11435 "timer=%d, control=%d, customerize=%d", 11436 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 11437 cnt[BTC_NCNT_CUSTOMERIZE]); 11438 11439 return p - buf; 11440 } 11441 11442 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11443 { 11444 struct rtw89_btc *btc = &rtwdev->btc; 11445 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo; 11446 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl; 11447 struct rtw89_btc_rpt_cmn_info *pcinfo; 11448 struct rtw89_btc_cx *cx = &btc->cx; 11449 struct rtw89_btc_dm *dm = &btc->dm; 11450 struct rtw89_btc_wl_info *wl = &cx->wl; 11451 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify; 11452 char *p = buf, *end = buf + bufsz; 11453 u8 i; 11454 11455 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11456 return 0; 11457 11458 p += scnprintf(p, end - p, "========== [Statistics] ==========\n"); 11459 11460 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11461 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) { 11462 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105; 11463 11464 p += scnprintf(p, end - p, 11465 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ", 11466 "[summary]", pfwinfo->cnt_h2c, 11467 pfwinfo->cnt_h2c_fail, 11468 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 11469 pfwinfo->cnt_c2h, 11470 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 11471 le16_to_cpu(prptctrl->rpt_info.len_c2h)); 11472 11473 p += scnprintf(p, end - p, 11474 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 11475 pfwinfo->event[BTF_EVNT_RPT], 11476 le16_to_cpu(prptctrl->rpt_info.cnt), 11477 le32_to_cpu(prptctrl->rpt_info.en)); 11478 11479 if (dm->error.map.wl_fw_hang) 11480 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11481 p += scnprintf(p, end - p, "\n"); 11482 p += scnprintf(p, end - p, 11483 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 11484 "[mailbox]", 11485 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 11486 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 11487 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 11488 11489 p += scnprintf(p, end - p, 11490 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n", 11491 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 11492 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 11493 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 11494 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 11495 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 11496 11497 p += scnprintf(p, end - p, 11498 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]", 11499 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11500 cx->cnt_wl[BTC_WCNT_RFK_GO], 11501 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11502 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]); 11503 11504 p += scnprintf(p, end - p, 11505 ", bt_rfk[req:%d]", 11506 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 11507 11508 p += scnprintf(p, end - p, 11509 ", AOAC[RF_on:%d/RF_off:%d]", 11510 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 11511 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 11512 } else { 11513 p += scnprintf(p, end - p, 11514 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d", 11515 "[summary]", pfwinfo->cnt_h2c, 11516 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h); 11517 } 11518 11519 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch || 11520 pfwinfo->err[BTFRE_EXCEPTION]) { 11521 p += scnprintf(p, end - p, "\n"); 11522 p += scnprintf(p, end - p, 11523 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:" 11524 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]", 11525 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch, 11526 pfwinfo->fver_mismch, 11527 pfwinfo->err[BTFRE_EXCEPTION], 11528 wl->status.map.lps, wl->status.map.rf_off); 11529 } 11530 11531 for (i = 0; i < BTC_NCNT_NUM; i++) 11532 cnt_sum += dm->cnt_notify[i]; 11533 11534 p += scnprintf(p, end - p, "\n"); 11535 p += scnprintf(p, end - p, 11536 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11537 "[notify_cnt]", 11538 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11539 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11540 11541 p += scnprintf(p, end - p, 11542 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 11543 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11544 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11545 cnt[BTC_NCNT_WL_STA]); 11546 11547 p += scnprintf(p, end - p, "\n"); 11548 p += scnprintf(p, end - p, 11549 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ", 11550 "[notify_cnt]", 11551 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 11552 cnt[BTC_NCNT_SWITCH_BAND], 11553 cnt[BTC_NCNT_SPECIAL_PACKET]); 11554 11555 p += scnprintf(p, end - p, 11556 "timer=%d, control=%d, customerize=%d", 11557 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL], 11558 cnt[BTC_NCNT_CUSTOMERIZE]); 11559 11560 return p - buf; 11561 } 11562 11563 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11564 { 11565 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 11566 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL; 11567 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11568 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 11569 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 11570 struct rtw89_btc_wl_info *wl = &cx->wl; 11571 u32 *cnt = rtwdev->btc.dm.cnt_notify; 11572 char *p = buf, *end = buf + bufsz; 11573 u32 cnt_sum = 0; 11574 u8 i; 11575 11576 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11577 return 0; 11578 11579 p += scnprintf(p, end - p, "%s", 11580 "\n\r========== [Statistics] =========="); 11581 11582 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11583 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 11584 !wl->status.map.rf_off) { 11585 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7; 11586 11587 p += scnprintf(p, end - p, 11588 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d)," 11589 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ", 11590 "[summary]", pfwinfo->cnt_h2c, 11591 pfwinfo->cnt_h2c_fail, 11592 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 11593 pfwinfo->cnt_c2h, 11594 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 11595 le16_to_cpu(prptctrl->rpt_info.len_c2h), 11596 rtwdev->btc.ver->info_buf); 11597 11598 p += scnprintf(p, end - p, 11599 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 11600 pfwinfo->event[BTF_EVNT_RPT], 11601 le16_to_cpu(prptctrl->rpt_info.cnt), 11602 le32_to_cpu(prptctrl->rpt_info.en)); 11603 11604 if (dm->error.map.wl_fw_hang) 11605 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11606 11607 p += scnprintf(p, end - p, 11608 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 11609 "[mailbox]", 11610 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 11611 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 11612 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 11613 11614 p += scnprintf(p, end - p, 11615 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", 11616 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 11617 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 11618 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 11619 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 11620 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 11621 11622 p += scnprintf(p, end - p, 11623 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 11624 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11625 cx->cnt_wl[BTC_WCNT_RFK_GO], 11626 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11627 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT], 11628 wl->rfk_info.proc_time); 11629 11630 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 11631 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 11632 11633 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", 11634 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 11635 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 11636 } else { 11637 p += scnprintf(p, end - p, 11638 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", 11639 "[summary]", 11640 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 11641 pfwinfo->cnt_c2h, 11642 wl->status.map.lps, wl->status.map.rf_off); 11643 } 11644 11645 for (i = 0; i < BTC_NCNT_NUM; i++) 11646 cnt_sum += dm->cnt_notify[i]; 11647 11648 p += scnprintf(p, end - p, 11649 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11650 "[notify_cnt]", 11651 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11652 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11653 11654 p += scnprintf(p, end - p, 11655 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 11656 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11657 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11658 cnt[BTC_NCNT_WL_STA]); 11659 11660 p += scnprintf(p, end - p, 11661 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 11662 "[notify_cnt]", 11663 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 11664 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 11665 cnt[BTC_NCNT_SPECIAL_PACKET]); 11666 11667 p += scnprintf(p, end - p, 11668 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 11669 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 11670 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 11671 cnt[BTC_NCNT_COUNTRYCODE]); 11672 11673 return p - buf; 11674 } 11675 11676 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11677 { 11678 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo; 11679 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL; 11680 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL; 11681 struct rtw89_btc_cx *cx = &rtwdev->btc.cx; 11682 struct rtw89_btc_dm *dm = &rtwdev->btc.dm; 11683 struct rtw89_btc_wl_info *wl = &cx->wl; 11684 u32 *cnt = rtwdev->btc.dm.cnt_notify; 11685 char *p = buf, *end = buf + bufsz; 11686 u32 cnt_sum = 0; 11687 u8 i; 11688 11689 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY)) 11690 return 0; 11691 11692 p += scnprintf(p, end - p, "%s", 11693 "\n\r========== [Statistics] =========="); 11694 11695 pcinfo = &pfwinfo->rpt_ctrl.cinfo; 11696 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF && 11697 !wl->status.map.rf_off) { 11698 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8; 11699 11700 p += scnprintf(p, end - p, 11701 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ", 11702 "[summary]", pfwinfo->cnt_h2c, 11703 pfwinfo->cnt_h2c_fail, 11704 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), 11705 pfwinfo->cnt_c2h, 11706 le16_to_cpu(prptctrl->rpt_info.cnt_c2h), 11707 le16_to_cpu(prptctrl->rpt_info.len_c2h), 11708 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l, 11709 rtwdev->btc.ver->info_buf); 11710 11711 p += scnprintf(p, end - p, 11712 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x", 11713 pfwinfo->event[BTF_EVNT_RPT], 11714 le16_to_cpu(prptctrl->rpt_info.cnt), 11715 le32_to_cpu(prptctrl->rpt_info.en)); 11716 11717 if (dm->error.map.wl_fw_hang) 11718 p += scnprintf(p, end - p, " (WL FW Hang!!)"); 11719 11720 p += scnprintf(p, end - p, 11721 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ", 11722 "[mailbox]", 11723 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok), 11724 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail), 11725 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv)); 11726 11727 p += scnprintf(p, end - p, 11728 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)", 11729 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty), 11730 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl), 11731 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx), 11732 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack), 11733 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack)); 11734 11735 p += scnprintf(p, end - p, 11736 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]", 11737 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ], 11738 cx->cnt_wl[BTC_WCNT_RFK_GO], 11739 cx->cnt_wl[BTC_WCNT_RFK_REJECT], 11740 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT], 11741 wl->rfk_info.proc_time); 11742 11743 p += scnprintf(p, end - p, ", bt_rfk[req:%d]", 11744 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ])); 11745 11746 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]", 11747 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on), 11748 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off)); 11749 } else { 11750 p += scnprintf(p, end - p, 11751 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)", 11752 "[summary]", 11753 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail, 11754 pfwinfo->cnt_c2h, 11755 wl->status.map.lps, wl->status.map.rf_off); 11756 } 11757 11758 for (i = 0; i < BTC_NCNT_NUM; i++) 11759 cnt_sum += dm->cnt_notify[i]; 11760 11761 p += scnprintf(p, end - p, 11762 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ", 11763 "[notify_cnt]", 11764 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO], 11765 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]); 11766 11767 p += scnprintf(p, end - p, 11768 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d", 11769 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE], 11770 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK], 11771 cnt[BTC_NCNT_WL_STA]); 11772 11773 p += scnprintf(p, end - p, 11774 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ", 11775 "[notify_cnt]", 11776 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH], 11777 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW], 11778 cnt[BTC_NCNT_SPECIAL_PACKET]); 11779 11780 p += scnprintf(p, end - p, 11781 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d", 11782 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE], 11783 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW], 11784 cnt[BTC_NCNT_COUNTRYCODE]); 11785 11786 return p - buf; 11787 } 11788 11789 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 11790 { 11791 struct rtw89_btc *btc = &rtwdev->btc; 11792 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver; 11793 const struct rtw89_btc_ver *ver = btc->ver; 11794 struct rtw89_btc_dm *dm = &btc->dm; 11795 char *p = buf, *end = buf + bufsz; 11796 11797 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++; 11798 11799 p += scnprintf(p, end - p, 11800 "\n\n\n** Page:%3d/RunCNT:%3d **", 11801 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO], 11802 dm->cnt_dm[BTC_DCNT_RUN]); 11803 p += scnprintf(p, end - p, 11804 "\n========== [BTC FEATURE SUB VER] =========="); 11805 p += scnprintf(p, end - p, 11806 "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]", 11807 "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt, 11808 fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots, 11809 ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta); 11810 p += scnprintf(p, end - p, 11811 "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]", 11812 "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep, 11813 fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg, 11814 ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg); 11815 p += scnprintf(p, end - p, 11816 "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]", 11817 "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver, 11818 fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh, 11819 ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo); 11820 p += scnprintf(p, end - p, 11821 "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],", 11822 "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi, 11823 fwsubver->fcxmlo, ver->fcxmlo); 11824 11825 p += _show_cx_info(rtwdev, p, end - p); 11826 p += _show_wl_info(rtwdev, p, end - p); 11827 p += _show_bt_info(rtwdev, p, end - p); 11828 p += _show_dm_info(rtwdev, p, end - p); 11829 p += _show_fw_dm_msg(rtwdev, p, end - p); 11830 11831 if (ver->fcxmreg == 1) 11832 p += _show_mreg_v1(rtwdev, p, end - p); 11833 else if (ver->fcxmreg == 2) 11834 p += _show_mreg_v2(rtwdev, p, end - p); 11835 else if (ver->fcxmreg == 7) 11836 p += _show_mreg_v7(rtwdev, p, end - p); 11837 11838 p += _show_gpio_dbg(rtwdev, p, end - p); 11839 11840 if (ver->fcxbtcrpt == 1) 11841 p += _show_summary_v1(rtwdev, p, end - p); 11842 else if (ver->fcxbtcrpt == 4) 11843 p += _show_summary_v4(rtwdev, p, end - p); 11844 else if (ver->fcxbtcrpt == 5) 11845 p += _show_summary_v5(rtwdev, p, end - p); 11846 else if (ver->fcxbtcrpt == 105) 11847 p += _show_summary_v105(rtwdev, p, end - p); 11848 else if (ver->fcxbtcrpt == 7) 11849 p += _show_summary_v7(rtwdev, p, end - p); 11850 else if (ver->fcxbtcrpt == 8) 11851 p += _show_summary_v8(rtwdev, p, end - p); 11852 11853 return p - buf; 11854 } 11855 11856 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) 11857 { 11858 const struct rtw89_chip_info *chip = rtwdev->chip; 11859 struct rtw89_btc *btc = &rtwdev->btc; 11860 const struct rtw89_btc_ver *btc_ver_def; 11861 const struct rtw89_fw_suit *fw_suit; 11862 u32 suit_ver_code; 11863 int i; 11864 11865 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL); 11866 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit); 11867 11868 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) { 11869 btc_ver_def = &rtw89_btc_ver_defs[i]; 11870 11871 if (chip->chip_id != btc_ver_def->chip_id) 11872 continue; 11873 11874 if (suit_ver_code >= btc_ver_def->fw_ver_code) { 11875 btc->ver = btc_ver_def; 11876 goto out; 11877 } 11878 } 11879 11880 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX]; 11881 11882 out: 11883 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", 11884 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); 11885 } 11886 11887 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms) 11888 { 11889 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info; 11890 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; 11891 11892 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) 11893 return; 11894 11895 if (!a2dp.exist) 11896 return; 11897 11898 fsleep(ms * 1000); 11899 } 11900 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time); 11901 11902 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state) 11903 { 11904 rtwdev->btc.cx.wl.rfk_info.con_rfk = state; 11905 } 11906 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk); 11907